【开发者必备】Spring Boot 2.7.x:WebMvcConfigurer配置手册来了(六)!

关注我的公众号:【编程朝花夕拾】,可获取首发内容。

01 引言

上一期我们介绍了addArgumentResolversaddReturnValueHandlers,分别用来请求参数的解析以及方法返回值的处理。我们继续WebMvcConfigurer配置的分享,这一期了解四个方法:

  • configureMessageConverters
  • extendMessageConverters
  • configureHandlerExceptionResolvers
  • extendHandlerExceptionResolvers

前两个是消息转化器,后两个是异常解析器。

02 方法13、14

configureMessageConverters

extendMessageConverters

java 复制代码
default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
}

default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
}

作用:配置 HTTP 请求和响应的消息转换器。

使用场景

  • 自定义 JSON 序列化/反序列化
  • 支持新的数据格式
  • 统一日期格式处理

2.1 使用说明

configureMessageConvertersextendMessageConverters都是用来配置消息转化器的,但是影响最终的结果。

extendMessageConverters是追加在默认消息转化器的后面,而configureMessageConverters会覆盖默认的消息转化器。我们一起看看源码就知道了:

从源码可以看出,一旦配置了configureMessageConverters,会跳过默认的消息转化器。而extendMessageConverters不影响配置的和默认的消息转化器。

从源码可以看出默认的消息转化器有七个:

2.1 配置

假设我们只配置Fastjson的消息转化器和字符串的消息转化器。

java 复制代码
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    FastJsonConfig fastJsonConfig = new FastJsonConfig();

    FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
    fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);
    converters.add(fastJsonHttpMessageConverter);
}

@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    converters.add(new StringHttpMessageConverter(Charset.forName("GBK")));
}

2.3 测试

java 复制代码
@GetMapping("/testJSON")
public Wjson testWjsonReturn(@RequestBody Wjson wjson) {
    return wjson;
}

我们需要关注org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver#readWithMessageConverters()方法。

我们发现配置的信息放在了结尾,这不是我们预期的结果,我们希望fastJsonHttpMessageConverter在第一个,默认处理器不加载才对。

2.4 原因分析

见鬼了,明明源代码表示可以,但是结果却不是想象的那样。在跟踪源代码的时候的时候,发现WebMvcConfigurer的配置有两个:

第一个是WebMvcAutoConfiguration下的WebMvcAutoConfigurationAdapter,用来自动装配的,一定会加载默认的消息转化器。第二个才是我们定义的。所以当第一个配置类执行的时候,会加载默认消息转化器。

所以默认的消息转化器我们先不管,确保我们定义的configureMessageConverters在前面即可。

2.5 问题解决

我们分别通过configureMessageConvertersextendMessageConverters来解决我们的问题。

配置configureMessageConverters

我们需要自定义的WebMvcConfigurerWebMvcAutoConfigurationAdapter之前即可。我们先看看WebMvcAutoConfigurationAdapter的源码:

从图上可以知道源码通过@Order限制了加载的顺序,那我们只要将优先级高于@Order(0)即可。

配置extendMessageConverters

通过extendMessageConverters指定顺序,那么我们要确保我们的WebMvcConfigurer最后执行,所以无需@Order注解。利用list.add(inddex, xx)保证顺序。

java 复制代码
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    converters.add(0, new StringHttpMessageConverter(Charset.forName("GBK")));
}

效果如图:

03 方法15、16

configureHandlerExceptionResolvers

extendHandlerExceptionResolvers

java 复制代码
default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
}

default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
}

作用 :是 Spring MVC 异常处理体系中的核心配置方法,它允许开发者完全自定义应用程序的异常处理机制。

使用场景

  • 统一异常处理
  • 自定义异常处理

2.1 使用说明

见名知意,和上面介绍的消息转化器基本一致:

同样configureHandlerExceptionResolvers控制着是否加载默认的异常解析器。默认的异常解析器有三个:

HandlerExceptionResolver就是针对异常做出想用的处理:

2.2 自定义异常解析器

java 复制代码
/** AHandlerExceptionResolver **/
public class AHandlerExceptionResolver implements HandlerExceptionResolver {

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        System.out.println("AHandlerExceptionResolver....");
        return null;
    }
}


/** BHandlerExceptionResolver **/
public class BHandlerExceptionResolver implements HandlerExceptionResolver {

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        System.out.println("BHandlerExceptionResolver....");
        return null;
    }
}

返回值为null表示继续后面的异常解析器解析,返回ModelAndView表示异常解析中断,直接返回结果。

2.3 配置

java 复制代码
@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
    resolvers.add(new AHandlerExceptionResolver());
}

@Override
public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
    resolvers.add(new BHandlerExceptionResolver());
}

我们要验证配置了configureHandlerExceptionResolvers会不会取代默认的异常解析器。

2.4 测试

java 复制代码
@GetMapping("/testEx1")
public void testEx1()  {
    throw new RuntimeException("testEx1");
}

调用发现确实没有默认的处理器:

核心方法在这里:

org.springframework.web.servlet.handler.HandlerExceptionResolverComposite#resolveException

结果两个都执行了:

我们不配置configureHandlerExceptionResolvers,再试一下:

在两个都配置的情况下,AHandlerExceptionResolver直接返回数据。

再次测试

直接返回结果,BHandlerExceptionResolver没有再执行。

04 小结

这两组方法极其类似,但是使用的时候差异却很大。但是本质都是相同的。类别着记忆,也更容易记忆。今天的分享就到这里。下一期将是WebMvcConfigurer配置的最后一期,期待一下吧!

相关推荐
自由生长20246 小时前
JNI是什么?
程序员
一 乐6 小时前
婚纱摄影网站|基于ssm + vue婚纱摄影网站系统(源码+数据库+文档)
前端·javascript·数据库·vue.js·spring boot·后端
Boilermaker19926 小时前
[Java 并发编程] Synchronized 锁升级
java·开发语言
Cherry的跨界思维7 小时前
28、AI测试环境搭建与全栈工具实战:从本地到云平台的完整指南
java·人工智能·vue3·ai测试·ai全栈·测试全栈·ai测试全栈
alonewolf_997 小时前
JDK17新特性全面解析:从语法革新到模块化革命
java·开发语言·jvm·jdk
一嘴一个橘子7 小时前
spring-aop 的 基础使用(啥是增强类、切点、切面)- 2
java
码事漫谈7 小时前
Protocol Buffers 编码原理深度解析
后端
sheji34167 小时前
【开题答辩全过程】以 中医药文化科普系统为例,包含答辩的问题和答案
java
码事漫谈7 小时前
gRPC源码剖析:高性能RPC的实现原理与工程实践
后端
恋爱绝缘体18 小时前
2020重学C++重构你的C++知识体系
java·开发语言·c++·算法·junit