1, the introduction of

1.1 Web MVC

In Web development, the browser typically sends a request to the server, which receives the request and passes the response to the client, which renders it and displays it to the user. Therefore, the server cannot actively notify the client of updates, although there are some push technologies that can do this.

In standard MVC, the server can actively push data to the client, but the actual WebMVC can not do this, if the user wants to update the view, they need to send a request again.

Web side development experience from CGI->Servlet->JSP->Model1->Model2->Front Controller+PageController process:

  • CGI :(Common Gateway Interface) a public Gateway Interface used to receive and process web user requests, and then dynamically generate a response to the user. Each request generates one heavyweight process.
  • Servlet: Receives a Web user request, processes it, and generates a response dynamically to the user. But only one thread (and a thread pool) is generated per request, lightweight. The essence is to output HTML streams in Java code.
  • JSP: Runs in a standard HTML page embedded scripting language, essentially embedding Java code in HTML code. JSPS will eventually be compiled into servlets.
  • Model1: An enhanced version of JSP, which can be thought of as JSP + Javabeans, uses the JSP :useBean standard action to simplify getting/creating Javabeans and encapsulating request parameters into Javabeans.
  • Model2: Web MVC model, but the controller uses Servlet, the model uses JavaBean, the view uses JSP.
  • Front Controller+PageController: Front Controller+ application Controller+PageController (also known as actions) + context, also Web MVC, but with clearer responsibilities.

1.2 Spring MVC

Spring MVC with Spring can provide us with powerful features, more concise configuration. Here’s how Spring Web MVC handles requests:

From the above figure, we summarize the Spring MVC request processing flow. After the user sends the request:

  1. The user request reaches the front-end controller, and the front-end controller finds the controller that handles the request according to the URL, and delegates the request to it.
  2. After receiving the request, the controller will call the business processing object to process it, and process the data model to get ModelAndView, and return it to the front-end controller;
  3. The front-end controller selects the corresponding view based on the returned view name for rendering and returns the final response to the user.

Combined with specific classes in the Spring MVC framework, we can get a more detailed diagram below:

The core class in SpringMVC is DispatcherServlet. According to the above analysis, it can be considered as a bridge for intermediate scheduling. Let’s look at the code after we introduce the Spring MVC dependencies. The core method in the DispatcherServlet is doDispatch() and here is its code:

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        boolean multipartRequestParsed = false;
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

        try {
            try {
                ModelAndView mv = null;
                Object dispatchException = null;

                try {
                    // 1. First check if it is Multipart, that is, if it contains the file to be uploaded
                    processedRequest = this.checkMultipart(request); multipartRequestParsed = processedRequest ! = request;// 2. According to the request and handlerMappings(list), find the corresponding HandlerExecutionChain
                    mappedHandler = this.getHandler(processedRequest);
                    if (mappedHandler == null || mappedHandler.getHandler() == null) {
                        this.noHandlerFound(processedRequest, response);
                        return;
                    }

                    // 3. Get the corresponding HandlerAdapter from a list of handlerAdapters in the same way
                    HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
                    String method = request.getMethod();
                    boolean isGet = "GET".equals(method);
                    if (isGet || "HEAD".equals(method)) {
                        long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                        if (this.logger.isDebugEnabled()) {
                            this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                        }

                        if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
                            return; }}// 4. Perform preprocessing of processor-specific interceptors
                    if(! mappedHandler.applyPreHandle(processedRequest, response)) {return;
                    }

                    // 5. The adapter executes the handler (calling the handler's corresponding function handler). Note that ModelAndView is returned
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }

                    this.applyDefaultViewName(processedRequest, mv);
                    // 6. Perform post-processing of processor-specific interceptors
                    mappedHandler.applyPostHandle(processedRequest, response, mv);
                } catch (Exception var20) {
                    dispatchException = var20;
                } catch (Throwable var21) {
                    dispatchException = new NestedServletException("Handler dispatch failed", var21);
                }
				
                // 7. Process the distribution result, which includes some exception handling, getting a view parser based on the view name and rendering, etc
                this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
            } catch (Exception var22) {
                this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
            } catch (Throwable var23) {
                this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23)); }}finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                if(mappedHandler ! =null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); }}else if (multipartRequestParsed) {
                // Clean up the resources occupied by the multipart request
                this.cleanupMultipart(processedRequest); }}}// This method is used to process the result received from the processor, both the exception and the resulting ModelAndView are processed
    private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
        boolean errorView = false;
		
        // Handle exception information
        if(exception ! =null) {
            if (exception instanceof ModelAndViewDefiningException) {
                this.logger.debug("ModelAndViewDefiningException encountered", exception);
                mv = ((ModelAndViewDefiningException)exception).getModelAndView();
            } else{ Object handler = mappedHandler ! =null ? mappedHandler.getHandler() : null;
                mv = this.processHandlerException(request, response, handler, exception); errorView = mv ! =null; }}// Parse the view and render the view
        if(mv ! =null && !mv.wasCleared()) {
            // The actual rendering method will find the corresponding View parser based on the name of ModelAndView and render a View View
            this.render(mv, request, response);
            if(errorView) { WebUtils.clearErrorRequestAttributes(request); }}else if (this.logger.isDebugEnabled()) {
            this.logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + this.getServletName() + "': assuming HandlerAdapter completed request handling");
        }

        if(! WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {if(mappedHandler ! =null) {
                mappedHandler.triggerAfterCompletion(request, response, (Exception)null); }}}Copy the code

