springboot扩展消息转换器
扩展消息转换器听起来可能有点抽象,实际上消息转换器所起到的作用就是将数据进行序列化和反序列化,例如前端请求传递过来的json数据,我们会反序列化为java对象,同样,给前端返回数据也用到了序列化的,在这些操作中,都会使用消息转换器进行处理。
-
序列化(Serialization):将Java对象转换为可以传输的格式(如JSON、XML等),以便将数据返回给客户端。这通常发生在Controller方法的返回值被处理时。
-
反序列化(Deserialization):将传输过来的数据(如JSON、XML等)转换为Java对象,以便在Controller方法中使用。这通常发生在Controller方法的参数被处理时。
一、Spring Boot 扩展消息转换器的执行流程
-
HTTP 请求到达
当一个 HTTP 请求到达 Spring Boot 应用时,
DispatcherServlet
(分发器 Servlet)会接收到这个请求。 -
分发请求
DispatcherServlet
会将这个请求分发给合适的HandlerAdapter
(处理器适配器)进行处理。 -
查找处理器
HandlerAdapter
会找到处理这个请求的Controller
,并调用相应的处理方法。 -
数据转换
在调用处理方法时,如果方法的参数或返回值需要进行数据转换(例如,参数是一个 Java 对象,但客户端发送的是一个 JSON 格式的请求),
HandlerAdapter
会使用HttpMessageConverter
(消息转换器) 来进行数据转换。 -
选择合适的消息转换器
HandlerAdapter
会遍历所有已注册的HttpMessageConverter
,找到一个支持转换当前数据的HttpMessageConverter
,然后使用这个HttpMessageConverter
来进行数据转换。 -
调用处理方法
数据转换完成后,处理方法会被执行,处理结果会被返回给
HandlerAdapter
。 -
响应数据转换
HandlerAdapter
会再次使用HttpMessageConverter
来将处理结果转换为 HTTP 响应。 -
返回响应
最后,
DispatcherServlet
会将 HTTP 响应返回给客户端。
通过上述流程,我们可以知道,在外面添加自定义的消息转换器时,
需要添加序列化和反序列化两种方式,以便处理接收数据和返回数据
-
具体例子:
@RestController
public class MyController {
@PostMapping("/example")
public Result example(@RequestBody MyObject myObject) {
// 处理myObject
return Result.success();
}
}
-
请求到达:客户端发送一个包含JSON数据的HTTP POST请求到
/example
端点。 -
数据转换:Spring Boot会使用合适的
HttpMessageConverter
(如MappingJackson2HttpMessageConverter
)将请求体中的JSON数据反序列化为MyObject
类型的Java对象。 -
调用处理方法:反序列化后的
MyObject
对象作为参数传递给example
方法。
通过上述我们也就可以知道,平时我们使用的
@RequestBody
实际上就是使用消息转换器起到反序列化的作用,同样的,RestController
就是使用消息转换器起到反序列化的作用
二、自定义消息消息转换器
这里我们以时间格式处理为例,在前后端数据传递过程中,时间格式处理是经常会遇到的
- 配置类设置
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
// 创建一个消息转换器对象
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
// 设置对象转换器,可以将java对象转换为json字符串
converter.setObjectMapper(new JacksonObjectMapper());
// 将自定义的转换器添加到spring MVC框架的消息转换器列表中,并且放在第一个位置
converters.add(0, converter);
}
}
- JacksonObjectMapper设置
package com.sky.json;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
/**
* 对象映射器:基于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:ss";
//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);
// addDeserializer方法用于添加反序列化器,用于前端传递的时间字符串转为LocalDateTime对象
// addSerializer方法用于添加序列化器,用于将LocalDateTime对象转为前端需要的时间字符串
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);
}
}