MVC summary

1. An overview of the

It’s the same three things we did before

What is 1.1?

Spring provides a view-level processing framework that is implemented using servlets and can be configured using XML or annotations.

It provides interceptors, file uploads, CORS and more.

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 the developer focus on the logical architecture without the need to worry about parameter encapsulation.

1.3 how to use

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

It implements the forwarding of various requests based on a DispatcherServlet class, where all requests from the front end come to the Servlet, which then encapsulates the parameters and forwards the requests, performing the specific logic. (Chapter 2)

1.3.1 XML
  • According to the principle above, we need oneDispatcherServletTo give us the foundationServletService, we can passservletSpecification of theweb.xmlFile to initialize the class. It also declares that this class handles all requests and then implements request forwarding through this class.
  • In addition, we also need a configuration file to configure the relevant ones that we needmvcInformation.

Let’s look at a 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> Copy the code
1.3.2 annotations

Annotation is now the mainstream, SpringBoot based on JavaConfig automatic configuration

Implementation method:

An SPI specification was defined in Servlet3.0.

SPI, or Service Provider Interface, is a Service discovery mechanism. It automatically loads the classes defined in the files by looking for them in the META-INF/services folder in the ClassPath path. That is, the Servlet automatically loads the classes defined by this file when the service is started


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.

This class has an onStartup method, which is also called when the container is initialized. This method takes two arguments

  • Set<Class<? >> webAppInitializerClassesHe represents our presentSpringExisting in a containerwebInitialize the class. We can do it ourselvesWebApplicationInitializerClass customizationServletMethod to execute at initialization time.
  • ServletContext servletContexOn behalf of theServletContext object
org.springframework.web.SpringServletContainerInitializer
Copy the code
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
    @Override
 public void onStartup(Set<Class<? >> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
 // Start logic  } } Copy the code

Take a look at the 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);  // Spring's refresh method  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/*");  } } Copy the code

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


In the implementation, However, Spring doesn’t recommend that we do this. He suggests separating Spring and SpringMvc and looking at the diagram


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

Look at the code at this point

public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
 
    //Spring configuration file
    @Override
    protectedClass<? >[] getRootConfigClasses() { return newClass<? >[] { RootConfig.class }; }   //SpringMVC configuration file  @Override  protectedClass<? >[] getServletConfigClasses() { return newClass<? >[] { App1Config.class }; }   // Specify a path that DispatcherServlet can intercept  @Override  protected String[] getServletMappings() {  return new String[] { "/app1/*" };  } } Copy the code

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 that, what does he do?

Requirements: request distribution; Parameter encapsulation; Results back

So what if we implement it ourselves? (Annotations alone, let’s see how we use MVC.)

  • a@ControllerAnnotation that identifies the current class as a control-layer interface,
  • aRequestMappingIdentifies the methodURIAnd how the request was made
  • a@ResponseBodyIdentifies the return type of this method asJSON
  • atest01Identifies the method used for processing/testrequest
@Controller
public class UserController {

    @GetMapping("/test")
    @ResponseBody
 public String test01(a){  return "success" ;   } } Copy the code

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

Consider our request process first:

  • The front end sends aHttpRequest through differenturiImplementation of different logic processing
  • And thisuriAnd what we define at the back end@RequestMappingIn thevalueThe same value
  • Which means we can pass oneMapStructure,valueAs akeyThat will bemethodtheClassObject as avalueTo aMappingRegisterIn the
  • When the request comes in, pass itURIFrom thisMapTo obtain the correspondingMethodExecute if 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 look specifically at how the DispatcherServlet handles requests during this period

Role: Distribute all requests

Class inheritance structure diagram


You can see that it inherits the HttpServlet class and belongs to a Servlet whose interception path was configured earlier. He would intercept all the requests and then do a distribution.

The following diagram should be familiar to all of you:


The way DispatcherServlet handles all requests is fully illustrated in this diagram.

Let’s talk about his design ideas.

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

Spring provides three types of processor mapper 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, HttpServletResponse response) throws Exception {
        System.out.println("HttpController execution");
 return null;  } } Copy the code
@Component("/test01")
public class HandlerController implements HttpRequestHandler {

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

    @GetMapping("/test")
    public String test01(a){
 System.out.println("Executed.");  return "success" ;  } } Copy the code
  • RouterFunctionMapping.MVCProvides a mapper processor that handles controller definition through 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  publicRouterFunction<? > routerFunctionA() { return RouterFunctions.route()  .GET("/person/{id}", request1 -> ServerResponse.ok().body("Hello World"))  .build();  }  } Copy the code

After talking about processor mapper, let’s talk about processor adapters

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

  • RequestMappingHandlerAdapterUsed to handle all method requests, that is, pass@ControllerAnnotated defined
  • HandlerFunctionAdapterUsed to handle functional mapping, that is, throughRouterFunctionMappingThe definition of the
  • HttpRequestHandlerAdapterUsed to process the implementationHttpRequestHandlerOf the interface
  • SimpleControllerHandlerAdapterUsed to process the implementationControllerInterface request

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

The process of executing a specific request on the processor is actually the process of calling our method, and the return value is there

Generally we have two methods for returning values:

  • @ResponseBodyDirect returnJSONThe data.
  • Or return a view that is parsed by the view resolver.

For return value resolution,MVCProvides an interface for handling all of the return values, and we’ll just cover the two above

  • ModelAndViewMethodReturnValueHandlerUsed to handle requests to return to the viewmodel
  • RequestResponseBodyMethodProcessorUsed to process 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)

View objects are 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 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(); Copy the code

MVC gets the method and URL references 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 the model and view for data interaction

MVVM is also an architectural pattern, and it also has three cores

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

Its core idea is: bind data and view through ViewModel, manipulate view with data, common framework is Vue

3.2 Spring Mvc implementation process

  • The user sends a request toDispatcherServlet
  • DispatcherServeltCalled when the request is receivedHandlerMapping, find the request handler mapper (Choose three)
  • Through the processor mapperURIProcessor execution chain (contains interceptors, and processor objects)
  • Call the processor adapter to find the processor that can handle the chain of execution (choose one of four)
  • Processor-specific execution, returnsModelAndViewobject
    • If there is@ResponseBodyAnnotation, directly for data echo
  • Returns theModelAndViewObject toViewResoveThe view parser parses and returns the view
  • DispatcherServletrightViewRender the view
  • In response to the user

This article is formatted using MDNICE