Spring Web MVC knows this is enough

Version 5.3.30-SNAPSHOThttps://docs.spring.io/spring-framework/docs/5.3.30-SNAPSHOT/reference/html/web.html#mvc-servlet-config

Spring Web MVC is the original web framework based on the Servlet API and has been included in the Spring framework from the beginning. Its official name "Spring Web MVC" comes from the name of its source module (Spring -webmvc), but the more common name is "Spring MVC".

Parallel to Spring Web MVC, Spring Framework 5.0 introduces a reactive stack web framework whose name "Spring WebFlux" is also based on its source module (Spring - WebFlux).

Before digging into Spring Web MVC, we need to understand two concepts: MVC pattern and front-end controller pattern.

-1MVC mode

MVC is a software design pattern. The MVC pattern stands for Model-View-Controller pattern. This pattern is used for layered development of applications.

  • Model - A model represents an object or JAVA POJO that accesses data. It can also have logic to update the controller when the data changes.
  • View - A view represents a visualization of the data contained by the model.
  • Controller - Controller acts on models and views. It controls the flow of data to model objects and updates the view when the data changes. It separates the view from the model.

Insert image description here

-1.1 Implementation

We create a Car model object. CarView is a view class that prints Car information on the console. CarController is responsible for storing model data to the controller class and updating the corresponding model information to the CarView view.

  • Car

    package com.example.demo.mvc;
    
    /**
     * @Author yrz
     * @create 2023/7/27 14:10
     * @Description TODO
     */
    
    public class Car {
        public Car() {
        }
    
        public Car(String plateNo, String color) {
            this.plateNo = plateNo;
            this.color = color;
        }
    
        /**
         * 车牌
         */
        private String plateNo;
        /**
         * 车颜色
         */
        private String color;
    
        public String getPlateNo() {
            return plateNo;
        }
    
        public void setPlateNo(String plateNo) {
            this.plateNo = plateNo;
        }
    
        public String getColor() {
            return color;
        }
    
        public void setColor(String color) {
            this.color = color;
        }
    }
    
    
  • CarView

    package com.example.demo.mvc;
    
    /**
     * @Author yrz
     * @create 2023/7/27 14:14
     * @Description TODO
     */
    
    public class CarView {
        public void printCarInfo(Car car){
            System.out.println(car.getPlateNo() + " " + car.getColor());
        }
    }
    
    
  • CarController

    package com.example.demo.mvc;
    
    /**
     * @Author yrz
     * @create 2023/7/27 14:16
     * @Description TODO
     */
    
    public class CarController {
        private Car car;
        private CarView carView;
    
        public CarController(Car car, CarView carView) {
            this.car = car;
            this.carView = carView;
        }
    
        public void setCarPlateNo(String plateNo){
            car.setPlateNo(plateNo);
        }
    
        public void setCarColor(String color){
            car.setColor(color);
        }
    
        public void updateCarView(){
            carView.printCarInfo(car);
        }
    }
    
    
  • MVCPatternDemo

    package com.example.demo.mvc;
    
    /**
     * @Author yrz
     * @create 2023/7/27 14:19
     * @Description TODO
     */
    
    public class MVCPatternDemo {
        public static void main(String[] args) {
            Car car = new Car("冀E6666", "红色");
            CarView carView = new CarView();
            CarController carController = new CarController(car, carView);
            carController.updateCarView();
            car.setColor("蓝色");
            carController.updateCarView();
        }
    }
    
    

-1.2 Division of labor

In common B/S architecture application software based on the MVC framework, the front-end (Client Side) and the back-end (Server Side) are responsible for different tasks and responsibilities.

  • The front-end (client) is mainly responsible for the following aspects:
  1. View: The front end is responsible for creating and rendering the user interface, including the layout, style and interaction of the UI. It is responsible for displaying data to the user and receiving input from the user.

User interaction: The front end handles user input and interaction, such as receiving user clicks, inputs, and operations, and updating the view accordingly.

  • The backend (server side) is mainly responsible for the following aspects:
  1. Model: The backend is responsible for handling business logic and data persistence, including interaction with the database or other persistent storage. It defines the structure and rules of data and provides CRUD (create, read, update, delete) operations on data.
  2. Controller (Controller): The backend is responsible for handling the control and process of business logic, and performs corresponding processing according to user requests. It receives requests from the front end, processes the requests and operates on the model, and returns the results to the front end.
  3. Data storage and management: The backend is responsible for interacting with persistent storage (such as a database), including reading, writing, modifying, and deleting data. It can also be responsible for caching data to improve performance and handle issues such as concurrent access and security.
    Generally speaking, in the MVC framework, the front end is responsible for displaying the user interface and processing user interactions, and the back end is responsible for processing business logic and data storage. The front-end and back-end communicate through well-defined interfaces and protocols. The front-end sends the user's request to the back-end for processing, and receives the data and results returned by the back-end to implement a complete application.

0Front-end controller mode

Front Controller Pattern is a software design pattern used to build the request processing flow of web applications. It provides a centralized component, the front-end controller, for centrally processing all requests and scheduling corresponding handlers based on the type and content of the request.

