A schematic analysis of the Spring MVC request processing process (a)

Source: Internet
Author: User
Tags what callback

Objective

The Spring MVC framework is believed to be familiar to many people, and the information on this is a huge search. But the feeling speaks is not very meticulous, lets many beginners all foggy. I have done so, I have studied it before, but I don't have to find it again after some time. So I decided to write it down for later use.
  This series is based on spring-4.3.1, the configuration method is all based on java-based mode

From the configuration

First, the Configuration code:

@EnableWebMvc@Configuration Public  class mvcconfig extends webmvcconfigureradapter {    @Override     Public void configuredefaultservlethandling(Defaultservlethandlerconfigurer Configurer)    {configurer.enable (); }@Override     Public void configureviewresolvers(Viewresolverregistry Registry) {registry.jsp ("/web-inf/jsp/",". JSP"); Registry.enablecontentnegotiation (NewMappingjackson2jsonview ()); }@Override     Public void configurecontentnegotiation(Contentnegotiationconfigurer Configurer) {Configurer.favorpathextension (true). Ignoreacceptheader (true). ParameterName ("mediatype"). Defaultcontenttype (mediatype.text_html). MediaType ("HTML", mediatype.text_html). MediaType ("JSON", Mediatype.application_json); }@Bean(name ="Multipartresolver")//File Upload bean     PublicCommonsmultipartresolverCommonsmultipartresolver() {return NewCommonsmultipartresolver (); }}

The spring MVC configuration based on the java-based approach requires the creation of a configuration class and implementation WebMvcConfigurer interface, which WebMvcConfigurerAdapter is a simple abstraction of the WebMvcConfigurer interface (with some default implementations added), so the configuration code above chooses to inherit directly WebMvcConfigurerAdapter . Then implement the specific methods in the interface according to the needs of the project, and finally note that you want to label them on the configuration class @EnableWebMvc .
Someone here might ask, how do I know what to implement? How exactly should I match? What are the processing processes between them? OK, don't worry, we'll step by step.
First, we need to know WebMvcConfigurer what callback methods are available on the interface.

Webmvcconfigurer
 PackageOrg.springframework.web.servlet.config.annotation;/** * For reasons, we will introduce only some of the methods commonly used by spring MVC * * Public  interface webmvcconfigurer {    voidAddformatters (Formatterregistry Registry);voidConfiguremessageconverters (listvoidExtendmessageconverters (list/ * Some options for configuring content adjudication * /    voidConfigurecontentnegotiation (Contentnegotiationconfigurer configurer);voidConfigureasyncsupport (Asyncsupportconfigurer configurer);/ * @since 4.0.3 * /    voidConfigurepathmatch (Pathmatchconfigurer configurer);/ * Parameter Resolution * /    voidAddargumentresolvers (list/ * Return value Resolution * /    voidAddreturnvaluehandlers (list/ * Exception handling * /    voidConfigurehandlerexceptionresolvers (listvoidExtendhandlerexceptionresolvers (listvoidAddinterceptors (Interceptorregistry Registry); Messagecodesresolver Getmessagecodesresolver ();voidAddviewcontrollers (Viewcontrollerregistry Registry);/** * Here Configure the View resolver */    voidConfigureviewresolvers (Viewresolverregistry Registry);/** * Static resource processing * /    voidAddresourcehandlers (Resourcehandlerregistry Registry);voidConfiguredefaultservlethandling (Defaultservlethandlerconfigurer configurer);voidAddcorsmappings (Corsregistry registry);}

Here are a few common ways to focus on the following:

void configureViewResolvers(ViewResolverRegistry registry);void configureContentNegotiation(ContentNegotiationConfigurer configurer);void addViewControllers(ViewControllerRegistry registry);void addResourceHandlers(ResourceHandlerRegistry registry);void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer);
1. Configureviewresolvers (Viewresolverregistry Registry)

From the method name we can see that this method is used to configure the view parser, the parameter of the method ViewResolverRegistry is a registrar, used to register you want to customize the view parser and so on. ViewResolverRegistrya few common methods:

1). Enablecontentnegotiation
/** 启用内容裁决视图解析器*/publicvoidenableContentNegotiation(View... defaultViews) {        initContentNegotiatingViewResolver(defaultViews);    }

This method creates a content adjudication parser that ContentNegotiatingViewResolver does not parse the specific view, but manages all the view parsers that you register, all of which are parsed first, and then determined by which parser to use. The specific mapping rules are determined based on the requested media types.

2). urlbasedviewresolverregistration
    publicjsp(String prefix, String suffix) {        new InternalResourceViewResolver();        resolver.setPrefix(prefix);        resolver.setSuffix(suffix);        this.viewResolvers.add(resolver);        returnnew UrlBasedViewResolverRegistration(resolver);    }

