Spring MVC消息转换器的扩展

消息转换器是 Spring MVC 中用于实现 HTTP 请求/响应报文与 Java 对象相互转换的核心组件。它解决了控制器方法参数和返回值与不同数据格式(JSON、XML、文本等)的适配问题。

如果要单独指定一个属性的格式,可以为其添加@JsonFormat(pattern = "目标格式")注解来实现。但是在项目实际开发中,面对众多的实体类,这种方法显然不现实,此时就要来扩展MVC中的消息转换器,为全局 LocalDateTime指定格式。

java 复制代码
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")  
private LocalDateTime createTime;

本文以格式化时间数据为例,来简述如何实现消息转换器的扩展。

首先,我们要在继承了WebMvcConfigurationSupport类的配置类中重写extendMessageConverters方法,在方法体中实现扩展。

java 复制代码
/**  
 * 配置类,注册web层相关组件  
 */  
@Slf4j  
@Configuration  
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
	  
    /**  
     * 扩展Spring MVC框架的消息转换器  
     * @param converters  
     */  
    @Override  
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {  
        log.info("扩展消息转换器...");
        
        //创建消息转换器对象  
        MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();  
  
        //为消息转换器设置一个对象转换器,对象转换器可以将java对象转为json  
        messageConverter.setObjectMapper(new JacksonObjectMapper());  
  
        //将上面的消息转换器对象追加到mvc框架的转换器集合中  
        converters.add(0,messageConverter);  
    }  
}

方法体中,先new一个空白的消息转换器对象,再为其设置对象转换器,并将自己设置的消息转换器加入框架的转换器集合中,同时设置高优先级确保其生效。

对象转换器的实现:

java 复制代码
/**  
 * 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象  
 * 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]  
 * 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]  
 */public class JacksonObjectMapper extends ObjectMapper {  
  
    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";  
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";  
    public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";  
  
    public JacksonObjectMapper() {  
        super();  
        //收到未知属性时不报异常  
        this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);  
  
        //反序列化时,属性不存在的兼容处理  
        this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);  
  
        SimpleModule simpleModule = new SimpleModule()  
                .addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))  
                .addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))  
                .addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))  
                .addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))  
                .addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))  
                .addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));  
  
        //注册功能模块 例如,可以添加自定义序列化器和反序列化器  
        this.registerModule(simpleModule);  
    }  
}

通过继承ObjectMapper类自定义一个对象映射其,实现在序列化和反序列化过程中强行设置时间格式:

  1. 定义三种时间类型的默认格式。
  2. 忽略其他属性,避免在序列化过程中出现异常
  3. 注册时间类型的自定义序列化器/反序列化器
  4. 注册模块

特别注意:

  1. 对象转换器部分的代码较为固定,可以直接CV
  2. 由于本文的时间格式在序列化和反序列化中实现,所以在接收请求体参数,响应Java对象等大部分场景都有效。但是,当在Controller层接收Query参数和路径参数时,由于不涉及序列化和反序列化,依然需要手动添加注解来为其指定正确的格式
相关推荐
青云计划7 小时前
知光项目知文发布模块
java·后端·spring·mybatis
Victor3567 小时前
MongoDB(9)什么是MongoDB的副本集(Replica Set)?
后端
Victor3567 小时前
MongoDB(8)什么是聚合(Aggregation)?
后端
yeyeye1119 小时前
Spring Cloud Data Flow 简介
后端·spring·spring cloud
Tony Bai9 小时前
告别 Flaky Tests:Go 官方拟引入 testing/nettest,重塑内存网络测试标准
开发语言·网络·后端·golang·php
+VX:Fegn089510 小时前
计算机毕业设计|基于springboot + vue鲜花商城系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
程序猿阿伟10 小时前
《GraphQL批处理与全局缓存共享的底层逻辑》
后端·缓存·graphql
小小张说故事10 小时前
SQLAlchemy 技术入门指南
后端·python
识君啊10 小时前
SpringBoot 事务管理解析 - @Transactional 的正确用法与常见坑
java·数据库·spring boot·后端
想用offer打牌11 小时前
MCP (Model Context Protocol) 技术理解 - 第五篇
人工智能·后端·mcp