In the front-end controller mode, all requests first pass through the front-end controller, and then based on the requested information, they are distributed to the appropriate handler to execute the actual processing logic. This centralized request processing can bring some of the following benefits:

  1. Centralized request processing: The front-end controller serves as the entry point of the application and is responsible for receiving and processing all requests. This centralized processing method simplifies the logic of request distribution and processing, and improves the maintainability and reusability of the code.

  2. Unified request processing: Through the front-end controller, unified processing of requests can be achieved. For example, common processing steps such as authentication, request logging, exception handling, etc. can be implemented in the front controller to avoid writing the same code repeatedly in each handler.

  3. Support diverse request handling strategies: The front-end controller can dynamically select the appropriate handler based on the type, content, or other identification of the request. This flexibility enables the system to customize processing according to different request requirements, improving the scalability and adaptability of the system.

  4. Supports complex request distribution and routing: the front-end controller can distribute requests to different handlers based on the request's routing information. This flexible request distribution mechanism can support complex request routing strategies, such as routing and distribution based on URL, request parameters, request headers, etc.

In summary, the front-end controller pattern provides a structured and scalable way to handle and manage web applications by introducing a centralized front-end controller component to centralize request distribution and processing in one place. Request process. It can simplify the code structure, improve code reusability, and support flexible request processing strategies.

The Front Controller Pattern is used to provide a centralized request processing mechanism, and all requests will be handled by a single handler. The handler can do authentication/authorization/logging, or track the request, and then pass the request to the appropriate handler. The following are the entities of this design pattern.

  • Front Controller - A single handler that handles all types of requests for an application, whether it is a web-based application or a desktop-based application program.
  • Dispatcher - The front controller may use a dispatcher object to dispatch requests to the corresponding specific handler.
  • View - A view is an object created for a request.

Front-end controller + scheduler = Controller in MVC

0.1 implementation

We will createFrontController and Dispatcher respectively as Front-end controller and scheduler. HomeView and StudentView represent various requests received by the front controller And the view created.

FrontControllerPatternDemo, our demo class uses FrontController to demonstrate the front controller design pattern.

Insert image description here

  • HomeView

    public class HomeView {
       public void show(){
          System.out.println("Displaying Home Page");
       }
    }
    
  • StudentView

    public class StudentView {
       public void show(){
          System.out.println("Displaying Student Page");
       }
    }
    
  • Dispatcher

    public class Dispatcher {
       private StudentView studentView;
       private HomeView homeView;
       public Dispatcher(){
          studentView = new StudentView();
          homeView = new HomeView();
       }
     
       public void dispatch(String request){
          if(request.equalsIgnoreCase("STUDENT")){
             studentView.show();
          }else{
             homeView.show();
          }  
       }
    }
    
  • FrontController

    public class FrontController {
       
       private Dispatcher dispatcher;
     
       public FrontController(){
          dispatcher = new Dispatcher();
       }
     
       private boolean isAuthenticUser(){
          System.out.println("User is authenticated successfully.");
          return true;
       }
     
       private void trackRequest(String request){
          System.out.println("Page requested: " + request);
       }
     
       public void dispatchRequest(String request){
          //记录每一个请求
          trackRequest(request);
          //对用户进行身份验证
          if(isAuthenticUser()){
             dispatcher.dispatch(request);
          }  
       }
    }
    
  • FrontControllerPatternDemo

    public class FrontControllerPatternDemo {
       public static void main(String[] args) {
          FrontController frontController = new FrontController();
          frontController.dispatchRequest("HOME");
          frontController.dispatchRequest("STUDENT");
       }
    }
    

1Servlet API

Servlet: (especially in the Java language) a small application that runs on a server; a small service program

