5.1 Spring MVC starts
5.1.1 Tracking requests from spring MVC
Every time a user clicks a link or submits a form in a Web browser, the request begins to work. The job description of the request is like a courier delivery agent. Like a post office couriers or FedEx delivery officer, the request takes information from one place to another.
① when the request leaves the browser, with information about what the user has requested, such as the form information submitted by the user.
The first stop of the request journey is spring's front-end controller Dispatcherservlet, where a single-instance servlet will request a delegate to other components of the application to perform the actual processing.
Dispatcherservlet's task is to send the request to the Spring MVC controller. Dispatcherservlet queries one or more processor mappings (handler mapping) ② to determine which controller the request should send the request to. The processor map makes decisions based on the URL information that is carried by the request.
Once the appropriate controller is selected, Dispatcherservlet sends the request to the selected controller. To the controller ③, the request unloads its payload (user-submitted information) and waits patiently for the controller to process the information. (In fact, the well-designed controller itself deals with little or no work, but instead delegates the business logic to one or more service objects for processing.) )
After the controller completes the logic processing, it usually generates some information that needs to be returned to the user and displayed on the browser. This information is called the model. But it is not enough to simply return the original information to the user-the information needs to be formatted in a user-friendly way, usually HTML. Therefore, the information needs to be sent to a view, usually a JSP.
The last thing the controller does is package the model data and mark the name of the view used to render the output. It then sends the request back to Dispatcherservlet④, along with the model and view name.
This way, the controller is not coupled to a particular view, and the view name passed to Dispatcherservlet does not directly represent a particular JSP. In fact, it is not even certain that the view is a JSP. Instead, it simply passes a logical name that will be used to find the real view that produces the result. Dispatcherservlet will use the view resolver ⑤ to match the logical view name to a specific view implementation, which may or may not be a JSP. Since Dispatcherservlet already knows which view renders the results, the requested task is basically complete. Its last stop is the implementation of the view (possibly JSP) ⑥, where it delivers model data. The requested task is complete. The view will render the output using model data, which is passed to the client through the response object (not as hard-coded as it sounds) ⑦.
As you can see, the request takes a lot of steps to eventually form a response back to the client. Most of the steps are done inside the spring framework, which is the component shown in Figure 5.1. While the main focus of this chapter is on how to write a controller, let's start by looking at how to build the basic components of spring MVC.
5.1.2 Building Spring MVC
Based on Figure 5.1, it looks like we need to configure a lot of components. Fortunately, with the enhancements of recent spring releases, it is easy to get started with spring MVC. Now, we're going to use the simplest way to configure Spring MVC: The functionality to be implemented is limited to running the controller we created. In the 7th chapter, we will look at some other configuration options.
Configure Dispatcherservlet
Dispatcherservlet is at the heart of spring MVC. Here the request is first exposed to the framework, which is responsible for routing the request to other components. In the traditional way, a servlet like Dispatcherservlet is configured in the Web. xml file, which is placed in the application's war package. Of course, this is one of the ways to configure Dispatcherservlet.
However, this approach is not the only option with the help of the Servlet 3 specification and the feature enhancements of Spring 3.1, which is not the configuration method we used in this chapter. We will use Java to configure Dispatcherservlet in the servlet container without using the Web. xml file. The following list of programs shows the required Java classes.
Program Listing 5.1 Configuration Dispatcherservlet
PackageSpittr.config;ImportOrg.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; Public classSpittrwebappinitializerextendsAbstractannotationconfigdispatcherservletinitializer {@Overrideprotectedstring[] Getservletmappings () {return NewString[] {"/"};//map Dispatcherservlet to "/"} @OverrideprotectedClass<?>[] getrootconfigclasses () {return NewClass<?>[] {rootconfig.class }; } @OverrideprotectedClass<?>[] getservletconfigclasses () {return NewClass<?>[] {webconfig.class};//specifying a configuration class }}
In program listing 5.1, Spittrwebappinitializer overrides three methods.
The first method is Getservletmappings (), which maps one or more paths to dispatcherservlet. In this case, it maps "/", which means it will be the default servlet for the app. It handles all requests that go into the app.
To understand the other two methods, we first need to understand the relationship between Dispatcherservlet and a servlet listener (that is, Contextloaderlistener).
When Dispatcherservlet is started, it creates a spring application context and loads the beans declared in the configuration file or configuration class. In the Getservletconfigclasses () method of listing 5.1, we require Dispatcherservlet to load the application context using beans defined in the Webconfig configuration class (using Java configuration).
But in spring web apps, there's usually another application context. The other application context is created by Contextloaderlistener.
We want Dispatcherservlet to load the beans that contain the Web components, such as the controller, view resolver, and processor mappings, and Contextloaderlistener to load the other beans in the app. These beans are typically the middle-tier and data-tier components that drive the backend.
In fact, Abstractannotationconfigdispatcherservletinitializer will create both Dispatcherservlet and Contextloaderlistener. The class with @configuration annotations returned by the Getservletconfigclasses () method will be used to define the bean in the Dispatcherservlet application context. The class with @configuration annotations returned by the Getrootconfigclasses () method will be used to configure the bean in the context of the app Contextloaderlistener created.
Enable Spring MVC
Just as there are several ways to configure Dispatcherservlet, there are more than one way to activate the Spring MVC component. Typically, spring is configured through an XML configuration file, for example by <mvc:annotation-driven> to activate annotation-based spring MVC.
The simplest spring MVC configuration We can create is a class with @enablewebmvc annotations:
Package Spittr.config; Import org.springframework.context.annotation.Configuration; Import ORG.SPRINGFRAMEWORK.WEB.SERVLET.CONFIG.ANNOTATION.ENABLEWEBMVC, @Configuration @enablewebmvc Public class Webconfig {}
This can work, and it does enable spring MVC, but there are a number of issues to be resolved:
The view resolver is not configured. If so, Spring uses beannameview-resolver by default, and the view parser looks for the bean whose ID matches the view name, and the bean to be found to implement the View interface, which parses the view in such a way.
Component scanning is not enabled. The result is that spring can only find controllers that are explicitly declared in the configuration class.
With this configuration, Dispatcherservlet maps to the app's default servlet, so it handles all requests, including requests for static resources, slices, and style sheets (which in most cases may not be the effect you want).
So we need to add something to the smallest spring MVC configuration on webconfig to make it really useful. The webconfig in the following list of programs resolves the problem described above.
Program Listing 5.2 The smallest but available spring MVC configuration
PackageSpittr.config;ImportOrg.springframework.context.annotation.Bean;ImportOrg.springframework.context.annotation.ComponentScan;Importorg.springframework.context.annotation.Configuration;ImportOrg.springframework.web.servlet.ViewResolver;ImportOrg.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;ImportORG.SPRINGFRAMEWORK.WEB.SERVLET.CONFIG.ANNOTATION.ENABLEWEBMVC;ImportOrg.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;Importorg.springframework.web.servlet.view.InternalResourceViewResolver, @Configuration @enablewebmvc//Start Spring MVC@ComponentScan ("Spitter.web")//Start Component Scan Public classWebconfigextendsWebmvcconfigureradapter {//Configuring the JSP view resolver@Bean Publicviewresolver Viewresolver () {internalresourceviewresolver resolver=NewInternalresourceviewresolver (); Resolver.setprefix ("/web_inf/views/"); Resolver.setsuffix (". JSP"); Resolver.setexposecontextbeansasattributes (true); returnResolver; } @Override Public voidconfiguredefaultservlethandling (Defaultservlethandlerconfigurer configurer) {configurer.enable ();//Configuring the handling of static resources }}
The first thing to note in Listing 5.2 is that webconfig now adds @componentscan annotations, so the Spitter.web package will be scanned for components. As you'll see later, the controller we're writing will have a @controller annotation, which makes it a candidate bean when the component is scanned. Therefore, we do not need to explicitly declare any controller in the configuration class.
Next, we add a viewresolver bean. More specifically, it is internalresourceviewresolver. We will discuss the view parser in more detail in the 6th chapter. All we need to know is that it looks for the JSP file, and when it finds it, it adds a specific prefix and suffix to the view name (for example, a view called home will resolve to web-infviews/home.jsp).
Finally, the new Webconfig class also expands the Webmvcconfigureradapter and writes its configuredefaultservlethandling () method. By invoking the Enable () method of Defaultservlethandlerconfigurer, we ask Dispatcherservlet to forward requests for static resources to the default servlet in the Servlet container. Instead of using the Dispatcherservlet itself to handle such requests
Webconfig is ready, what about RootConfig? Because this chapter focuses on Web development, and the Web-related configuration is already configured with the application context created by Dispatcherservlet, the current rootconfig is relatively straightforward:
PackageSpittr.config;ImportOrg.springframework.context.annotation.ComponentScan;ImportOrg.springframework.context.annotation.ComponentScan.Filter;Importorg.springframework.context.annotation.Configuration;ImportOrg.springframework.context.annotation.FilterType;ImportORG.SPRINGFRAMEWORK.WEB.SERVLET.CONFIG.ANNOTATION.ENABLEWEBMVC, @Configuration @componentscan (basepackages = {"Spitter"}, Excludefilters ={@Filter (type= filtertype.annotation, value = Enablewebmvc.class) }) Public classRootConfig {}
The only thing to note is that RootConfig uses @componentscan annotations. In this case, in this book, we have a lot of opportunities to use non-Web Components to enrich the perfect rootconfig.
5.1.3 Spittr Application Introduction
The example used in this chapter, from Twitter to get some inspiration, so the first call Spitter, and then borrowed from the recently popular site Flickr, so we also take e out, and eventually form the name Spittr. This also helps to differentiate between domain names (similar to Twitter, which is implemented here in spring, so called Spitter) and app names.
Spittr is similar to Twitter, where users can add tweets. Spittr has two important concepts: Spitter (the user of the app) and Spittle (the user publishes a simple state). This chapter builds the application's Web tier, creates a controller to showcase the spittle, and the user registration process.
5.2 Writing the basic controller
In spring MVC, the controller is just the class that adds the @requestmapping annotation to the method, which declares the request that they want to process.
At the beginning, we were as simple as possible, assuming that the controller class was handling requests for "/" and rendering the first page of the app. The homecontroller shown in Listing 5.3 is probably the simplest of the spring MVC controller classes.
PackageSpittr.web;ImportOrg.springframework.stereotype.Controller;Importorg.springframework.web.bind.annotation.RequestMapping;ImportOrg.springframework.web.bind.annotation.RequestMethod; @Controller//declaring a controller Public classHomeController {@RequestMapping (value= "/", method = Requestmethod.get)//Handling GET Requests PublicString Home () {return"Home"; } }
The first thing
You might notice is that homecontroller with @controller annotations. Obviously this annotation is used to declare the controller, but in fact this annotation has little effect on spring MVC itself. homecontroller is a stereotype (stereotype) annotation based on @component annotations. Here, its purpose is to assist in the implementation of component scanning. Because HomeController has @controller annotations, the component scanner automatically finds HomeController and declares it as a bean in the spring application context.
In fact, you can also let HomeController with @component annotations, it achieves the same effect, but it may be a little more ideographic, it is not possible to determine what type of HomeController component.
HomeController is the only method, the home () method, with @requestmapping annotations. Its Value property specifies the request path to be processed by this method, and the Method property refines the HTTP methods it handles. In this case, the home () method is called when an HTTP GET request for "/" is received.
You can see that the home () method does not actually do much: it returns a string type of "home". This string will be interpreted by spring MVC as the name of the view to render. Dispatcherservlet will require the view parser to resolve this logical name to the actual view.
Given the way we configure Internalresourceviewresolver, the view name "Home" will resolve to the JSP of the "web-infviews/home.jsp" path. Now, we'll make the homepage of the Spittr app quite simple, as shown below.
Program Manifest 5.4 spittr The first page of the app, defined as a simple JSP
<%@ page language= "java" contenttype= "text/html; Charset=utf-8 " pageencoding=" UTF-8 "%> <%@ taglib prefix=" C "uri=" http://java.sun.com/jsp/jstl/ Core "%><%@ taglib prefix=" Spring "uri=" Http://www.springframework.org/tags "%> " href= "<c:url value="/resources/style.css "/>" >
This JSP does not have much to pay attention to. It is just a welcome app user and provides two links: one is to view the Spittle list and the other is to register it in the app. It shows what the home page looks like at this time.
5.2.1 Test Controller
The following procedure describes how to test the controller of Spring MVC.
Program Listing 5.5 Improved Homecontrollertest
PackageSpittr.web;Importorg.junit.Test;ImportORG.SPRINGFRAMEWORK.TEST.WEB.SERVLET.MOCKMVC;Importorg.springframework.test.web.servlet.request.MockMvcRequestBuilders;Importorg.springframework.test.web.servlet.result.MockMvcResultMatchers;Importorg.springframework.test.web.servlet.setup.MockMvcBuilders; Public classhomecontrollertest {@Test Public voidTesthomepage ()throwsException {HomeController Controller=NewHomeController (); //Set MOCKMVCMockmvc MOCKMVC =Mockmvcbuilders.standalonesetup (Controller). build (); Mockmvc.perform (Mockmvcrequestbuilders.get ("/")). Andexpect (Mockmvcresultmatchers.view (). Name ("Home"))); } }
It first passes a HomeController instance to Mockmvcbuilders.standalonesetup () and calls build () to build the MOCKMVC instance. It then uses the MOCKMVC instance to perform a GET request for "/" and sets the desired view name.
5.2.2 defining request handling at the class level
One thing we can do is to split the @requestmapping and place its path mapping part at the class level. The procedure is shown in Listing 5.7.
Listing 5.7 Splitting the @requestmapping in HomeController
PackageSpittr.web;ImportOrg.springframework.stereotype.Controller;Importorg.springframework.web.bind.annotation.RequestMapping;ImportOrg.springframework.web.bind.annotation.RequestMethod; @Controller//declaring a controller@RequestMapping ("/")//Controller Matching Path Public classHomeController {@RequestMapping (method= Requestmethod.get)//Handling GET Requests PublicString Home () {return"Home";//View name } }
In this new version of HomeController, the path is now transferred to the class-level @requestmapping, and the HTTP method is still mapped at the method level. When the controller adds @requestmapping annotations at the class level, this annotation is applied to all processor methods of the controller. The @requestmapping annotation on the processor method complements the @requestmapping declaration at the class level.
As far as HomeController is concerned, there is only one controller method. After merging with class-level @requestmapping, the @requestmapping of this method indicates that home () will handle a GET request for the "/" path.
In other words, we didn't actually change any of the functions, we just swapped some code for a place, but HomeController did the same thing as before. Because we have a test now, we can ensure that there is no damage to the original functionality in this process.
When we modify @requestmapping, we can also make another change to HomeController. The Value property of the @RequestMapping can accept an array of type string. So far, we have set it to a string type of "/". However, we can also map it to a request for "/homepage" by simply changing the class-level @requestmapping to the following:
// Controller Matching Path Public class HomeController {//...}
The HomeController Home () method now maps to get requests for "" and "homepage".
This article Code link: https://github.com/Gugibv/spring/tree/master/spittr
Spring Combat Study notes-fifth: Building a Spring Web application