So, we can summarize how Spriung MVC works as follows:

  1. The request sent by the user will arrive firstDispatcherServletAnd processed by it;
  2. DispatcherServletThrough the firstHandlerMappingFind the corresponding to the requestHandlerExecutionChain(Contains oneHandlerProcessor, multipleHandlerInterceptorInterceptor), through which it is easy to add new mapping policies;
  3. thenDispatcherServletContinue sending requests toHandlerAdapter.HandlerAdapterProcessors are packaged as adapters to support multiple types of processors, the adapter design pattern, which makes it easy to support many types of processors;
  4. HandlerAdapterBased on the results of the adaptation, the real processor’s function processing method is called, the function processing is completed, and one is returnedModelAndViewObject (containing model data, logical view name);
  5. Again byDispatcherServletAccording to theModelAndViewFind the correspondingViewResolverAnd it resolves the logical view name to concreteViewWith this strategy pattern, it is easy to replace other view technologies;
  6. I’m going to talk aboutViewRender,ViewIt’ll get in through the wireModelRender the Model data, which is actually a Map data structure, so it’s easy to support other view technologies;
  7. Return control toDispatcherServletBy theDispatcherServletReturn the response to the user, ending the process.

2. Use Spring MVC

2.1 XmL-based Configuration of Spring MVC

First, to use Spring MVC you need to add dependencies:

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>
Copy the code

The DispatcherServlet we analyzed above is registered with web.xml and we need to add the following configuration:

	<! DOCTYPEweb-app PUBLIC
			"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
			"http://java.sun.com/dtd/web-app_2_3.dtd" >
	<web-app>
		<display-name>Archetype Created Web Application</display-name>

		<servlet>
			<servlet-name>spring_is_coming</servlet-name>
			<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
			<load-on-startup>1</load-on-startup>
		</servlet>
		<servlet-mapping>
			<servlet-name>spring_is_coming</servlet-name>
			<url-pattern>*.mvc</url-pattern>
		</servlet-mapping>
	</web-app>
Copy the code

Here we register a servlet, the DispatcherServlet mentioned above, and give it a name of spring_is_coming. We also specify a servlet-mapping for it. As shown above, in url-pattern we specify the pattern of the urls to be handled by this servlet, that is, all urls ending in *.mvc. Load-on-startup Initializes the Servlet when the container is started.

By default, DispatcherServlet loads configuration files under WEB-INF/[Servlet name for DispatcherServlet]-servlet.xml. According to the above configuration we need to add the spring_is_coming-servlet.xml file under the web-INF directory of the current project. Add the following code to the file:


      
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="Http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
       xmlns:p="http://www.springframework.org/schema/p">

    <! -- HandlerMapping -->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

    <! -- HandlerAdapter -->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

    <! -- ViewResolver -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <bean name="/hello.mvc" class="me.shouheng.spring.mvc.HelloController"/>

</beans>
Copy the code

Here we declare several beans, which are the default implementations of HandlerMapping and HandlerAdapter. Then, we also define the InternalResourceViewResolver a view the parser. It is the default view resolver, and in its properties configuration, we specify the prefix and suffix paths for the loaded files. In fact, when we specify a view name as hello, the view parser loads the file/web-INF/JSP /hello.jsp.

Next we define a controller whose name corresponds to the specified URL. Because before we use the Bean mapping rules is BeanNameUrlHandlerMapping, that is to say the name of the Bean and url.

Then there is the code for the controller defined above:

public class HelloController implements Controller {

    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        ModelAndView mv = new ModelAndView();
        // Add model data can be any POJO object
        mv.addObject("message"."Hello Spring MVC!");
        // Set the logical view name, which the view parser resolves to the specific view page
        mv.setViewName("hello");
        returnmv; }}Copy the code

Here we use modelAndView.setViewName () to specify the name of the corresponding JSP file for the ModelAndView, which will record the named file in the specified directory according to the view resolution rules we configured above.

Start the server, enter the address in your browser: http://localhost:8080/hello.mvc, for testing.

2.2 Using filters

We can also process requests before the dispenser processes them, which we do through filters. We can use filters to do some basic work, such as string encoding problems. Let’s use a simple custom example to demonstrate the use of filters:

First, we customize a simple filter and output some information to the console:

public class TheFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init, filterConfig" + filterConfig);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("==================================== doFilter, servletRequest: "
                + servletRequest
                + "\nservletResponse: "
                + servletResponse
                + "\nfilterChain: " + filterChain);
        // This method must be called, otherwise the request will be intercepted here
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy(a) {
        System.out.println("destroy"); }}Copy the code

Here we implement the Fileter interface’s three declaration periods-related methods. Then, configure it into web.xml:

    <filter>
        <filter-name>the_filter</filter-name>
        <filter-class>me.shouheng.spring.mvc.TheFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>the_filter</filter-name>
        <url-pattern>*.mvc</url-pattern>
    </filter-mapping>
Copy the code

So we can process all requests that end in *.mvc.

2.3 DispatcherServlet,

The DispatcherServlet is actually a Servlet and we need to configure this class when we use Spring MVC because it is the core configuration class of Spring MVC. Other types of servlets need to be configured when we want to provide interfaces to other clients instead of using Spring MVC, but they are configured in the same way as they are used in servlets.

We have already mentioned the meaning of the two parameters of DispatcherServlet and used the configuration file spring_is_coming-servlet.xml. There are actually several ways to specify a configuration file for a DispatcherServlet:

The first option is to load the file in the WEB-INF directory using the default [DispatcherServlet’s Servlet name]-servlet.xml, which is the way we used it above.

The second way is to use contextClass in the < Servlet > tag when configuring the servlet and specify a configuration class that implements the WebApplicationContext interface. If this parameter is not specified, XmlWebApplicationContext is used by default.

The third method is similar to the second in that it is specified when the servlet is configured, except that it uses contextConfigLocation and uses a string to specify the location of the context. This string can be split into multiple strings (using commas as delimiters) to support multiple contexts (in the case of multiple contexts, if the same bean is defined twice, the last one takes precedence). As follows:

   <servlet>
        <servlet-name>chapter2</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-servlet-config.xml</param-value>
        </init-param>
    </servlet>
Copy the code

Often when configuring a context, we specify multiple contexts, each of which has its own responsibility. In addition to the Servlet context we configured earlier, we also need to configure the entire application context when using Spring:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
         classpath:spring-common-config.xml,
         classpath:spring-budget-config.xml
    </param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Copy the code

The configured ContextLoaderListener automatically initializes the application context when the container is started. The configuration file for the application context is specified by context-param above. Application contexts are typically used to load the underlying classes of the entire program, such as the DAO layer and Service layer. They can then be used with any other Web layer. The Servlet configuration context is usually used to load classes required by the Web layer, such as Controller, HandlerMapping, HandlerAdapter, and so on.

2.4 the interceptor