The method registers an internal resource View parser that InternalResourceViewResolver is apparently accessed by all JSPs that it parses. The method parameter is used to specify the prefix and file suffix of the path, such as:

    registry.jsp("/WEB-INF/jsp/"".jsp");

For the above configuration, if the returned view name is example, it will be returned /WEB-INF/jsp/example.jsp to the front end and the report 404 cannot be found.
  

3). Beanname
    publicvoidbeanName() {        new BeanNameViewResolver();        this.viewResolvers.add(resolver);    }

This method registers a BeanNameViewResolver view resolver, what does this parser do? It mainly resolves the view name to the corresponding bean. What do you mean? If the returned view name is example, will it find a bean called example in the spring container, and the bean is of type view.class? If so, return this bean.
  

4). Viewresolver
    publicvoidviewResolver(ViewResolver viewResolver) {        ifinstanceof ContentNegotiatingViewResolver) {            thrownew BeanInitializationException(                    "addViewResolver cannot be used to configure a ContentNegotiatingViewResolver. Please use the method enableContentNegotiation instead.");        }        this.viewResolvers.add(viewResolver);    }

This method must be known by the name, it is used to register a variety of view parsers, including their own definition.
  

2. Configurecontentnegotiation (Contentnegotiationconfigurer configurer)

In the previous section we talked about the configureViewResolvers method, if we enabled the Content award parser in this method, then configureContentNegotiation(ContentNegotiationConfigurer configurer) this method is specifically used to configure some parameters of the Content award. This is relatively straightforward, and we can look at it directly from an example:
  

public void Configurecontentnegotiation (Contentnegotiationconfigurer configurer) {/ * Whether media type is determined by requesting the extension of the URL * /Configurer. Favorpathextension(true)/ * Do not check the Accept request header * /                . Ignoreacceptheader(true). ParameterName("mediatype")/ * Set the default media yype * /                . Defaultcontenttype(mediatype. TEXT_html)/ * request to end with. HTML will be treated as mediatype.text_html*/                . MediaType("HTML", mediatype. TEXT_html)/ * requests that end with. JSON will be treated as mediatype.application_json*/                . MediaType("JSON", mediatype. Application_json);}

Here we can give an example to further familiarize ourselves with the above knowledge, if our MVC configuration is as follows:

    @EnableWebMvc    @Configuration     Public  class mvcconfig extends webmvcconfigureradapter {        @Override         Public void configureviewresolvers(Viewresolverregistry Registry) {registry.jsp ("/web-inf/jsp/",". JSP"); Registry.enablecontentnegotiation (NewMappingjackson2jsonview ()); }@Override         Public void configurecontentnegotiation(Contentnegotiationconfigurer Configurer) {Configurer.favorpathextension (true). Ignoreacceptheader (true). ParameterName ("mediatype"). Defaultcontenttype (mediatype.text_html). MediaType ("HTML", mediatype.text_html). MediaType ("JSON", Mediatype.application_json); }    }

The controller's code is as follows:

    @Controller    publicclass ExampleController {         @RequestMapping("/example1")         publicexample1() {            new HashMap();            map.put("1""a");            map.put("2""b");            returnnew ModelAndView("example1", map);        }    }

Create a example1.jsp file in the web-inf/jsp directory, free of content. Now launch Tomcat, enter the following link in the browser: Http://localhost:8080/example1.json, the browser returns as follows:
  
