Spring MVC implementation process is not clear?

Time:2021-1-10

MVC summary

1. Overview

Or the previous three routines

What is 1.1?

SpringProvides a set of view layer processing framework, which is based onServletIt can be realized throughXMLOr annotation to configure what we need.

He provided interceptors, file uploads,CORSAnd other services.

1.2 why?

OriginalServletIn large projects, we need to go through multiple encapsulation to avoid code redundancy. Secondly, due to the different parameters required by different interfaces, we need to work on our ownServletLayer encapsulates the parameters we need, which is a repetitive and boring work for developers, so the view layer framework appears to encapsulate the parameters for us. Let developers pay attention to the logical architecture, do not need to consider parameter encapsulation and other issues.

1.3 how to use

Before we talk about how to use it, we need to knowMVCHow does it work.

He’s based on aDispatcherServletClass to forward all kinds of requests, that is, all the front-end requests will come to this servlet, and then this class encapsulates the parameters and forwards the requests, and executes the specific logic.(Chapter two, let’s talk about it)

1.3.1 XML
  • According to the above principle, we need aDispatcherServletTo provide the foundation for usServletService, we can passservletcanonicalweb.xmlFile to initialize the class. And declare this class to handle all requests, and then implement request forwarding through this class.
  • In addition, we also need a configuration file to configure the related information we needmvcInformation.

Let’s take a look at a complete exampleweb.xmlto configure

<web-app>

    <servlet>
    <servlet-name>dispatchServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatchServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

</web-app>
1.3.2 notes

Annotation is now the mainstream,SpringBootbe based onJavaConfigAutomatic configuration is realized

Implementation mode:

stayServlet3.0It defines a specification when it is usedSPIstandard.

SPI , full nameService Provider Interface, is a service discovery mechanism. It passes through theClassPathUnder the pathMETA-INF/servicesFolder search file, automatically load the class defined in the file.That is, when the service is started, the servlet will automatically load the class defined in the file

Spring MVC implementation process is not clear?

Let’s take a look at the contents of this document. He defined it internallySpringServletContainerInitializerContainer initialization class, that is, in theServletThis class is automatically initialized when it is started. This class is also the key to annotation implementation.

There is one in this classonStartupMethod, which is also called when the container is initialized. This method has two parameters

  • Set<Class<?>> webAppInitializerClassesHe represents our current situationSpringExisting in containerwebInitialize the class. We can do it ourselvesWebApplicationInitializerClass to customizeServletThe method executed during initialization.
  • ServletContext servletContexOn behalf ofServletContext object
org.springframework.web.SpringServletContainerInitializer
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
    @Override
    public void onStartup(Set<Class<?>> webAppInitializerClasses,         
 ServletContext servletContext)    throws ServletException {
        //Start logic
    }
}

Let’s look at the annotation configuration method

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletCxt) {

        // Load Spring web application configuration
        AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
        //A configuration class, @ configuration
        ac.register(AppConfig.class);
        //The refresh method of spring
        ac.refresh();

        // Create and register the DispatcherServlet
        DispatcherServlet servlet = new DispatcherServlet(ac);
        ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);
        registration.setLoadOnStartup(1);
        registration.addMapping("/app/*");
    }
}

Through implementationWebApplicationInitializerInterface, asMVCAfter loadingSpringServletContainerInitializerLoad this class when you need to.


However, in the specific implementation,SpringWe are not recommended to do so,He suggested that theSpringandSpringMvcSeparate, look at a picture

Spring MVC implementation process is not clear?

He added a layer of web environment configuration to spring. It’s equivalent to wrapping a layer of springServlet

Take a look at the code at this point

public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    
    //Spring configuration file
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { RootConfig.class };
    }

    //Spring MVC configuration file
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { App1Config.class };
    }
    
    //Specifies the path that the dispatcher servlet can intercept
    @Override
    protected String[] getServletMappings() {
        return new String[] { "/app1/*" };
    }
}

adoptAbstractAnnotationConfigDispatcherServletInitializer

Spring MVC implementation process is not clear?

You can see that he didWebApplicationInitializerInterface, that is, in theServletThis class is loaded during initialization.

AbstractContextLoaderInitializerClass, he initialized itSpring

AbstractDispatcherServletInitializerClass, initializedDispatcherServlet

AbstractAnnotationConfigDispatcherServletInitializerClass, integrating two classes together

2. Implementation principle

Before we talk about this principle, let’s talk about what he is going to do?

Requirements: request distribution; parameter encapsulation; result return

So what if we do it ourselves? (Just talking about annotations, let’s see how we use them firstMVCOf)

  • One@ControllerAnnotation, indicating that the current class is the control layer interface,
  • OneRequestMappingIdentify the name of the methodURIAnd request method
  • One@ResponseBodyThe return type that identifies this method isJSON
  • Onetest01Identify this method to handle/testrequest
@Controller
public class UserController {

    @GetMapping("/test")
    @ResponseBody
    public String test01(){
        return "success" ;

    }
}

Next, let’s take a look at the logic of our own handling of requests from what we already have

Let’s first think about our request process

  • The front end sends oneHttpRequest, through differenturiRealize different logic processing
  • And this oneuriAnd our back-end definition@RequestMappingInvalueSame value
  • That is, we can go through aMapStructure, willvalueAskey, willmethodOfClassObject as avalueSave to oneMappingRegisterin
  • When the request came, it passedURIFrom thisMapGet the correspondingMethodIf there is no correspondingMethodGive me one404.