The logic handled by the interceptor in the DispatcherServlet is very straightforward. The DispatcherServlet calls the three methods of HandlerExecutionChain at different processing stages of the core method doDispatch() (in new versions of Spring the related logic is extracted and encapsulated into separate methods).

  1. HandlerExecutionChain.applyPreHandle()Will be inContollerIs called before the method is executed;
  2. HandlerExecutionChain.applyPostHandle()Will be inContollerIs called after the method is executed and before the view is rendered, and is not called if an exception occurs in the middle; `
  3. HandlerExecutionChain. TriggerAfterCompletion () will be inContollerIs called after the view is rendered, always called, regardless of whether it is an exception;

So, what’s going on in these three methods? Here’s the logic. In fact, the three methods are similar, that is, they take the defined interceptor from an array and iterate over it:

    boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HandlerInterceptor[] interceptors = this.getInterceptors();
        if(! ObjectUtils.isEmpty(interceptors)) {for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {
                HandlerInterceptor interceptor = interceptors[i];
                if(! interceptor.preHandle(request, response,this.handler)) {
                    this.triggerAfterCompletion(request, response, (Exception)null);
                    return false; }}}return true;
    }
Copy the code

So, the logic of this part is not complicated. So, so let’s see how to use interceptors in Spring MVC:

    <bean name="interceptor" class="me.shouheng.spring.mvc.TestInterceptor"/>

    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/hello2.mvc"/>
            <ref bean="interceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
Copy the code

We add the above lines to the previous spring_is_coming-servlet.xml. Here we use a custom interceptor, and here we give its definition:

public class TestInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("=========preHandle");
        return super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("=========postHandle");
        super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("=========afterCompletion");
        super.afterCompletion(request, response, handler, ex);
    }

    @Override
    public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("=========afterConcurrentHandlingStarted");
        super.afterConcurrentHandlingStarted(request, response, handler); }}Copy the code

We then use the < MVC: Interceptor > tag to define the corresponding interceptor and the path to match it. This will invoke the interceptor we defined when the responding Controller is triggered when accessing the specified URL.

Here we also explain a few methods of HandlerInterceptorAdapter. Virtually all interceptors end up implementing the HandlerInterceptor interface, from which the first three methods in the above class actually come. The default return value in preHandle() is true, indicating that the current interceptor will continue processing to the next interceptor. In fact refer to the above HandlerExecutionChain. ApplyPreHandle () method also can see that.

2.5 Annotation-based Configuration

In the annotation-based configuration approach, we need to make some changes to the above configuration. First, we use an annotation-based adapter and mapping mechanism. In spring_is_coming-servlet.xml, we replace the previous code with:

    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
Copy the code

Note that the above two lines of code are configured after Spring 3.1. The code before 3.1 has been removed in the latest Spring release and is no longer redundant.

Then, we define the following Controller:

@Controller
public class HelloController3 {

    @RequestMapping(value = "/hello3")
    public ModelAndView handle(a) {
        ModelAndView mv = new ModelAndView();
        // Add model data can be any POJO object
        mv.addObject("message"."Hello Spring MVC!");
        // Set the logical view name, which the view parser resolves to the specific view page
        mv.setViewName("hello3");
        returnmv; }}Copy the code

The configuration is similar to the previous Bean name-mapping mechanism, except that the annotation-based configuration is used. On the class we use as Controller, we use the @Controller annotation, and on the specific business layer methods we use the @RequestMapping annotation and specify the mapping path. We then register the Bean with the context:

    <bean class="me.shouheng.spring.mvc.HelloController3"/>
Copy the code

This completes the basic configuration. Then, run the Web container and enter the url: http://localhost:8080/hello3. Also note that you need to change the matching path of the Servlet in web.xml to/if it is *.mvc.

The only difference between this configuration and the previous one is that the mapping rule is converted from Bean name to URL to annotation to URL.

In addition to configuring the URL path as described above, we can also add various seed paths. Such as:

@Controller
@RequestMapping("/user")
public class HelloController3 {

    @RequestMapping(value = "/hello3")
    public ModelAndView handle(a) {
        ModelAndView mv = new ModelAndView();
        // Add model data can be any POJO object
        mv.addObject("message"."Hello Spring MVC!");
        // Set the logical view name, which the view parser resolves to the specific view page
        mv.setViewName("hello3");
        returnmv; }}Copy the code

This will match: /user/hello3.

2.6 RequestMapping annotations

As you can see from above, the core configuration using annotations should belong to the @requestMapping annotation. Here is the definition of this annotation:

public @interface RequestMapping {
    String name(a) default "";
    @AliasFor("path") String[] value() default {};
    @AliasFor("value") String[] path() default {};
    RequestMethod[] method() default {};
    String[] params() default {};
    String[] headers() default {};
    String[] consumes() default {};
    String[] produces() default {};
}
Copy the code

Among them:

  1. nameSpecifies a name for the current controller.
  2. valueandpathAre equivalent, are used to specify the URL matching rules;
  3. methodTo specify matching methods, such as POST, GET, and so on;
  4. consumesSpecify the content-type of the request, e.g. application/json, text/ HTML;
  5. params: Specifies that the request must contain some parameter values to be processed by the method.
  6. headers: Specifies that the request must contain some specified header value before the method can process the request.
  7. produces: Specifies that the request must contain some specified header value before the method can process the request.

Let’s briefly explain some of these methods.

2.6.1 value and path

The effects of these two parameters are equivalent because they are related to each other only by an alias. These two parameters are used to specify the URL to be mapped to the controller. Here we list common URL mapping configurations:

  1. @RequestMapping(value={"/test1", "/user/create"}): Multiple URL paths map to the same processor;
  2. @RequestMapping(value="/users/{userId}"): Uses URL placeholders, such as “/users/123456” or “/users/abcd”, to pass@PathVariableYou can extract variables from the URI template schema;
  3. @RequestMapping(value="/users/**"): can match /users/ ABC/ABC, but /users/123 will be mapped to the mode in 2 first.
  4. @RequestMapping(value="/product?" ): matches “/product1” or “/producta”, but does not match “/product” or “/productaa”;
  5. @RequestMapping(value="/product*"): matches “/productabc” or “/product”, but does not match “/productabc/ ABC”;
  6. @RequestMapping(value="/product/*"): can match ‘/product/ ABC’, but not ‘/productabc’
  7. @RequestMapping(value="/products/**/{productId}"): Matches “/products/ ABC/ABC /123” or “/products/123”.
  8. Regular expression based approach.

Configuration Mode 2: A specific example of specifying parameters in a path and obtaining parameters in a method:

    @RequestMapping("/testPathVariable/{id}")
    public String testPathVariable(@PathVariable("id") Integer id2) {
        System.out.println("testPathVariable: " + id2);
        return SUCCESS;
    }
Copy the code

2.6.2 params

This parameter is used to restrict the request to be processed only if the request contains data with the specified parameter name, for example:

@Controller
@RequestMapping("/parameter1")                                      //① Processor generic mapping prefix
public class RequestParameterController1 {
    @RequestMapping(params="create", method=RequestMethod.GET) 
    public String showForm(a) {... }@RequestMapping(params="create", method=RequestMethod.POST)  
    public String submit(a) {... }}Copy the code

The first method indicates that the request has a create parameter name and the request method is GET. For example, the matching request URL is http://×××/parameter1? Create “; The second method is matched if the request has a parameter name of “create” and the request method is “POST”.

RequestMapping(params=”submitFlag=create”, method= requestmethod.get); The request is matched only when submitFlag=create is displayed and the request method is GET.

Also note from the params definition in @requestMapping that it is an array, and when multiple values are specified, the values are ‘and’, meaning that both parameters are included.

2.6.3 consumes

The consumes are used to specify the data types for the requests that the controller handles. The media types are Text, plain Application, json and so on. They are placed in the request header, such as content-Type: Application/X-www-form-urlencoded indicates that the requested data is key/value data, and the controller will process the requested data only if the requested data is the same as the controller specified in @requestMapping.

    @RequestMapping(value = "/testMethod", method = RequestMethod.POST,consumes="application/json")
    public String testMethod(a) {
        System.out.println("testMethod");
        return SUCCESS;
    }
Copy the code

For example, the controller above only accepts JSON data. Requests for non-JSON data are not processed.

2.6.4 produces

Produces specifies what type of data the current request expects. This parameter is placed in the Accept header at request time. A request will be accepted and processed only if the Accept type is the same as produces specified in the controller.

2.6.5 headers

While It is a special case that uses Consumes and Produces to specify the types of data that are requested and desired, headers allows you to specify what information needs to be contained in headers for the controller to handle it. Such as:

    @RequestMapping(value = "testParamsAndHeaders", params = { "username","age! =10" }, headers = { "Accept-Language=US,zh; Q = 0.8 "})
    public String testParamsAndHeaders(a) {
        System.out.println("testParamsAndHeaders");
        return SUCCESS;
    }
Copy the code

Used to set the first language in the request header to be US.

3, other

3.1 The difference between interceptors and filters

  1. Interceptors are based on Java’s reflection mechanism and filters are based on function callbacks;
  2. Interceptors do not rely on the servlet container. Filters do, because filters are defined by the Servlet specification and are only used in Web applications, whereas interceptors can be used in Appliaction, Swing, etc.
  3. Interceptors can be called multiple times during the life of an Action, while filters can only be called once when the container is initialized.
  4. The interceptor can fetch individual beans from the IOC container, but the filter can’t. This is important. Inject a service into the interceptor to invoke business logic;
  5. Filters are preprocessed after the request enters the container, but before the request enters the servlet. The return at the end of the request is also after the servlet has finished processing it and before it is returned to the front end.

In fact, as you can see from the configuration above, the filter is called before the request reaches the Servlet and belongs to the Servlet, not Spring.