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

springboot2.6.2系列教程之Spring Web MVC 框架-9,第1张

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 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 的默认值之上添加了以下特性:

包括ContentNegotiatingViewResolver和BeanNameViewResolver豆类。支持提供静态资源,包括对 WebJars 的支持。自动注册Converter、GenericConverter和Formatterbean。支持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 数据,您可能需要编写自己的类JsonSerializer和JsonDeserializer类。自定义序列化程序通常通过模块向 Jackson 注册,但 Spring Boot 提供了一个替代@JsonComponent注解,可以更轻松地直接注册 Spring Bean。

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

@JsonComponent
public class MyJsonComponent {

    public static class Serializer extends JsonSerializer {

        @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 {

        @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 还提供了JsonObjectSerializer基JsonObjectDeserializer类,它们在序列化对象时提供了标准 Jackson 版本的有用替代方案。

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

@JsonComponent
public class MyJsonComponent {

    public static class Serializer extends JsonObjectSerializer {

        @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 {

        @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/**");
            }

        };
    }

}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5709816.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存