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

01 引言
上一期我们介绍了addArgumentResolvers和addReturnValueHandlers,分别用来请求参数的解析以及方法返回值的处理。我们继续WebMvcConfigurer配置的分享,这一期了解四个方法:
configureMessageConvertersextendMessageConvertersconfigureHandlerExceptionResolversextendHandlerExceptionResolvers
前两个是消息转化器,后两个是异常解析器。
02 方法13、14
configureMessageConverters
extendMessageConverters
java
default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
}
default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
}
作用:配置 HTTP 请求和响应的消息转换器。
使用场景:
- 自定义
JSON序列化/反序列化 - 支持新的数据格式
- 统一日期格式处理
2.1 使用说明
configureMessageConverters和extendMessageConverters都是用来配置消息转化器的,但是影响最终的结果。
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 问题解决
我们分别通过configureMessageConverters和extendMessageConverters来解决我们的问题。
配置configureMessageConverters
我们需要自定义的WebMvcConfigurer在WebMvcAutoConfigurationAdapter之前即可。我们先看看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配置的最后一期,期待一下吧!