To undertake the former Wen springboot sentiment edify-web configuration (a), this article will be based on the previous analysis of the MVC of the relevant applications
A simple example of MVC
Write a controller layer code directly, return the format as JSON
package com.example.demo.web.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.ResponseBody;import java.util.HashMap;import java.util.Map;/** * @author nanco * ------------- * ------------- * @create 2018/9/4 **/@Controller@RequestMapping("/boot")@ResponseBodypublic class DemoController { @RequestMapping(value = "/hello", method = RequestMethod.GET) public Map<String, String> helloWorld() { Map<String, String> result = new HashMap<>(); result.put("springboot", "hello world"); return result; }}
After running, the Client Tools HTTP Access link Http://127.0.0.1:9001/demoWeb/boot/hello can get the following simple results
{"springboot":"hello world"}
SOURCE Analysis
We all know that the core component of SPRINGMVC is Dispatcherservlet, which is essentially a servlet component, and also contains the logic to handle the front-end request. Specific can refer to Springmvc source sentiment edify-dispatcherservlet. This article explains the process of springboot creating dispatcherservlet and MVC configuration
Dispatcherservletautoconfiguration
The first step is to configure the Dispatcherservlet component, which is divided into several steps
The first head of the brain annotation to understand
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)@Configuration@ConditionalOnWebApplication(type = Type.SERVLET)@ConditionalOnClass(DispatcherServlet.class)@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)@EnableConfigurationProperties(ServerProperties.class)public class DispatcherServletAutoConfiguration {}
From the above annotations, it is necessary to continue after the Servletwebserverfactoryautoconfiguration class is injected into the Bean factory, which is associated with the previous article.
No.2 dispatcherservletconfiguration Inner class
@Configuration @Conditional (Defaultdispatcherservletcondition.class) @ConditionalOnClass (SERVLETREGISTRATION.CLA SS) @EnableConfigurationProperties (Webmvcproperties.class) protected static class Dispatcherservletconfiguration { The SPRING.MVC was introduced to the beginning of the configuration private final webmvcproperties webmvcproperties; Private final serverproperties serverproperties; Public Dispatcherservletconfiguration (Webmvcproperties webmvcproperties, serverproperties ServerProperties) {this.webmvcproperties = webmvcproperties; This.serverproperties = serverproperties; }//Create the Dispatcherservlet directly and inject it into the Bean factory @Bean (name = default_dispatcher_servlet_bean_name) public Dispat Cherservlet Dispatcherservlet () {Dispatcherservlet dispatcherservlet = new Dispatcherservlet (); Corresponds to Spring.mvc.dispatch-options-request dispatcherservlet.setdispatchoptionsrequest (THIS.W EbmvcprOperties.isdispatchoptionsrequest ()); Corresponds to Spring.mvc.dispatch-trace-request dispatcherservlet.setdispatchtracerequest (THIS.WEBMV Cproperties.isdispatchtracerequest ()); Corresponds to Spring.mvc.throw-exception-if-no-handler-found dispatcherservlet.setthrowexceptionifnohandlerfound ( This.webMvcProperties.isThrowExceptionIfNoHandlerFound ()); return dispatcherservlet; }//Create a @Bean @ConditionalOnBean (multipartresolver.class) for file request named Multipartresolver @Condition Alonmissingbean (name = dispatcherservlet.multipart_resolver_bean_name) public multipartresolver MultipartResolver (M Ultipartresolver resolver) {//Detect if the user has created a multipartresolver but named it incorrectly return resolver; }//Get Server.servlet.path indicates that Dispatcherservlet's interception path @Bean public Dispatcherservletpathprovider Maindis PatcherservletpathproVider () {return ()-DispatcherServletConfiguration.this.serverProperties.getServlet () . GetPath (); } }
The simple thing is to create a dispatcherservlet, so how is it injected into Tomcat's servlet collection?
No.3 dispatcherservletregistrationconfiguration Inner class
@Configuration @Conditional (Dispatcherservletregistrationcondition.class) @ConditionalOnClass (servletregistratio N.class) @EnableConfigurationProperties (webmvcproperties.class) @Import (dispatcherservletconfiguration.class) Pro Tected Static class Dispatcherservletregistrationconfiguration {private final serverproperties serverproperties; Private final webmvcproperties webmvcproperties; Private final multipartconfigelement Multipartconfig; Public Dispatcherservletregistrationconfiguration (Serverproperties serverproperties, Webmvcproperties WebM Vcproperties, objectprovider<multipartconfigelement> multipartconfigprovider) {This.serve Rproperties = serverproperties; This.webmvcproperties = webmvcproperties; This.multipartconfig = Multipartconfigprovider.getifavailable (); }//Dispatcherservlet injected into a container such as tomcat @Bean (name = Default_dispatcher_servlet_registraTion_bean_name) @ConditionalOnBean (value = dispatcherservlet.class, NAME = default_dispatcher_servlet_bean_name) Public servletregistrationbean<dispatcherservlet> dispatcherservletregistration (DISPATCHERSERVL ET Dispatcherservlet) {//with Server.servlet.path, default =/Servletregistrationbean<dispatcherservlet> ; Registration = new Servletregistrationbean<> (Dispatcherservlet, THIS.SERVERPR Operties.getservlet (). getservletmapping ()); Registration.setname (Default_dispatcher_servlet_bean_name); Read Spring.mvc.servlet.load-on-startup, default is-1 Registration.setloadonstartup (This.webmvcprop Erties.getservlet (). Getloadonstartup ()); if (this.multipartconfig! = null) {registration.setmultipartconfig (this.multipartconfig); } return registration; } }
By the above code, the injection of the servlet into the Tomcat container is implemented through the implementation class Servletregistrationbean of the Servletcontextinitializer interface , and the specific article does not expand , but if the user wants to inject a servlet or filter into Tomcat, this bean is often used to manipulate it.
Webmvcautoconfiguration
After the Dispatcherservlet component is created and injected into the Web container, the next step is to configure the MVC, and the author also follows several steps to analyze
The skull annotation Look at
@Configuration@ConditionalOnWebApplication(type = Type.SERVLET)@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class })public class WebMvcAutoConfiguration {}
This configuration is also in effect when injected into the Bean factory by the dispatcherservletautoconfiguration above.
No.2 Filter Collection
1.hiddenhttpmethodfilter-Covert Propagation Put/delete/patch Request
@Bean @ConditionalOnMissingBean(HiddenHttpMethodFilter.class) public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() { // 默认对post请求的包读取_method参数指定的方法,然后再作转换 return new OrderedHiddenHttpMethodFilter(); }
Implicit propagation of Put/delete/patch requests via the methodparam parameter, default parameter name _method
, or user-configurable
2.httpputformcontentfilter-Explicit Response Put/delete/patch Request
// spring.mvc.formcontent.putfilter.enabled不指定或者值不为false则生效 @Bean @ConditionalOnMissingBean(HttpPutFormContentFilter.class) @ConditionalOnProperty(prefix = "spring.mvc.formcontent.putfilter", name = "enabled", matchIfMissing = true) public OrderedHttpPutFormContentFilter httpPutFormContentFilter() { // 直接对PUT/DELETE/PATCH请求进行响应,其order值大于OrderedHiddenHttpMethodFilter return new OrderedHttpPutFormContentFilter(); }
It is generally used in conjunction with the above-mentioned Orderedhiddenhttpmethodfilter , whose order value is greater than the former so that it responds to a put and other requests.
Note : This is only registered filter to the Bean factory, and is not injected into the web container such as Tomcat, if users want to support the above request method, you can consider through the servletregistrationbean/ Filterregistrationbean to inject.
No.3 enablewebmvcconfiguration internal class, its similar @EnableWebMvc annotations, similar to our common spring configuration of Mvc:annotation-driven. Because of too much code, just pick a few to see
@Configuration public static class Enablewebmvcconfiguration extends Delegatingwebmvcconfiguration {//register RE Questmappinghandleradapter component @Bean @Override public Requestmappinghandleradapter Requestmappinghandle Radapter () {Requestmappinghandleradapter adapter = Super.requestmappinghandleradapter (); Adapter.setignoredefaultmodelonredirect (this.mvcproperties = = NULL | | this.mvcProperties.isIgnoreDefaul Tmodelonredirect ()); return adapter; }//Register requestmappinghanldermapping component @Bean @Primary @Override public Requestmappinghan Dlermapping requestmappinghandlermapping () {//Must be @Primary for Mvcuricomponentsbuilder to work return super.requestmappinghandlermapping (); }//Validator component @Bean @Override public Validator mvcvalidator () {if (! Classutils.ispresent ("Javax.validation.Validator", GetClass (). getClassLoader ()) {return super.mvcvalidator (); } return Validatoradapter.get (Getapplicationcontext (), Getvalidator ()); }//Exception Handling component @Override protected Exceptionhandlerexceptionresolver CREATEEXCEPTIONHANDLEREXCEP Tionresolver () {if (this.mvcregistrations! = null && this.mvcregistrations. Getexce Ptionhandlerexceptionresolver ()! = null) {return this.mvcRegistrations.getExceptionHandlerExceptionResolve R (); } return Super.createexceptionhandlerexceptionresolver (); } }
is mainly used to register the response front-end request of the plug-in collection, concrete how to integrate visible the author's top spring article, there is mention, it does not unfold here
warm hint: The author here reminds of this class is delegatingwebmvcconfiguration implementation class, which itself is annotated @Configuration decoration, its internal The Setconfigurers () method helps assemble all the collections that implement the Webmvcconfigurer interface, so the user can implement this interface to extend the associated configuration of MVC
private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite(); @Autowired(required = false) public void setConfigurers(List<WebMvcConfigurer> configurers) { if (!CollectionUtils.isEmpty(configurers)) { this.configurers.addWebMvcConfigurers(configurers); } }
No.4 Webmvcautoconfigurationadapter Inner Class (Webmvcconfigurer Interface Implementation Class)-adds additional components based on the above MVC components, including view components, message Processor components, and so on.
Limited to the code too long, the author here also select a few to see
The Message Processor collection is configured @Override public void Configuremessageconverters (list
Summary This article mainly explains the Springboot automatic configuration process of MVC, the reader mainly focuses on the bean factory configuration of components such as dispatcherservlet components and message processing. If users also want to customize to extend the relevant configuration of MVC, you can implement the Webmvcconfigurer interface, such as the next
package com.example.demo.web.config;import org.springframework.http.converter.HttpMessageConverter;import org.springframework.web.servlet.HandlerExceptionResolver;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.util.List;/** * @author nanco * ------------- * ------------- * @create 2018/9/5 **/@Configurationpublic class BootWebMvcConfigurer implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { } @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { } @Override public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) { }}
This article also describes if users want to expand the appropriate filter or servlet, you can use Filterregistrationbean/servletregistrationbean, such as the next
Package Com.example.demo.web.config;import Org.springframework.boot.web.servlet.filterregistrationbean;import Org.springframework.boot.web.servlet.servletregistrationbean;import Org.springframework.context.annotation.Bean ; Import Org.springframework.context.annotation.configuration;import Org.springframework.web.filter.onceperrequestfilter;import Javax.servlet.filter;import Javax.servlet.FilterChain ; Import Javax.servlet.servlet;import Javax.servlet.servletexception;import Javax.servlet.http.httpservlet;import Javax.servlet.http.httpservletrequest;import Javax.servlet.http.httpservletresponse;import java.io.IOException;/ * * @author Nanco *-------------*-------------* @create 2018/9/5 **/@Configurationpublic class Servletfilterbeans { Only intercept/simple/@Bean ("Simpleservlet") public servletregistrationbean<servlet> Simpleservlet () { return new servletregistrationbean<> (new Simpleservlet (), "/simple/"); }//Intercept/simple,/simple/,/simple/Ha etc. @Bean ("Simplefilter") public filterregistrationbean<filter> Simplefilter () {Filterregistrationbean Bean = New Filterregistrationbean<> (); Bean.setfilter (New Simplefilter ()); Bean.addurlpatterns ("/simple/*"); return bean; } private static Class Simpleservlet extends HttpServlet {@Override protected void doget (httpservletrequ EST req, HttpServletResponse resp) throws Servletexception, IOException {System.out.println ("Doservice Path:" + Req.getrequesturi ()); Super.doget (req, resp); }} private static class Simplefilter extends Onceperrequestfilter {@Override protected void DoFilter Internal (HttpServletRequest request, httpservletresponse response, Filterchain Filterchain) throws Servletexception, IOException {System.out.println ("Filter Path:" + Request.getrequesturi ()); Filterchain.dofilter (request, response); } }}