MVC summary

1. An overview of the

It’s the same three routines

What is 1.1?

Spring provides a view-level processing framework, based on servlets, that can be configured using XML or annotations.

It provides services such as interceptors, file uploads, CORS, etc.

1.2 Why?

Native Servlet is needed in large projects in multiple packaging, to avoid redundant code, second due to different interfaces require different parameters, we need to himself at the Servlet layer encapsulates the parameters, we need it for developers is a repetitive and boring work, so the view layer framework, the parameters for our packaging, and other functions. Let developers focus solely on the logical architecture, without worrying about parameter encapsulation and other issues.

1.3 how to use

Before we talk about how to use it, we need to understand how MVC works.

It realizes the forwarding of various requests based on a DispatcherServlet class, that is, all the requests from the front end will go to this Servlet, and then this class performs parameter encapsulation and request forwarding, and performs specific logic. (Let’s talk more about this in Chapter 2.)

1.3.1 XML
  • So based on the above principle, we need oneDispatcherServletTo provide us with a foundationServletThe service we can get throughservletSpecification of theweb.xmlFile to initialize the class. The class is declared to handle all requests, and then the request is forwarded through this class.
  • In addition, we also need a configuration file to configure the relevant ones that we needmvcInformation.

Now let’s look at the complete oneweb.xmlconfiguration

<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 annotations

Annotations are now the mainstream, and SpringBoot implements automatic configuration based on JavaConfig

Implementation method:

In Servlet3.0, a specification SPI specification was defined.

SPI, also known as the Service Provider Interface, is a Service discovery mechanism. It automatically loads the classes defined in the file by looking for it in the META-INF/services folder under the ClassPath path. This means that when the service starts, the Servlet will automatically load the classes defined in this file

Let’s take a look at the contents of this file. Class defines SpringServletContainerInitializer, his inner container is initialized, that is to say, when the Servlet start automatically initialize the class, the class was the key to annotation to achieve.

There is an onStartup method in this class, which is called when the container is initialized. This method takes two arguments

  • Set<Class<? >> webAppInitializerClassesHe represents our presentSpringIt’s in the containerwebInitialize the class. We can do it ourselvesWebApplicationInitializerClass self-definitionServletMethod to be executed when initialized.
  • ServletContext servletContexOn behalf of theServletContext 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}}

Look at the specific annotation configuration:

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); // refresh(); // refresh(); // Create and register the DispatcherServlet DispatcherServlet servlet = new DispatcherServlet(ac); ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet); registration.setLoadOnStartup(1); registration.addMapping("/app/*"); }}

By implementing WebApplicationInitializer interface, as a configuration of MVC classes, at the time of loading SpringServletContainerInitializer load this class.


However, Spring does not recommend that we do this in the concrete implementation. It suggests separating Spring and Spring MVC. See the diagram below

He adds a layer of Web environment configuration on top of Spring. It’s like wrapping a layer around SpringServlet

Take a look at the code at this point

