Summary of Spring Web MVC Knowledge Points—Official Original

1. Filter

The spring-web module provides some useful filters (Filter):

  • Form Data
  • Forwarded Header
  • Shallow ETag
  • CORS

1. Form Data

Browsers can only submit form data via HTTP GET or HTTP POST, but non-browser clients can also use HTTP PUT, PATCH, and DELETE. The Servlet API requires  ServletRequest.getParameter*() methods to only support HTTP POST form field access.

spring-web The module is provided  FormContentFilter to intercept  application/x-www-form-urlencoded HTTP PUT, PATCH and DELETE requests whose content type is, read form data from the request body, and wrap it  ServletRequestto make the form data available through  ServletRequest.getParameter*() a series of methods.

2. Forwarded Header

When a request goes through a proxy (like a load balancer), the host, port, and scheme can change, making it a challenge to create a link to the correct host, port, and scheme from the client's perspective.

RFC 7239  defines  Forwarded HTTP headers that proxies can use to provide information about the original request. There are other non-standard headers, including  X-Forwarded-Host, X-Forwarded-Port, X-Forwarded-Proto, X-Forwarded-SSL and  X-Forwarded-Prefix.

ForwardedHeaderFilter is a servlet filter that modifies the request to a)  Forwarded change the host, port, and scheme based on the headers, and b) remove those headers to eliminate further effects. This filter relies on wrapping the request, so it must come before other filters, e.g.  RequestContextFilterit should work with the modified request instead of the original request.

There are security considerations for forwarded headers, since the application has no way of knowing whether these headers were added by a proxy or by a malicious client. This is why proxies at trust boundaries should be configured to drop untrusted  Forwarded headers from outside. You can also  ForwardedHeaderFilter configure  removeOnly=true, in which case it will remove but not use these headers.

To support asynchronous requests and error dispatch, this filter should be   mapped with DispatcherType.ASYNC and  . DispatcherType.ERRORIf using the Spring Framework  AbstractAnnotationConfigDispatcherServletInitializer, all filters are automatically registered for all dispatch types. However, if passing  or  registering filters  web.xml in Spring Boot  , make sure  to include in addition to   and  .FilterRegistrationBeanDispatcherType.ASYNCDispatcherType.ERRORDispatcherType.REQUEST

3. Shallow ETag

ShallowEtagHeaderFilter Creates a "shallow" ETag by caching the content written to the response and computing the MD5 hash. If-None-Match The next time the client sends, it does the same thing, but it also compares the calculated value with the  request header, and returns a 304 (NOT_MODIFIED) if the two are equal.

This strategy saves network bandwidth, but not CPU, since the full response must be calculated for each request. Other strategies at the controller level, described earlier, can avoid the occurrence of calculations

This filter has a  writeWeakETag parameter that configures the filter to write weak ETags like this: W/"02a2d595e6ed9a0b24f027f2b63b134d6"

为了支持 异步请求,这个过滤器必须用 DispatcherType.ASYNC 来映射,这样过滤器就可以延迟并成功地生成ETag到最后一个异步dispatch的结束。如果使用Spring框架的 AbstractAnnotationConfigDispatcherServletInitializer(见 Servlet 配置),所有过滤器都会自动注册为所有的dispatch类型。然而,如果通过 web.xml 或Spring Boot中的 FilterRegistrationBean 注册过滤器,请确保包含 DispatcherType.ASYNC。

4. CORS

Spring MVC provides fine-grained support for CORS configuration through annotations on controllers. However, when used with Spring Security, we recommend relying on the built-in  CorsFilter, which must be ordered before Spring Security's filter chain.

2. Annotated Controller

Spring MVC provides an annotation-based programming model where  components @Controller and  @RestController components use annotations to express request mapping, request input, exception handling, and more. Annotated controllers have flexible method signatures, do not need to inherit a base class, and do not need to 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, the method takes a  Modeland returns a  String view name, but many other options exist and are explained later in this chapter.

1. Declaration

You can  WebApplicationContext define the controller bean by using the standard Spring bean definition in the servlet.  The stereotype allows auto-detection, consistent with Spring's general support @Controller for detecting classes in the classpath  and auto-registering bean definitions for them. @ComponentIt is also a stereotype of the annotated class, indicating that it is a web component.

To achieve  @Controller automatic detection of such beans, you can add component scanning to your Java configuration, as shown in the following example:

@Configuration
@ComponentScan("org.example.web")
public class WebConfig {

    // ...
}

The following example shows the XML configuration equivalent of the previous example: 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="org.example.web"/>

    <!-- ... -->

</beans>

@RestController is a composed annotation, which itself is a meta-annotation composed of @Controller and @ResponseBody, indicating that each method of a controller inherits the type-level @ResponseBody annotation, so write directly to the response body instead of using HTML templates for view parsing and rendering.

AOP proxy

