【开发者必备】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配置的最后一期,期待一下吧!

相关推荐
saber_andlibert4 小时前
TCMalloc底层实现
java·前端·网络
逍遥德4 小时前
如何学编程之01.理论篇.如何通过阅读代码来提高自己的编程能力?
前端·后端·程序人生·重构·软件构建·代码规范
wangjialelele4 小时前
平衡二叉搜索树:AVL树和红黑树
java·c语言·开发语言·数据结构·c++·算法·深度优先
m0_481147334 小时前
拦截器跟过滤器的区别?拦截器需要注册吗?过滤器需要注册吗?
java
Coder_Boy_4 小时前
基于SpringAI的在线考试系统-相关技术栈(分布式场景下事件机制)
java·spring boot·分布式·ddd
独自破碎E4 小时前
【BISHI15】小红的夹吃棋
android·java·开发语言
冻感糕人~4 小时前
【珍藏必备】ReAct框架实战指南:从零开始构建AI智能体,让大模型学会思考与行动
java·前端·人工智能·react.js·大模型·就业·大模型学习
啦啦啦_99994 小时前
Redis实例-2
java
alice--小文子4 小时前
cursor-mcp工具使用
java·服务器·前端
进阶小白猿4 小时前
Java技术八股学习Day33
java·开发语言·学习