Public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {/ / @ Override the Spring configuration file protected Class<? >[] getRootConfigClasses() { return new Class<? >[] { RootConfig.class }; } //SpringMVC configuration file @Override protected Class<? >[] getServletConfigClasses() { return new Class<? >[] { App1Config.class }; } // Override protected String[] getServletMappings() {return new String[] {"/app1/*"}; }}

Through AbstractAnnotationConfigDispatcherServletInitializer

Can see he realized WebApplicationInitializer interface, that is, when the Servlet initialization will load the class.

AbstractContextLoaderInitializer class, he initialization of the Spring

AbstractDispatcherServletInitializer class, initialize the DispatcherServlet

AbstractAnnotationConfigDispatcherServletInitializer, the two together

2. Implementation Principle

Before we talk about the principle, what is he going to do?

Requirements: Request distribution; Parameter encapsulation; Results back

So what if we do it ourselves? (Note only, let’s see how we use MVC.)

  • a@ControllerAnnotation that identifies the current class as a control layer interface,
  • aRequestMappingIdentifies the methodURIAnd how to request it
  • a@ResponseBodyIdentifies that the return type of this method isJSON
  • atest01Identifies that this method is used for processing/testrequest
@Controller public class UserController { @GetMapping("/test") @ResponseBody public String test01(){ return "success" ; }}

Next, let’s look at our own logic for handling requests through what we already have

Consider our request process for a moment:

  • The front end sends aHttpRequest, through differenturiImplement different logic processing
  • And thisuriAnd our back-end definition@RequestMappingIn thevalueThe same value
  • So we can go through oneMapStructure,valueAs akeyThat will bemethodtheClassObject as avalueTo aMappingRegisterIn the
  • When the request comes, passURIFrom thisMapGets the correspondingMethodExecute if there is no correspondingMethodGive me a404.

2.1 the Spring loaded

How to use in the above mentioned, he loaded by AbstractContextLoaderInitializer Spring configuration file.

At this point, the Spring stuff is loaded, but not initialized

2.2 the MVC load

Also through AbstractDispatcherServletInitializer class implements

2.2.1 DispatcherServlet

Let’s take a look at how the DispatcherServlet handles requests during this period

Function: Distribute all requests

Class inheritance structure diagram

You can see that it inherits from the HttpServlet class and belongs to a Servlet whose intercepting path we configured earlier. He intercepts all requests and makes a distribution.

Here’s a picture you should be familiar with:

In fact, the way the DispatcherServlet handles all requests is completely reflected in this diagram.

Let’s talk about his design ideas.

When a request comes, enterdoDispatchMethod and then process the request, also returning an execution chain

Spring provides three types of processor mappers to handle different requests.

  • BeanNameUrlHandlerMappingHandle aloneBeanThe request. Applicable to implementationControllerandHttpRequestHandlerThe class of the interface
@Component("/test02") public class HttpController implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest request, 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"); }}
  • RequestMappingHandlerMappingHandler mappings for method types.
Public String test01(){System.out.println();} public String test01(){System.out.println(); return "success" ; }}
  • RouterFunctionMapping.MVCProvided is a mapper handler that handles defining controllers through functional programming. It needs to be added directly to the container, and then routed to 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 mappers, let’s talk about processor adapters

Different requests require different handling methods, which is why Spring provides an adapter.

  • RequestMappingHandlerAdapterTo handle all method requests, i.e@Controllerannotation-defined
  • HandlerFunctionAdapterTo handle functional mappings, i.e., byRouterFunctionMappingThe definition of the
  • HttpRequestHandlerAdapterTo handle the implementationHttpRequestHandlerOf the interface
  • SimpleControllerHandlerAdapterTo handle the implementationControllerInterface request

The appropriate processor is obtained through the processor adapter to process the corresponding request.

The process of executing a specific request in the processor is actually the process of calling our method, so the return value appears

Usually we have two methods for return values:

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

For return value parsing,MVCAn interface is provided to handle all return values, and we will only talk about the two above

  • ModelAndViewMethodReturnValueHandlerUsed to handle requests to return to the viewmodel
  • RequestResponseBodyMethodProcessorFor processing returnsJSON

After we get the method return value, can call this. ReturnValueHandlers. HandleReturnValue return value of the parser this method, used to return on the view model and echo of the JSON data (echo directly to the web page, where the returned view object to null)

The view object is parsed directly through the view parser, the data model is rendered, and then displayed back to the front end.

2.2.2 MappingRegistry

This class holds the mapping information for method.

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();

MVC gets references to methods and URLs from this class. The equivalent of a Spring MVC container.

3. The interview questions

3.1 What is MVC? What is the MVVM?

A: MVC is an architectural pattern that has three cores

  • View (View). The user interface
  • Model (the Model). Business data
  • Controller. Receive user input and control model and view for data interaction

MVVM is also an architectural pattern that has three cores

  • Model (Model). The back-end data
  • View Model (ViewModel). It completes the binding of data and view
  • View (View). The user interface

Its core idea is to bind data and view through ViewModel and manipulate view with data. The common framework is VUE

3.2 Spring MVC execution flow

  • The user sends a request toDispatcherServlet
  • DispatcherServeltInvoked after receiving the requestHandlerMapping, locate the request handler mapper (Choose three)
  • Through the processor mapperURIProcessor execution chain (including interceptors, and handler objects)
  • Invoke the processor adapter to find the processor that can handle the chain of execution (choose one of four)
  • The processor executes and returns the ModelAndView object

    • If there is@ResponseBodyAnnotations, direct data echo
  • Returns theModelAndViewObject toViewResoveThe view parser parses and returns the view
  • DispatcherServletrightViewRender view
  • In response to the user

More original articles please pay attention to the author’s official account @MakerStack, reprint please contact the author for authorization