springboot2.6.2系列教程之Spring Web MVC 框架-9

目录

      • Spring Web MVC 框架
        • Spring MVC 自动配置
        • HttpMessage转换器
        • 自定义 JSON 序列化器和反序列化器
        • 静态内容
        • 欢迎页面
        • 路径匹配和内容协商
        • 模板引擎
        • 错误处理
        • CORS 支持

Spring Web MVC 框架

Spring MVC是一个丰富的“模型视图控制器”Web 框架。Spring MVC 允许您创建特殊的@Controller@RestControllerbean 来处理传入的 HTTP 请求。控制器中的方法通过使用@RequestMapping注解映射到 HTTP。

以下代码显示了一个典型@RestController的提供 JSON 数据的代码:

@RestController
@RequestMapping("/users")
public class MyRestController {

    private final UserRepository userRepository;

    private final CustomerRepository customerRepository;

    public MyRestController(UserRepository userRepository, CustomerRepository customerRepository) {
        this.userRepository = userRepository;
        this.customerRepository = customerRepository;
    }

    @GetMapping("/{user}")
    public User getUser(@PathVariable Long userId) {
        return this.userRepository.findById(userId).get();
    }

    @GetMapping("/{user}/customers")
    public List<Customer> getUserCustomers(@PathVariable Long userId) {
        return this.userRepository.findById(userId).map(this.customerRepository::findByUser).get();
    }

    @DeleteMapping("/{user}")
    public void deleteUser(@PathVariable Long userId) {
        this.userRepository.deleteById(userId);
    }

}
Spring MVC 自动配置

Spring Boot 为 Spring MVC 提供了自动配置,适用于大多数应用程序。

自动配置在 Spring 的默认值之上添加了以下特性:

  • 包括ContentNegotiatingViewResolverBeanNameViewResolver豆类。
  • 支持提供静态资源,包括对 WebJars 的支持。
  • 自动注册ConverterGenericConverterFormatterbean。
  • 支持HttpMessageConverters
  • 自动注册MessageCodesResolver
  • 静态index.html支持。
  • ConfigurableWebBindingInitializerbean的自动使用。

如果您想保留那些 Spring Boot MVC 自定义并进行更多MVC 自定义(拦截器、格式化程序、视图控制器和其他功能),您可以添加自己@Configuration的类型类WebMvcConfigurer 添加@EnableWebMvc.

如果您想提供、 或的自定义实例RequestMappingHandlerMapping,并且仍然保留 Spring Boot MVC 自定义,则可以声明一个类型的 bean并使用它来提供这些组件的自定义实例。``

如果你想完全控制 Spring MVC,你可以添加你自己的@Configuration注释@EnableWebMvc,或者添加你自己的@Configuration-annotated DelegatingWebMvcConfiguration,如@EnableWebMvc.

HttpMessage转换器

Spring MVC 使用该HttpMessageConverter接口来转换 HTTP 请求和响应。明智的默认设置是开箱即用的。例如,对象可以自动转换为 JSON(通过使用 Jackson 库)或 XML(通过使用 Jackson XML 扩展,如果可用,或者通过使用 JAXB,如果 Jackson XML 扩展不可用)。默认情况下,字符串以UTF-8.

如果需要添加或自定义转换器,可以使用 Spring Boot 的HttpMessageConverters类,如下清单所示:

@Configuration(proxyBeanMethods = false)
public class MyHttpMessageConvertersConfiguration {

    @Bean
    public HttpMessageConverters customConverters() {
        HttpMessageConverter<?> additional = new AdditionalHttpMessageConverter();
        HttpMessageConverter<?> another = new AnotherHttpMessageConverter();
        return new HttpMessageConverters(additional, another);
    }

}

HttpMessageConverter上下文中存在的任何bean 都将添加到转换器列表中。您也可以以相同的方式覆盖默认转换器。

自定义 JSON 序列化器和反序列化器

如果您使用 Jackson 来序列化和反序列化 JSON 数据,您可能需要编写自己的类JsonSerializerJsonDeserializer类。自定义序列化程序通常通过模块向 Jackson 注册,但 Spring Boot 提供了一个替代@JsonComponent注解,可以更轻松地直接注册 Spring Bean。

您可以直接在或实现上使用@JsonComponent注释。您还可以在包含序列化器/反序列化器作为内部类的类上使用它,如以下示例所示:JsonSerializer``JsonDeserializer``KeyDeserializer

@JsonComponent
public class MyJsonComponent {

    public static class Serializer extends JsonSerializer<MyObject> {

        @Override
        public void serialize(MyObject value, JsonGenerator jgen, SerializerProvider serializers) throws IOException {
            jgen.writeStringField("name", value.getName());
            jgen.writeNumberField("age", value.getAge());
        }

    }

    public static class Deserializer extends JsonDeserializer<MyObject> {

        @Override
        public MyObject deserialize(JsonParser jsonParser, DeserializationContext ctxt)
                throws IOException, JsonProcessingException {
            ObjectCodec codec = jsonParser.getCodec();
            JsonNode tree = codec.readTree(jsonParser);
            String name = tree.get("name").textValue();
            int age = tree.get("age").intValue();
            return new MyObject(name, age);
        }

    }

}

中的所有@JsonComponentbean 都会ApplicationContext自动向 Jackson 注册。因为@JsonComponent是用 元注释的@Component,所以通常的组件扫描规则适用。

Spring Boot 还提供了JsonObjectSerializerJsonObjectDeserializer类,它们在序列化对象时提供了标准 Jackson 版本的有用替代方案。

上面的例子可以重写为使用JsonObjectSerializer/JsonObjectDeserializer如下:

@JsonComponent
public class MyJsonComponent {

    public static class Serializer extends JsonObjectSerializer<MyObject> {

