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

相关推荐
xiaoye20183 小时前
mybatis-plus 浅析
后端
qincloudshaw3 小时前
java中实现对象深克隆的四种方式
后端
caimo3 小时前
Java无法访问网址出现Timeout但是浏览器和Postman可以
java·开发语言·postman
Deamon Tree4 小时前
ElasticSearch架构和写入、更新、删除、查询的底层逻辑
java·大数据·elasticsearch·架构
代码哈士奇4 小时前
简单使用Nest+Nacos+Kafka实现微服务
后端·微服务·nacos·kafka·nestjs
一 乐4 小时前
商城推荐系统|基于SprinBoot+vue的商城推荐系统(源码+数据库+文档)
前端·数据库·vue.js·spring boot·后端·商城推荐系统
北极糊的狐4 小时前
IntelliJ IDEA插件:CodeGeeX 智能助手插件
java·ide·intellij-idea
golang学习记4 小时前
VMware 官宣 彻底免费:虚拟化新时代来临!
后端
悟能不能悟4 小时前
jdk25结构化并发和虚拟线程如何配合使用?有什么最佳实践?
java·开发语言