In some cases, you may need to decorate a controller with an AOP proxy at runtime. An example is if you choose to use annotations directly on the controller  @Transactional . In such cases, especially for controllers, we recommend using class-based proxies, where such annotations automatically appear on controllers directly.

If the controller implements an interface and requires AOP proxies, you may need to configure class-based proxies explicitly. For example, for  @EnableTransactionManagement, you can change to  @EnableTransactionManagement(proxyTargetClass = true), and for  <tx:annotation-driven/>, you can change to  <tx:annotation-driven proxy-target-class="true"/>.

2. Request Mapping

You can use  @RequestMapping annotations to map requests to controller methods. It has various attributes that can be matched by URL, HTTP method, request parameters, headers and media type (meida type). You can use it at the class level to express shared mappings, or at the method level to narrow down to a specific endpoint mapping.

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

  • @GetMapping

  • @PostMapping

  • @PutMapping

  • @DeleteMapping

  • @PatchMapping

捷径是 自定义注解,因为可以说,大多数 controller 方法应该被映射到一个特定的HTTP方法,而不是使用 @RequestMapping,默认情况下,它匹配所有的HTTP方法。在类的层面上仍然需要一个 @RequestMapping 来表达共享映射。 下面的例子有类和方法层面的映射:

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

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

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

URI pattern
@RequestMapping methods can be mapped using a URL pattern. There are two options:

  • PathPattern — A preparse pattern that matches the URL path, is also preparsed to  PathContainer. This parsing scheme is designed for web usage, and it handles encoding and path parameters efficiently, and does matching efficiently.

  • AntPathMatcher — matches the string pattern and the string path. This is also the original resolution scheme used in Spring configuration to select classpath, filesystem and other location resources. It's less efficient, and string path input is a challenge to efficiently handle URL encoding and other issues.

PathPattern is the recommended resolution scheme for web applications and the only choice for Spring WebFlux. It is enabled in Spring MVC since version 5.3 and is enabled by default since version 6.0.

PathPatternAntPathMatcher The same pattern syntax  as is supported  . Additionally, it supports capturing patterns, e.g.  {*spring}for matching 0 or more path segments at the end of a path. PathPattern Also restricts  ** its use when matching multiple path segments, ie it is only allowed at the end of the pattern. This removes a lot of ambiguity in choosing the best matching pattern for a given request.

Some example patterns:

  • "/resources/ima?e.png" - matches a single character in the path segment

  • "/resources/*.png" - matches zero or more characters in a path segment

  • "/resources/**" - matches multiple path segments

  • "/projects/{project}/versions" - matches a path segment and captures it as a variable

  • "/projects/{project:[a-z]+}/versions" - Matches and captures a variable with regex

Captured URI variables can be  @PathVariable accessed with . For example:

@GetMapping("/owners/{ownerId}/pets/{petId}")
public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) {
    // ...
}

You can declare URI variables at the class and method level, as shown in the following example:

@Controller
@RequestMapping("/owners/{ownerId}")
public class OwnerController {

    @GetMapping("/pets/{petId}")
    public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) {
        // ...
    }
}

URI variables are automatically cast to the appropriate type, and raise otherwise  TypeMismatchException. Simple types ( int, long, Date etc.) are supported by default, you can register support for any other data type.

You can explicitly name URI variables (eg, @PathVariable("customId")), but if the names are the same, and your code is  -parameters compiled with compiler flags, you can ignore this detail.

Syntax  {varName:regex} Declare a URI variable with a regular expression, the syntax is  {varName:regex}. For example, given a URL  "/spring-web-3.0.5.jar", the following method can extract the name, version, and file extension:

@GetMapping("/{name:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{ext:\\.[a-z]+}")
public void handle(@PathVariable String name, @PathVariable String version, @PathVariable String ext) {
    // ...
}

URI path patterns can also have embedded  ${…​} placeholders, which are  PropertySourcesPlaceholderConfigurer resolved at startup by using against local, system, environment and other property sources. For example, you can use this to parameterize the base URL according to some external configuration.

Pattern comparison
When multiple patterns match a URL, the best match must be chosen. This is done depending on whether using the parsed PathPattern is enabled or not using:

  • PathPattern.SPECIFICITY_COMPARATOR
  • AntPathMatcher.getPatternComparator(String path)

Both help to classify patterns, more specific patterns are above. A pattern is less specific if it has fewer URI variables (counts as 1), single wildcards (counts as 1), and double wildcards (counts as 2). In the case of the same score, the longer pattern is chosen. Given the same score and length, select the pattern with more URI variables than wildcards.
The default mapping patterns (/**) are excluded from scoring and are always sorted last. Also, prefixed patterns such as /public/** are considered less specific than other patterns without double wildcards.
For full details, follow the above link to see pattern Comparators (Comparators).

Guess you like

Origin blog.csdn.net/leesinbad/article/details/130040283