The Servlet API is a standard API for developing Java-based web applications (https://jakarta.ee/specifications/servlet/). It provides a set of interfaces and classes for handling HTTP requests and responses and enables the development of dynamic, scalable web applications. The following are some commonly used Servlet API interfaces and classes:

  1. javax.servlet.Servlet: An interface that all Servlet classes must implement, defining the servlet's life cycle methods and service methods.

  2. javax.servlet.http.HttpServlet: The HttpServlet class inherited from the Servlet interface provides extension methods for processing HTTP requests, such as doGet(), doPost() Wait.

  3. javax.servlet.ServletConfig: Indicates the configuration information of Servlet, including initialization parameters, etc.

  4. javax.servlet.ServletContext: Represents the context of the Servlet, providing shared resources and information for the Servlet.

  5. javax.servlet.http.HttpServletRequest: Encapsulates the client's HTTP request information, such as request URI, request parameters, request headers, etc.

  6. javax.servlet.http.HttpServletResponse: Encapsulates the HTTP response information sent to the client, such as response status code, response header, output stream, etc.

  7. javax.servlet.http.HttpSession: Used to track session status between the client and server and store user-related data.

  8. javax.servlet.RequestDispatcher: Used to forward requests to other Servlets or JSP pages for processing.

  9. javax.servlet.Filter: Used to pre- and post-process requests and responses before the request reaches the Servlet or before the response is returned to the client.

  10. javax.servlet.annotation.WebServlet: Used to configure Servlets through annotations.

The above are only some of the interfaces and classes in the Servlet API. The Servlet API also contains many other interfaces and classes for handling session management, cookies, file upload and download, asynchronous processing, etc. These interfaces and classes provide the core functionality needed to build web applications.

2DispatcherServlet

Like many other web frameworks, Spring MVC is designed around the front controller pattern, where the central Servlet DispatcherServlet provides a shared algorithm for request processing, while the actual work is performed by configurable delegate components. This model is flexible and supports different workflows.

DispatcherServlet, like any Servlet, needs to be declared and mapped according to the Servlet specification by using Java configuration or in web.xml. In turn, DispatcherServlet uses Spring configuration to discover the required delegate components for request mapping, view resolution, exception handling, etc.

2.1 Customize DispatcherServlet

The following Java configuration example registers and initializes the DispatcherServlet, which is automatically detected by the Servlet container:

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) {

        // Load Spring web application configuration
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(AppConfig.class);

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

This code is a typical class that implements the WebApplicationInitializer interface. It is used to configure and initialize a Spring Web-based application.

In the onStartup method, the following tasks are mainly completed:

  1. Create and register the Spring Web application's configuration class: Tell Spring by creating a AnnotationConfigWebApplicationContext object and registering the application's configuration classAppConfig.class How the Web configures and assembles the relevant components of an application.

  2. Create and register DispatcherServlet: Create a DispatcherServlet object and pass in the previously created AnnotationConfigWebApplicationContext object as a parameter. DispatcherServlet is the core controller that receives and handles all requests. Next, use the method of the servletContext object to register , specify the Servlet name as "app", and set its loading order is 1. addServletDispatcherServlet

  3. Configure the URL mapping rules of DispatcherServlet: By calling the method of the registration object, change "/app/* ” This URL pattern maps to the just created, which means that all requests starting with “/app” will be handled by this . addMappingDispatcherServletDispatcherServlet

The above code is used to initialize and configure the Spring Web application. Through the implementation class of WebApplicationInitializer, we can customize the startup behavior of the application and perform various configuration operations as needed, such as loading Spring configuration, registering Servlet, setting URL mapping, etc. This method is more flexible and easier to expand than the traditional method based on web.xml configuration.

In the above code,AppConfig is an application configuration class that is used to configure and assemble the relevant components of the Spring Web application. Specifically, AppConfig classes are typically marked with the @Configuration annotation, and may use other annotations to define beans, interceptors, view resolvers, etc.

The following is an example implementation of the AppConfig class for reference:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.example")
public class AppConfig implements WebMvcConfigurer {
    
    

    // 配置视图解析器
    @Bean
    public ViewResolver viewResolver() {
    
    
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }

    // 配置静态资源
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    
    
        configurer.enable();
    }

    // 配置拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    
    
        registry.addInterceptor(new MyInterceptor());
    }

    // 配置请求处理器
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
    
    
        registry.addViewController("/").setViewName("index");
        registry.addViewController("/about").setViewName("about");
    }
    
    // ...
}

In this example, the AppConfig class uses the @Configuration annotation to indicate that it is a configuration class. The annotation @EnableWebMvc enables the automatic configuration of Spring MVC and also allows us to perform some custom configuration.

In AppConfig, we can define various beans, such as view resolvers, interceptors, etc. In the example, a view parser is defined through the viewResolver method, and the prefix and suffix of the view file are set. The configureDefaultServletHandling method is used to configure the default processor for processing static resources. addInterceptors method is used to add interceptors. The addViewControllers method is used to define a simple request handler to handle specific URL requests.

Of course, in actual development, the specific implementation of the AppConfig class may differ according to project requirements. You can customize the content of the AppConfig class according to the specific conditions of the project, including defining other beans, configuring data sources, transactions, etc.

In short,AppConfig The role of the class is to configure and assemble the relevant components of the Spring Web application so that the application can run correctly and provide the required functionality.

In Spring Boot projects, there is usually no need to manually implement the WebApplicationInitializer interface to configure DispatcherServlet. This is because Spring Boot has automatically processed these configurations and provided default configuration methods.

Spring Boot simplifies and accelerates the development of Spring applications through automatic configuration and the principle of convention over configuration. It automatically detects the dependencies and file structure in the project and provides default configuration and behavior for the application according to the convention.

In Spring Boot, by adding dependency spring-boot-starter-web, the framework automatically configures DispatcherServlet and maps it to the root path "/" according to the convention. Spring Boot will automatically load and initialize DispatcherServlet, and automatically configure some default processors, view parsers, exception handlers, etc.

In addition to the automatic configuration of DispatcherServlet, Spring Boot also provides many other automatic configuration functions, such as automatic registration of Servlets, Filters, Listeners, automatic configuration of data sources, transactions, etc.

If you need custom configuration, Spring Boot provides various ways to override or extend the default configuration. You can customize URL mapping rules and processing logic by using annotations such as @EnableWebMvc, @RequestMapping in the application's configuration class. You can also override the default configuration by configuring custom properties in the application.properties or application.yml file.

Spring MVC supports defining multiple DispatcherServlet instances. Each DispatcherServlet instance has its own independent context and request handling flow.