        @Override
        protected void serializeObject(MyObject value, JsonGenerator jgen, SerializerProvider provider)
                throws IOException {
            jgen.writeStringField("name", value.getName());
            jgen.writeNumberField("age", value.getAge());
        }

    }

    public static class Deserializer extends JsonObjectDeserializer<MyObject> {

        @Override
        protected MyObject deserializeObject(JsonParser jsonParser, DeserializationContext context, ObjectCodec codec,
                JsonNode tree) throws IOException {
            String name = nullSafeValue(tree.get("name"), String.class);
            int age = nullSafeValue(tree.get("age"), Integer.class);
            return new MyObject(name, age);
        }

    }

}
静态内容

默认情况下,Spring Boot 从类路径中名为/static(或/public/resources/META-INF/resources)的目录或从ServletContext. 它使用ResourceHttpRequestHandler来自 Spring MVC 的方法,因此您可以通过添加自己的方法WebMvcConfigurer并覆盖该addResourceHandlers方法来修改该行为。

在独立的 Web 应用程序中,容器中的默认 servlet 也被启用并充当后备,ServletContext如果 Spring 决定不处理它,则从根目录提供内容。大多数情况下,这不会发生(除非你修改了默认的 MVC 配置),因为 Spring 总是可以通过DispatcherServlet.

默认情况下,资源映射在 上/**,但您可以使用该spring.mvc.static-path-pattern属性对其进行调整。例如,将所有资源重新定位到/resources/**可以实现如下:

spring:
  mvc:
    static-path-pattern: "/resources/**"

您还可以使用该spring.web.resources.static-locations属性自定义静态资源位置(将默认值替换为目录位置列表)。根 servlet 上下文路径"/"也会自动添加为位置。

除了前面提到的“标准”静态资源位置之外,还为Webjars 内容做了一个特殊情况。/webjars/**如果以 Webjars 格式打包,则任何具有路径的资源都将从 jar 文件中提供。

欢迎页面

Spring Boot 支持静态和模板化的欢迎页面。index.html它首先在配置的静态内容位置中查找文件。如果没有找到,它会寻找一个index模板。如果找到其中任何一个,它会自动用作应用程序的欢迎页面。

路径匹配和内容协商

Spring MVC 可以通过查看请求路径并将其与应用程序中定义的映射匹配(例如,@GetMapping控制器方法上的注释)将传入的 HTTP 请求映射到处理程序。

Spring Boot 默认选择禁用后缀模式匹配,这意味着 like 的请求"GET /projects/spring-boot.json"不会匹配到@GetMapping("/projects/spring-boot")映射。这被认为是Spring MVC 应用程序的最佳实践。过去,此功能主要对未发送正确“Accept”请求标头的 HTTP 客户端有用;我们需要确保向客户端发送正确的内容类型。如今,内容协商更加可靠。

还有其他方法可以处理不能始终发送正确的“接受”请求标头的 HTTP 客户端。我们可以不使用后缀匹配,而是使用查询参数来确保请求 like"GET /projects/spring-boot?format=json"将被映射到@GetMapping("/projects/spring-boot")

spring:
  mvc:
    contentnegotiation:
      favor-parameter: true

或者,如果您更喜欢使用不同的参数名称:

spring:
  mvc:
    contentnegotiation:
      favor-parameter: true
      parameter-name: "myparam"

大多数标准媒体类型都支持开箱即用,但您也可以定义新的媒体类型:

spring:
  mvc:
    contentnegotiation:
      media-types:
        markdown: "text/markdown"

后缀模式匹配已弃用,并将在未来版本中删除。如果您了解这些警告并且仍然希望您的应用程序使用后缀模式匹配,则需要以下配置:

spring:
  mvc:
    contentnegotiation:
      favor-path-extension: true
    pathmatch:
      use-suffix-pattern: true

或者,与其打开所有后缀模式,不如只支持已注册的后缀模式更安全:

spring:
  mvc:
    contentnegotiation:
      favor-path-extension: true
    pathmatch:
      use-registered-suffix-pattern: true

从 Spring Framework 5.3 开始,Spring MVC 支持多种实现策略,用于将请求路径匹配到 Controller 处理程序。它以前只支持该AntPathMatcher策略,但现在它也提供PathPatternParser. Spring Boot 现在提供了一个配置属性来选择和选择新策略:

spring:
  mvc:
    pathmatch:
      matching-strategy: "path-pattern-parser"
模板引擎

除了 REST Web 服务,您还可以使用 Spring MVC 来提供动态 HTML 内容。Spring MVC 支持多种模板技术,包括 Thymeleaf、FreeMarker 和 JSP。此外,许多其他模板引擎包括他们自己的 Spring MVC 集成。

错误处理

默认情况下,Spring Boot 提供了一个/error以合理方式处理所有错误的映射,并将其注册为 servlet 容器中的“全局”错误页面。对于机器客户端,它会生成一个 JSON 响应,其中包含错误、HTTP 状态和异常消息的详细信息。对于浏览器客户端,有一个“whitelabel”错误视图,它以 HTML 格式呈现相同的数据

CORS 支持

它允许您以灵活的方式指定授权哪种跨域请求,而不是使用 IFRAME 或 JSONP 等一些不太安全和不太强大的方法。

从 4.2 版开始,Spring MVC支持 CORS。在 Spring Boot 应用程序中使用带有注释的控制器方法 CORS 配置@CrossOrigin不需要任何特定配置。 可以通过使用自定义方法注册 bean来定义全局 CORS 配置,如下例所示:

@Configuration(proxyBeanMethods = false)
public class MyCorsConfiguration {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {

            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/api/**");
            }

        };
    }

}

你可能感兴趣的:(springboot,spring,前端,mvc)