2.1 spring loading

It’s on the topHow to use it?As mentioned in, he passedAbstractContextLoaderInitializerTo loadSpringConfiguration file.

Spring MVC implementation process is not clear?

At this point, things about spring have been loaded, but not initialized

2.2 MVC loading

It’s also throughAbstractDispatcherServletInitializerClass implementation

Spring MVC implementation process is not clear?

2.2.1 DispatcherServlet

Let’s take a look at this period,DispatcherServletHow to handle requests

Function: distribute all requests

Class inheritance structure diagram

Spring MVC implementation process is not clear?

You can see that he inherited itHttpServletClass, belonging to aServletAnd we configured this beforeServletThe interception path of. He will intercept all requests and make a distribution.

You should be familiar with the following picture:

Spring MVC implementation process is not clear?

actuallyDispatcherServletThe way all requests are handled is fully shown in this diagram.

Now let’s talk about his design ideas.

When a request comes, enterdoDispatchMethod, and then processes the request, also returns an execution chain

SpringThere are three ways to do thisProcessor mapperTo handle different requests.

  • BeanNameUrlHandlerMappingTreatment aloneBeanI’d like to ask. Suitable for implementationControllerandHttpRequestHandlerClass of interface
@Component("/test02")
public class HttpController  implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println ("HttpController execution");
        return null;
    }
}
@Component("/test01")
public class HandlerController implements HttpRequestHandler {

    @Override
    public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("handlerRequest");
    }
}
  • RequestMappingHandlerMappingProcessor mapping for method types.
@Controller
public class UserController {

    @GetMapping("/test")
    public String test01(){
        System.out.println ("executed");
        return "success" ;
    }
}
  • RouterFunctionMapping,MVCProvides a mapper processor that processes a controller defined by functional programming. You need to add it directly to the container, and then route an address to return the corresponding data
@Configuration
@ComponentScan("com.bywlstudio.controller")
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp("/WEB-INF/pages/",".jsp");
    }

    @Bean
    public RouterFunction<?> routerFunctionA() {
        return RouterFunctions.route()
                .GET("/person/{id}", request1 -> ServerResponse.ok().body("Hello World"))
                .build();
    }

}

After talking about processor mapper, let’s talk about it againProcessor adapter

Different request methods require different processing methods, which is the sameSpringWhy to provide an adapter.

  • RequestMappingHandlerAdapterUsed to process all method requests, that is, through the@ControllerAnnotation defined
  • HandlerFunctionAdapterIt is used to deal with functional mapping, that is, through theRouterFunctionMappingDefined
  • HttpRequestHandlerAdapterIt’s used to handle the implementationHttpRequestHandlerInterface
  • SimpleControllerHandlerAdapterIt’s used to handle the implementationControllerInterface request

Get the appropriate processor through the processor adapter to process the corresponding request.

When the processor executes a specific request,It’s actually the process of calling our method, and the return value will appear

Generally, we have two methods for return value:

  • @ResponseBodyDirect returnJSONData.
  • Or return a view that will be parsed by the view parser.

For return value parsing,MVCProvides an interface to handle all return values, here we just talk about the above two

  • ModelAndViewMethodReturnValueHandlerUsed to process requests to return to the view model
  • RequestResponseBodyMethodProcessorUsed to handle returnsJSON

After we get the return value of the method, we callthis.returnValueHandlers.handleReturnValueThis method of the return value parser is used to return and update the view modelJSONEcho of data(Directly echo to the web page, and the returned view object is null

For the view object, it is parsed directly through the view parser to render the data model, and then echo to the front end.

2.2.2 MappingRegistry

This class storesmethodMapping information for.

class MappingRegistry {

   private final Map<T, MappingRegistration<T>> registry = new HashMap<>();

   private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<>();

   private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<>();

   private final Map<String, List<HandlerMethod>> nameLookup = new ConcurrentHashMap<>();

   private final Map<HandlerMethod, CorsConfiguration> corsLookup = new ConcurrentHashMap<>();

   private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();

MVCGets the method and object from this classURLReference to. amount toSpring MVCIt’s a good container.

3. Interview questions

3.1 what is MVC? What is MVVM?

A:MVCIs an architecture pattern, it has three cores

  • View. user interface
  • Model. Business data
  • Controller. Receive user input, control model and view for data interaction

MVVMIt’s also an architecture pattern, and it’s also three cores

  • Model(Model)。 Back end data
  • View model(ViewModel)。 It completes the binding of data and view
  • View(View)。 user interface

Its core idea is as follows:adoptViewModelBind data to view and operate view with data. The common framework is Vue

3.2 execution process of spring MVC

  • User sends request toDispatcherServlet
  • DispatcherServeltCall after receiving requestHandlerMapping, find the request processor mapper(One out of three
  • Mapping by processor mapperURIProcessor execution chain (including interceptors and processor objects)
  • Call the processor adapter to find the processor that can handle the execution chain(One out of four)
  • Processor specific execution, returnModelAndViewobject

    • If there is@ResponseBodyAnnotation, direct data echo
  • TheModelAndViewObject toViewResoveThe view parser parses and returns to the view
  • DispatcherServletYesViewRender the view
  • Response user

More original articles please pay attention to the author’s official account number @MakerStack, please contact the authorisation of the author.