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 one
DispatcherServlet
To give us the foundationServlet
Service, we can passservlet
Specification of theweb.xml
File 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 need
mvc
Information.
Let’s look at a complete oneweb.xml
configuration
<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<? >> webAppInitializerClasses
He represents our presentSpring
Existing in a containerweb
Initialize the class. We can do it ourselvesWebApplicationInitializer
Class customizationServlet
Method to execute at initialization time.ServletContext servletContex
On behalf of theServlet
Context 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
@Controller
Annotation that identifies the current class as a control-layer interface, - a
RequestMapping
Identifies the methodURI
And how the request was made - a
@ResponseBody
Identifies the return type of this method asJSON
- a
test01
Identifies the method used for processing/test
request
@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 a
Http
Request through differenturi
Implementation of different logic processing - And this
uri
And what we define at the back end@RequestMapping
In thevalue
The same value - Which means we can pass one
Map
Structure,value
As akey
That will bemethod
theClass
Object as avalue
To aMappingRegister
In the - When the request comes in, pass it
URI
From thisMap
To obtain the correspondingMethod
Execute if no correspondingMethod
Give 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, enterdoDispatch
Method, which then processes the request, also returns an execution chain
Spring provides three types of processor mapper to handle different requests.
BeanNameUrlHandlerMapping
Handle aloneBean
The request. Applicable to implementationController
andHttpRequestHandler
The 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
RequestMappingHandlerMapping
Processor mappings for method types.
@Controller
public class UserController {
@GetMapping("/test")
public String test01(a){
System.out.println("Executed."); return "success" ; } } Copy the code
RouterFunctionMapping
.MVC
Provides 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.
RequestMappingHandlerAdapter
Used to handle all method requests, that is, pass@Controller
Annotated definedHandlerFunctionAdapter
Used to handle functional mapping, that is, throughRouterFunctionMapping
The definition of theHttpRequestHandlerAdapter
Used to process the implementationHttpRequestHandler
Of the interfaceSimpleControllerHandlerAdapter
Used to process the implementationController
Interface 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:
@ResponseBody
Direct returnJSON
The data.- Or return a view that is parsed by the view resolver.
For return value resolution,MVC
Provides an interface for handling all of the return values, and we’ll just cover the two above
ModelAndViewMethodReturnValueHandler
Used to handle requests to return to the viewmodelRequestResponseBodyMethodProcessor
Used 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 to
DispatcherServlet
DispatcherServelt
Called when the request is receivedHandlerMapping
, find the request handler mapper (Choose three)- Through the processor mapper
URI
Processor 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, returns
ModelAndView
object- If there is
@ResponseBody
Annotation, directly for data echo
- If there is
- Returns the
ModelAndView
Object toViewResove
The view parser parses and returns the view DispatcherServlet
rightView
Render the view- In response to the user
This article is formatted using MDNICE