In the browser input http://localhost:8080/example1 or http://localhost:8080/example1.html, return as follows:

Obviously, two times a different view parser is used, so what happens at the bottom? In the configuration we have two view resolvers registered:ContentNegotiatingViewResolverAndInternalResourceViewResolver, there is also a default view:MappingJackson2JsonView。 When the controller finishes executing, it returns a Modelandview with the name example1 of the view. Return first will be given toContentNegotiatingViewResolverFor view resolution processing, andContentNegotiatingViewResolverThe view name example1 is given to all the viewresolver it holds to try to parse (only in this instanceInternalResourceViewResolver), and then according to the requested mediatype, thenexample1.mediaType(This is Example1.json and example1.html) as the view name for all the view resolvers to parse again, after two steps to resolve, you will get a bunch of candidatesList<View>Plus the defaultMappingJackson2JsonView, and finally based on the requested media type from the candidateList<View>Select an optimal return, and the view is resolved. Now you can understand why the request link in the example above is added.jsonAnd not.jsonThe results will be different. When added.jsonIndicates that the requested media type is Mediatype.application_json, while theInternalResourceViewResolverThe contenttype of the parsed view is inconsistent with theMappingJackson2JsonViewContentType match, so I chose theMappingJackson2JsonViewReturned as a view. When not added.jsonWhen requested, the default media type is mediatype.text_html, so you use theInternalResourceViewResolverThe parsed view is returned as a value. I want to see here that you can already customize the view in general.

3. Addviewcontrollers (Viewcontrollerregistry Registry)

This method can easily implement a request-to-view mapping without writing a controller, for example:
  

    @Override      publicvoidaddViewControllers(ViewControllerRegistry registry){          registry.addViewController("/login").setViewName("login");      

This is a direct return to the login page when accessing ${domain}/login.

4. Addresourcehandlers (Resourcehandlerregistry Registry)

This method is used specifically to register a handler to handle static resources, such as: Pictures, js,css, and so on. Example:
  

    @Override    publicvoidaddResourceHandlers(ResourceHandlerRegistry registry) {        registry.addResourceHandler("/resource/**").addResourceLocations("/WEB-INF/static/");    }

When you request Http://localhost:8083/resource/1.png, you will return the/web-inf/static/1.png. Note : The static resources here are placed in the web-inf directory.

5. Configuredefaultservlethandling (Defaultservlethandlerconfigurer configurer)

Usage:

  @Override  public  void      Configuredefaultservlethandling  (Defaultservlethandlerconfigurer configurer) {configurer.enable (); }

A default handler is registered: DefaultServletHttpRequestHandler This handler is also used to handle static files, and it attempts to map /* . When the Dispatcherservelt is mapped / ( / and /* is differentiated) and no appropriate handler is found to handle the request, it is handed over DefaultServletHttpRequestHandler . Note : The static resources here are placed under the WEB root directory, not under web-inf .
Perhaps the description here is a bit difficult to understand (I feel the same), so simply give an example, for example: in the webroot directory There is a picture: 1.png We know the Servelt specification in the Web root directory (webroot) files can be directly accessed, But because the DispatcherServlet mapping path is configured: / it intercepts almost all of the requests, resulting in 1.png a lack of access, and registering one DefaultServletHttpRequestHandler can solve the problem. In fact, it can be understood that DispatcherServlet a feature that has been destroyed Servlet (the file under the root directory can be accessed directly) DefaultServletHttpRequestHandler is helpful to return to this feature.

Off Topic

Q: / /* What's the difference?
A: / all URLs except JSPs are intercepted and /* all URLs, including JSPs, are blocked. For example: Under Webroot There is a test.jsp, when DispatcherServlet configuring the map / , the browser input: http://localhost:8083/test.jsp This JSP is directly accessible, and does not pass DispatcherServlet , and when DispatcherServlet When the mapping is configured /* , the request is DispatcherServlet intercepted.

A schematic analysis of the Spring MVC request processing process (a)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.