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参数和路径参数时,由于不涉及序列化和反序列化,依然需要手动添加注解来为其指定正确的格式
相关推荐
whyfail10 分钟前
前端学 Spring Boot(8):接口为什么越用越慢?
前端·spring boot·后端
Muscleheng1 小时前
Spring Boot 3.x 集成 DeepSeek 实现 Function Calling(工具调用)
人工智能·spring boot·后端·ai·spring ai·deepseek
@航空母舰1 小时前
SpringBoot通过Map实现天然的策略模式
java·spring boot·后端
IT_陈寒2 小时前
JavaScript的this又双叒叕让我怀疑人生了
前端·人工智能·后端
陈随易2 小时前
MCP协议第5次更新,从打电话到微信聊天的巨大变革
前端·后端·程序员
65岁退休Coder2 小时前
LangChain v1.3.4 笔记 - 06 RAG 检索增强生成
后端
妙码生花3 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(四十三):前后端数据验证
后端·go·ai编程
YuePeng3 小时前
别再让 AI 直接写 SQL 了:一个注解搞定十亿行数据的语义层
后端·github
半夜里咳嗽的狼3 小时前
Go 1.25 的 WaitGroup.Go 省了两行代码,也补不上这三个并发边界
后端·go
Lihua奏3 小时前
身份验证:登录之后,服务器怎么一直认得你?
后端