Spring MVC消息转换器的扩展使用

Spring MVC消息转换器的扩展使用

问题

在实现用户编辑功能时,需要获取特定用户的ID,并根据该ID对用户信息进行修改。代码如下:

    @PutMapping
    public R<String> update(HttpServletRequest request,@RequestBody Employee employee){
        log.info(employee.toString());

        employee.setUpdateTime(LocalDateTime.now());
        employee.setUpdateUser((Long)request.getSession().getAttribute("employee"));
        employeeService .updateById(employee);

        return R.success("员工信息修改成功");
    }

但测试中,没有报错,但是功能并没有实现。查看运行中的记录,发现SQL执行的更新数据行数为0,传入ID和数据库中的记录值是不同的。

在这里插入图片描述
在这里插入图片描述

用户的ID是Long类型的数据,但在传递到后台时出现了误差。因此,我们需要在将其修改数据之前将其转换为String类型。

解决方法

解决上面的问题,需要了解一下Spring MVC中的消息转换器。

Spring MVC消息转换器(Message Converters)是用于在HTTP请求和响应之间进行数据转换的组件。在Spring MVC中,消息转换器的作用是将请求的数据(例如JSON、XML等)转换为Java对象,或者将Java对象转换为响应的数据格式。

Spring MVC提供了各种内置的消息转换器,用于处理不同的数据格式。一些常见的消息转换器包括:

  • StringHttpMessageConverter: 用于处理文本数据,例如普通字符串。

  • MappingJackson2HttpMessageConverter: 处理JSON格式的数据,它使用Jackson库将JSON数据转换为Java对象,反之亦然。

  • MarshallingHttpMessageConverter: 处理XML格式的数据,它使用JAXB或其他XML编排技术将XML数据转换为Java对象。

  • FormHttpMessageConverter: 处理表单数据,例如application/x-www-form-urlencoded格式的数据。


可以编写一个自定义的消息转换器,并将其添加到mvc中,解决上面的问题。

  • 定义一个带有自定义配置的 Jackson ObjectMapper,用于处理 Java 对象到 JSON 和 JSON 到 Java 对象的转换。

    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:ss";
        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(BigInteger.class, ToStringSerializer.instance)
                    .addSerializer(Long.class, ToStringSerializer.instance)
                    .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);
        }
    }
    
    

    这个 JacksonObjectMapper 的主要作用是提供一个可定制的 ObjectMapper,以适应应用程序对日期、时间格式和一些特殊类型的需求。通过创建和配置这样一个自定义 ObjectMapper,可以确保 JSON 数据与 Java 对象之间的转换满足特定的应用场景。

    • 日期和时间格式定义: 定义了默认的日期、时间和日期时间格式,分别为 yyyy-MM-ddHH:mm:ssyyyy-MM-dd HH:mm:ss
    • 配置不报异常: 配置 ObjectMapper,使其在遇到未知属性时不报异常。这通过调用 configure 方法来设置 FAIL_ON_UNKNOWN_PROPERTIESfalse 来实现。
    • 反序列化时属性不存在的兼容处理: 配置 ObjectMapper,在反序列化时处理属性不存在的兼容性。通过调用 getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) 来实现。
    • 自定义序列化和反序列化模块: 创建了一个 SimpleModule 对象,用于添加自定义的序列化器和反序列化器。具体的自定义处理包括对 LocalDateTimeLocalDateLocalTime 进行格式化的处理,以及对 BigIntegerLong 进行处理,将它们序列化为字符串。同时,注册了这个功能模块到 ObjectMapper 中。
    • 注册功能模块: 通过调用 registerModule 方法将自定义的 SimpleModule 注册到 ObjectMapper 中,以便应用自定义的序列化和反序列化规则。
  • 实现Spring MVC中的扩展消息转换器。

/**
     * 扩展mvc的消息转换器
     * @param converters
     */
    @Override
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        log.info("扩展消息转换器");
        //创建消息转换器
        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();

        //设置对象转换器,底层使用Jackson将Java对象转为json
        mappingJackson2HttpMessageConverter.setObjectMapper(new JacksonObjectMapper());

        //将上面的消息转换器对象追加到mvc框架的转换器集合中
        converters.add(0, mappingJackson2HttpMessageConverter);

    }

实现过程是:

  • 创建消息转换器: 创建了一个MappingJackson2HttpMessageConverter对象,Spring MVC中用于处理JSON格式的消息转换器。
  • 自定义对象映射器: 通过setObjectMapper方法设置了自定义的JacksonObjectMapper对象,该对象用于定义如何将Java对象转换为JSON。JacksonObjectMapper可能是您自己实现的ObjectMapper的子类,以实现对JSON序列化和反序列化的定制。
  • 添加到转换器集合: 最后,通过将新创建的MappingJackson2HttpMessageConverter对象添加到converters列表的开头(位置 0),确保它是转换器链的第一个元素。这样,它将首先被应用于处理消息转换。

测试

传递成功,数据也可以修改了。

在这里插入图片描述