Normally, scenarios where we can define multiple DispatcherServlet instances in a Spring MVC application include:

  1. Handle requests for different URL patterns: If we want to distribute requests for different URL patterns to different processors, we can configure an independent DispatcherServlet instance for each URL pattern. This allows you to select different processing logic based on the requested URL.

  2. Aggregation of multiple web applications: In some cases, we may need to aggregate multiple independent web applications into a parent project. In order to implement this scenario, we can configure an independent DispatcherServlet instance for each sub-application to handle the requests of each sub-application independently.

  3. Use different view technologies: If we need to use different view technologies (such as JSP, Thymeleaf, FreeMarker, etc.) in the same application at the same time, we can configure an independent view technology for each view DispatcherServlet instance. This allows the appropriate view resolver and template engine to be selected based on the requested view technology.

It is important to note that each DispatcherServlet instance needs to have a unique name within the application and be configured with an independent mapping path. Can be configured in web.xml or, in Spring Boot, customized by using the @ServletComponentScan annotation in the application configuration classDispatcherServlet Example.

In short, Spring MVC provides flexible configuration options, allowing us to define multiple independent DispatcherServlet instances in an application to meet different needs and scenarios.

In a Spring Boot web project, there are two DispatcherServlet instances by default.

  1. Master DispatcherServlet instance: The default mapping path is "/*", used to handle web requests. This instance is automatically created via the @SpringBootApplication annotation. It loads all the configuration for the application and handles web requests from clients.

  2. Management DispatcherServlet Example: The default mapping path is “/actuator”, which is used to handle Spring Boot’s management endpoint requests. This instance is automatically added by Spring Boot and provides a series of management endpoints for monitoring and managing the running status of the application. For example, the health status of the application can be obtained through the "/actuator/health" endpoint.

The two DispatcherServlet instances have different mapping paths to distinguish between different types of requests. The master DispatcherServlet handles general web requests, while the admin DispatcherServlet handles requests for the admin endpoint.

It should be noted that although there are only two DispatcherServlet instances by default, we can also customize and add more DispatcherServlet instances to Adapt to specific business needs.

To sum up, in the Spring Boot Web project, there will be two DispatcherServlet instances by default, one is used to handle general Web requests, and the other is used to handle the management endpoint request.

2.2 Context Hierarchy

DispatcherServlet requires a WebApplicationContext (an extension of the normal ApplicationContext) for its own configuration. WebApplicationContext has a link to the ServletContext and its associated Servlet. It is also bound to the ServletContext so that applications can use the static methods on RequestContextUtils to find it when they need to access the WebApplicationContext.

For many applications, a singleton WebApplicationContext is sufficient. There may also be a context hierarchy where the root WebApplicationContext is shared between multiple DispatcherServlet (or other Servlet) instances, each with its own configuration of child WebApplicationContexts.

The root WebApplicationContext typically contains infrastructure beans such as data repositories and business services that need to be shared across multiple Servlet instances. These beans are effectively inherited and can be overridden (i.e. redeclared) in a Servlet-specific child WebApplicationContext, which typically contains the beans native to the given Servlet. The diagram below shows this relationship:

Insert image description here

Looking at the picture above combined with the DispatcherServlet configuration code in 2.1, DispatcherServlet needs to contain a WebApplicationContext (AnnotationConfigWebApplicationContext) and define Controllers, ViewResolver, HandlerMapping (AppConfig.class). These instances form the DispatcherServlet context hierarchy.

Let’s understand it this way|ू•ૅω•́)ᵎᵎᵎ

2.3 Special Bean Types

DispatcherServlet delegates to special beans to handle requests and render appropriate responses. By "special beans", we refer to spring managed object instances that implement framework contracts. They usually come with built-in contracts, but you can customize their properties and extend or replace them.

The following table lists the special beans detected by DispatcherServlet:

Bean type Explanation
HandlerMapping Maps a request to a handler and a list of [interceptors] (https://docs.spring.io/spring-framework/docs/5.3.30-SNAPSHOT/reference/html/web.html#mvc-handlermapping- interceptor) for pre- and post-processing. The mapping is based on some standards, the details of which vary between ' HandlerMapping ' implementations. The two main "HandlerMapping" implementations are "RequestMappingHandlerMapping" (which supports "@RequestMapping" annotated methods) and "SimpleUrlHandlerMapping" (which maintains explicit registration of URI path patterns for handlers).
HandlerAdapter Helps 'DispatcherServlet' call a handler mapped to a request, regardless of how the handler is actually called. For example, calling an annotated controller requires parsing the annotation. The main purpose of ' HandlerAdapter ' is to protect ' DispatcherServlet ' from these details.
HandlerExceptionResolver A strategy for resolving exceptions, possibly mapping them to handlers, HTML error views, or other targets. See (Exception)(https://docs.spring.io/spring-framework/docs/5.3.30-SNAPSHOT/reference/html/web.html mvc-exceptionhandlers).
ViewResolver Parses the logical ' String ' based view name returned from the handler into an actual ' view ', using it to render to the response. SeeView Resolution and View Technologies.
LocaleResolver, LocaleContextResolver Resolve the "locale" and possibly the time zone the client is using to be able to provide internationalized views. See (locale)(https://docs.spring.io/spring-framework/docs/5.3.30-SNAPSHOT/reference/html/web.html mvc-localeresolver).
ThemeResolver Address themes that your web application can use - for example, to provide a personalized layout. See (theme)(https://docs.spring.io/spring-framework/docs/5.3.30-SNAPSHOT/reference/html/web.html mvc-themeresolver).
MultipartResolver The abstraction is used to parse multipart requests (e.g. browser form file uploads) with the help of some multipart parsing libraries. Seemultipart parsers.
FlashMapManager Stores and retrieves "input" and "output" "FlashMap"s that can be used to pass attributes from one request to another, typically through redirects. SeeFlash properties

These classes or interfaces in the table are all member attributes of DispatcherServlet. Understanding the role of member attributes actually also understands the role of DispatcherServlet.

2.4 Custom DispatcherServlet supplement

Two parts:

  1. Web MVC Config: Defines a special bean in 2.3 that will fall back to the default type listed in DispatcherServlet.properties if there is no matching bean type.
  2. Servlet Config: Reference 2.1.

2.5 Processing process

Insert image description here

2.6 Path matching

In versions prior to Spring MVC 5.3, we faced the following issues with decoding requestURI (requested URI):

  1. URL encoding problem: When the browser sends a request with special characters or non-ASCII characters, these characters will be automatically URL encoded by the browser, that is, the special characters will be converted into % Followed by the ASCII representation of the character. For example, spaces will be encoded as %20, Chinese characters will be encoded as %E4%BD%A0, etc. In the old version of Spring MVC, requestURI maintains encoding by default, that is, the URL is not decoded.

  2. Chinese garbled code problem: SincerequestURI is passed to the server after the browser encodes it, the server will restore the ASCII representation after % to the original by default characters, but for Chinese characters, the old version of Spring MVC will have the problem of Chinese garbled characters. For example, %E4%BD%A0 will be decoded into garbled characters instead of correct Chinese characters.

These issues may cause the application to not correctly handle requests with special or non-ASCII characters, resulting in issues such as garbled characters or parameter parsing errors.

PathPattern and AntPathMatcher are two tools for matching path patterns.

  1. AntPathMatcher:
    AntPathMatcher is one of the path matchers provided in the Spring framework, which is based on Ant-style path pattern matching. Ant-style path patterns use wildcards to represent certain parts of the path, such as ? to match any single character, * to match any number of characters (including 0 characters), ** means matching any number of paths (including 0 path segments). AntPathMatcher can be used to match file paths, URL paths, etc.

For example, using AntPathMatcher you can perform the following path matching:

  • /user/? can match /user/1 but not /user/1/friends
  • /user/* matches /user/1 and /user/1/friends
  • /user/** matches /user/1 and /user/1/friends
  1. PathPattern:

PathPattern is a class introduced by Spring Framework 5.3 to solve the problem of URL path pattern matching. In web application development, matching and parsing input URL paths is a common requirement. PathPattern provides a more flexible and powerful way to handle URL path patterns.

PathPatternThe following issues are resolved:

  1. Flexible matching of URL paths: Traditional URL path matching is based on string matching and cannot handle complex path pattern matching requirements. PathPattern Supports the use of path variables, wildcards, regular expressions, etc. to build flexible URL path matching patterns. For example, you can match , and other paths through /{category}/{id}, and match and < /span> is extracted as a variable. /books/123/movies/456{category}{id}

  2. Extraction and parsing of path parameters:PathPattern The path parameters can be extracted from the matching URL path and converted into the corresponding data type. Path parameters can be used to dynamically pass data. For example, in /books/123 can be extracted and parsed as path parameters. 123

  3. RESTful routing and resource mapping:PathPattern can be integrated with Spring Web MVC or Spring WebFlux for RESTful routing and resource mapping. By defining and matching path patterns, requests can be more easily mapped to corresponding processor methods, and multiple flexible path matching patterns are supported.

  4. Safe path matching:PathPattern Canonicalizing and standardizing URL paths provides more secure path matching. It handles URL encoding, decoding, and canonicalization, avoiding the introduction of potential security holes when handling path matching.

Compared with AntPathMatcher, PathPattern provides richer and more flexible path matching functions. PathPattern performs more stringent verification of paths and supports more pattern matching rules, including path segment matching, path parameter matching, query parameter matching, etc.

For example, using PathPattern you can perform the following path matching:

  • /user/{id} can match /user/1 but not /user/1/friends
  • /user/{id}/** matches /user/1 and /user/1/friends
  • /user/{id:\\d+} can match /user/1 but not /user/abc

If you use Spring Boot 2.6.x in your project, its path matching format is PathPattern. If you want to integrate Swagger, please note that an error will be reported at startup. You need to modify the path matching rules of Spring MVC to Ant style:

spring.mvc.pathmatch.matching-strategy=ant_path_matcher

2.7 View analysis

Spring MVC defines ViewResolver and View interfaces that allow you to render models in the browser without binding you to a specific view technology. ViewResolver provides a mapping between view names and actual views. Views handle the preparation of data before handing it over to a specific view technology.

The following table provides more details of the ViewResolver hierarchy:

ViewResolver Description
AbstractCachingViewResolver Subclasses of 'AbstractCachingViewResolver' cache the view instances they resolve. Caching improves the performance of certain view technologies. You can turn off caching by setting the 'cache' property to 'false'. Additionally, if you must refresh a certain view at runtime (for example, when a FreeMarker template is modified), you can use the 'removeFromCache(String viewName, Locale loc)' method.
UrlBasedViewResolver A simple implementation of the ViewResolver interface that can directly resolve logical view names into URLs without the need for explicit mapping definitions. This is appropriate if your logical name matches the name of the view resource in a direct way, without requiring arbitrary mapping.
InternalResourceViewResolver Convenient subclass of 'UrlBasedViewResolver' that supports 'InternalResourceView' (actually, servlets and jsps) and subclasses such as 'JstlView' and 'TilesView'. You can use 'setViewClass(...)' to specify a view class for all views generated by this parser. See the ’ UrlBasedViewResolver ’ javadoc for details.
FreeMarkerViewResolver Convenient UrlBasedViewResolver subclass that supports FreeMarkerView and custom subclasses.
ContentNegotiatingViewResolver Implementation of the 'ViewResolver' interface, which resolves views based on request file names or 'Accept' headers. See [Content Negotiation](https://docs.spring.io/spring-framework/docs/5.3.30-SNAPSHOT/reference/html/web.html#mvc-multiple-representations).
`BeanNameViewResolver ’ ViewResolver An implementation of the interface that interprets view names into bean names in the current application context. This is a very flexible variant that allows mixing and matching different view types based on different view names. Each such "view" can be defined as a bean, for example in XML or a configuration class.

2.8Multipart Resolver

MultipartResolver is a strategy for parsing multipart requests (includingfile uploads). There is one implementation based on Commons FileUpload and another implementation based on Servlet 3.0 multipart request parsing.

Commons FileUpload traditionally only works with POST requests, but accepts any multipart/content type. See the commonsmmultipartresolver javadoc for details and configuration options.

Servlet 3.0 multipart parsing needs to be enabled through the Servlet container configuration. By default it will try to parse any multipart/content-type with any HTTP method, but this may not be supported by all Servlet containers. See the StandardServletMultipartResolver javadoc for details and configuration options.

3 Annotated Controller Handler

Spring MVC provides an annotation-based programming model, in which @Controller and @RestController components use annotations to express request mapping, request input, exception handling, etc. Annotated controllers have flexible method signatures and do not have to extend the base class or implement a specific interface. The following example shows a controller defined by annotations:

@Controller
public class HelloController {

    @GetMapping("/hello")
    public String handle(Model model) {
        model.addAttribute("message", "Hello World!");
        return "index";
    }
}

In the previous example, this method accepts a Model and returns the view name as a string, but there are many other options, which we will explain later in this chapter.

@RestController is a compound annotation that itself has meta-annotations of @Controller and @ResponseBody to indicate that each method of the controller inherits the type-level @ResponseBody annotation and, therefore, writes the response body directly instead of using HTML Templates perform view parsing and rendering. So in our Spring Boot project, when defining page routing, WebController should use @Controller annotation instead of @RestController.

3.1Request Mapping

You can use the @RequestMapping annotation to map requests to controller methods. It has various properties that can be matched based on URL, HTTP method, request parameters, headers and media type. You can use it at the class level to represent a shared mapping, or at the method level to narrow down to a specific endpoint mapping.

There are also HTTP method specific shortcut variants of @RequestMapping:

  • @GetMapping
  • @PostMapping
  • @PutMapping
  • @DeleteMapping
  • @PatchMapping

The shortcut is to provide a custom annotation since most controller methods should be mapped to specific HTTP methods instead of using @RequestMapping which by default matches all HTTP methods. A @RequestMapping is still required at the class level to express shared mapping.

The following example has type and method level mapping:

@RestController
@RequestMapping("/persons")
class PersonController {

    @GetMapping("/{id}")
    public Person getPerson(@PathVariable Long id) {
        // ...
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public void add(@RequestBody Person person) {
        // ...
    }
}

3.2 Method parameters

Controller method argument Description
WebRequest, NativeWebRequest Generic access to request parameters and request and session attributes, without direct use of the Servlet API.
javax.servlet.ServletRequest,javax.servlet.ServletResponse Choose any specific request or response type — for example, ServletRequest, HttpServletRequest, or Spring’s MultipartRequest, MultipartHttpServletRequest.
javax.servlet.http.HttpSession Enforces the presence of a session. As a consequence, such an argument is never null. Note that session access is not thread-safe. Consider setting the RequestMappingHandlerAdapter instance’s synchronizeOnSession flag to true if multiple requests are allowed to concurrently access a session.
javax.servlet.http.PushBuilder Servlet 4.0 push builder API for programmatic HTTP/2 resource pushes. Note that, per the Servlet specification, the injected PushBuilder instance can be null if the client does not support that HTTP/2 feature.
java.security.Principal Currently authenticated user — possibly a specific Principal implementation class if known.Note that this argument is not resolved eagerly, if it is annotated in order to allow a custom resolver to resolve it before falling back on default resolution via HttpServletRequest#getUserPrincipal. For example, the Spring Security Authentication implements Principal and would be injected as such via HttpServletRequest#getUserPrincipal, unless it is also annotated with @AuthenticationPrincipal in which case it is resolved by a custom Spring Security resolver through Authentication#getPrincipal.
HttpMethod The HTTP method of the request.
java.util.Locale The current request locale, determined by the most specific LocaleResolver available (in effect, the configured LocaleResolver or LocaleContextResolver).
java.util.TimeZone + java.time.ZoneId The time zone associated with the current request, as determined by a LocaleContextResolver.
java.io.InputStream, java.io.Reader For access to the raw request body as exposed by the Servlet API.
java.io.OutputStream, java.io.Writer For access to the raw response body as exposed by the Servlet API.
@PathVariable For access to URI template variables. See URI patterns.
@MatrixVariable For access to name-value pairs in URI path segments. See Matrix Variables.
@RequestParam For access to the Servlet request parameters, including multipart files. Parameter values are converted to the declared method argument type. See @RequestParam as well as Multipart.Note that use of @RequestParam is optional for simple parameter values. See “Any other argument”, at the end of this table.
@RequestHeader For access to request headers. Header values are converted to the declared method argument type. See @RequestHeader.
@CookieValue For access to cookies. Cookies values are converted to the declared method argument type. See @CookieValue.
@RequestBody For access to the HTTP request body. Body content is converted to the declared method argument type by using HttpMessageConverter implementations. See @RequestBody.
HttpEntity<B> For access to request headers and body. The body is converted with an HttpMessageConverter. See HttpEntity.
@RequestPart For access to a part in a multipart/form-data request, converting the part’s body with an HttpMessageConverter. See Multipart.
java.util.Map, org.springframework.ui.Model, org.springframework.ui.ModelMap For access to the model that is used in HTML controllers and exposed to templates as part of view rendering.
RedirectAttributes Specify attributes to use in case of a redirect (that is, to be appended to the query string) and flash attributes to be stored temporarily until the request after redirect. See Redirect Attributes and Flash Attributes.
@ModelAttribute For access to an existing attribute in the model (instantiated if not present) with data binding and validation applied. See @ModelAttribute as well as Model and DataBinder.Note that use of @ModelAttribute is optional (for example, to set its attributes). See “Any other argument” at the end of this table.
Errors, BindingResult For access to errors from validation and data binding for a command object (that is, a @ModelAttribute argument) or errors from the validation of a @RequestBody or @RequestPart arguments. You must declare an Errors, or BindingResult argument immediately after the validated method argument.
SessionStatus + class-level @SessionAttributes For marking form processing complete, which triggers cleanup of session attributes declared through a class-level @SessionAttributes annotation. See @SessionAttributes for more details.
UriComponentsBuilder For preparing a URL relative to the current request’s host, port, scheme, context path, and the literal part of the servlet mapping. See URI Links.
@SessionAttribute For access to any session attribute, in contrast to model attributes stored in the session as a result of a class-level @SessionAttributes declaration. See @SessionAttribute for more details.
@RequestAttribute For access to request attributes. See @RequestAttribute for more details.
Any other argument If a method argument is not matched to any of the earlier values in this table and it is a simple type (as determined by BeanUtils#isSimpleProperty), it is resolved as a @RequestParam. Otherwise, it is resolved as a @ModelAttribute.

上述表格中为@Controller中方法的参数和参数注解,具体含义不翻译了可自行百度。有几个常见的、重要的还是有必要去了解的:javax.servlet.ServletRequest, javax.servlet.ServletResponsejavax.servlet.http.HttpSession@RequestBody,@PathVariable,@RequestParam

3.3返回值

Controller method return value Description
@ResponseBody The return value is converted through HttpMessageConverter implementations and written to the response. See @ResponseBody.
HttpEntity<B>, ResponseEntity<B> The return value that specifies the full response (including HTTP headers and body) is to be converted through HttpMessageConverter implementations and written to the response. See ResponseEntity.
HttpHeaders For returning a response with headers and no body.
String A view name to be resolved with ViewResolver implementations and used together with the implicit model — determined through command objects and @ModelAttribute methods. The handler method can also programmatically enrich the model by declaring a Model argument (see Explicit Registrations).
View A View instance to use for rendering together with the implicit model — determined through command objects and @ModelAttribute methods. The handler method can also programmatically enrich the model by declaring a Model argument (see Explicit Registrations).
java.util.Map, org.springframework.ui.Model Attributes to be added to the implicit model, with the view name implicitly determined through a RequestToViewNameTranslator.
@ModelAttribute An attribute to be added to the model, with the view name implicitly determined through a RequestToViewNameTranslator.Note that @ModelAttribute is optional. See “Any other return value” at the end of this table.
ModelAndView object The view and model attributes to use and, optionally, a response status.
void A method with a void return type (or null return value) is considered to have fully handled the response if it also has a ServletResponse, an OutputStream argument, or an @ResponseStatus annotation. The same is also true if the controller has made a positive ETag or lastModified timestamp check (see Controllers for details).If none of the above is true, a void return type can also indicate “no response body” for REST controllers or a default view name selection for HTML controllers.
DeferredResult<V> Produce any of the preceding return values asynchronously from any thread — for example, as a result of some event or callback. See Asynchronous Requests and DeferredResult.
Callable<V> Produce any of the above return values asynchronously in a Spring MVC-managed thread. See Asynchronous Requests and Callable.
ListenableFuture<V>, java.util.concurrent.CompletionStage<V>, java.util.concurrent.CompletableFuture<V> Alternative to DeferredResult, as a convenience (for example, when an underlying service returns one of those).
ResponseBodyEmitter, SseEmitter Emit a stream of objects asynchronously to be written to the response with HttpMessageConverter implementations. Also supported as the body of a ResponseEntity. See Asynchronous Requests and HTTP Streaming.
StreamingResponseBody Write to the response OutputStream asynchronously. Also supported as the body of a ResponseEntity. See Asynchronous Requests and HTTP Streaming.
Reactor and other reactive types registered via ReactiveAdapterRegistry A single value type, e.g. Mono, is comparable to returning DeferredResult. A multi-value type, e.g. Flux, may be treated as a stream depending on the requested media type, e.g. “text/event-stream”, “application/json+stream”, or otherwise is collected to a List and rendered as a single value. See Asynchronous Requests and Reactive Types.
Other return values If a return value remains unresolved in any other way, it is treated as a model attribute, unless it is a simple type as determined by BeanUtils#isSimpleProperty, in which case it remains unresolved.

3.4Jackson

Jackson是一个Java库,用于处理JSON格式的数据。它提供了一组强大的功能,可以在Java对象和JSON之间进行转换,包括序列化(将Java对象转换为JSON字符串)和反序列化(将JSON字符串转换为Java对象)。

以下是Jackson的主要作用:

  1. 对象序列化和反序列化:Jackson可以将Java对象转换为JSON字符串,以及将JSON字符串转换为Java对象。这对于在Java应用程序和前端或其他服务之间传递数据时非常有用。

  2. 数据绑定:Jackson可以将JSON数据绑定到Java对象上,并将JSON数据中的属性值映射到Java对象的相应属性上。这使得在处理JSON数据时可以轻松地将其转换为Java对象,并进行操作。

  3. 数据格式化和解析:Jackson提供了灵活的方式来格式化(美化)JSON数据并解析复杂的JSON结构。它支持各种JSON格式,如数组、嵌套对象、键值对等。

  4. 支持注解:Jackson支持在Java对象中使用注解,以控制JSON序列化和反序列化的行为。通过注解,可以自定义属性的命名、忽略某些属性、处理日期格式等。

  5. 支持流式API:Jackson提供了流式的API,可以逐行读取JSON数据,并进行处理,而不需要将整个JSON字符串加载到内存中。这对于处理大型JSON数据或实时流式数据非常有用。

Spring框架提供了对Jackson JSON库的全面支持,包括以下几个方面的应用:

  1. JSON序列化和反序列化:Spring使用Jackson库作为默认的JSON序列化和反序列化工具。在处理HTTP请求和响应时,Spring MVC框架会自动将Java对象转换为JSON格式的响应数据,并将接收到的JSON数据转换为Java对象。这使得开发人员可以在控制器方法中直接使用Java对象,而不需要手动处理JSON数据的转换。

  2. HTTP message converters: Spring provides a set of HTTP message converters, including one for JSON format using the Jackson library. These converters allow developers to easily convert between Java objects and JSON data when processing HTTP requests and responses.

  3. annotation support: Spring provides support for Jackson library annotations, including @JsonSerialize, @JsonDeserialize, @JsonProperty, etc. Through these annotations, developers can customize JSON serialization and deserialization rules for Java objects, including attribute naming, type conversion, date formatting, etc.

  4. Configuration options: Spring allows developers to have fine-grained control over the configuration of the Jackson library. For example, you can configure Jackson's characteristics, such as whether to indent JSON output, whether to ignore null attributes, etc. Through configuration options, developers can adjust JSON serialization and deserialization behavior based on specific needs.

  5. Support other JSON libraries: Although Spring uses the Jackson library for JSON processing by default, it also supports other JSON libraries such as Gson, FastJson, etc. Developers can choose the appropriate JSON library for integration according to their preferences and project needs, and configure it in Spring.

In short, through Spring's support for the Jackson JSON library, developers can process JSON data more conveniently and convert between Java objects and JSON data. This provides convenience for scenarios such as developing RESTful APIs and handling front-end and back-end data interaction, and improves development efficiency and code readability.

4Asynchronous requests

Spring MVC has extensive integration with Servlet 3.0 asynchronous request handling:

DeferredResult and Callable return values ​​in controller methods provide basic support for a single asynchronous return value.

The controller can stream multiple values, including SSE and raw data.

4.1DeferredResult

Once the asynchronous request handling feature is enabled in a servlet container, controller methods can wrap any supported controller method return value with a DeferredResult, as shown in the following example:

@GetMapping("/quotes")
@ResponseBody
public DeferredResult<String> quotes() {
    DeferredResult<String> deferredResult = new DeferredResult<String>();
    // Save the deferredResult somewhere..
    return deferredResult;
}

// From some other thread...
deferredResult.setResult(result);

Controllers can generate return values ​​asynchronously from different threads - for example, in response to external events (JMS messages), scheduled tasks, or other events.

4.2Callable

Controllers can wrap any supported return value with java.util.concurrent. can be called, as shown in the following example:

@PostMapping
public Callable<String> processUpload(final MultipartFile file) {

    return new Callable<String>() {
        public String call() throws Exception {
            // ...
            return "someView";
        }
    };
}

The return value can then be obtained by running the given task through the configured TaskExecutor.

Guess you like

Origin blog.csdn.net/qq_27890899/article/details/131967903