目录
创建类继承WebMvcConfigurationSupport或者实现WebMvcConfiguration接口
configureMessageConverters和extendMessageConverters的区别
继承WebMvcConfigurationSupport的类
什么是消息转换器?
在SpringMVC中消息转换器是用于将HTTP请求和响应的消息体转换为java对象或者将java对象转换成HTTP响应消息体组件,通过实现HttpMessageConverter接口来实现不同格式的转换,如 JSON,XML等。
主要功能:
- 自动转换:消息转换器能够根据请求的内容类型(Content-Type)和响应的内容类型(Accept)自动选择合适的转换器进行转换。
- 支持多种格式:可以支持多种数据格式的转换,包括但不限于:
- JSON(使用 Jackson 或 Gson)
- XML
- 表单数据
- 字符串等
- 自定义支持:开发者可以自定义消息转换器,满足特定的需求。
使用场景:
- 在处理 RESTful API 时,通常使用消息转换器来处理客户端发送的数据(如 JSON、XML 等)并将其转换为 Java 对象。
- 发送响应时,消息转换器将 Java 对象序列化为客户端所需要的格式。
常用的消息转换器
消息转换器 | 用途说明 |
---|---|
MappingJackson2HttpMessageConverter | 用于将 Java 对象转换为 JSON 格式,支持使用 Jackson 库。适用于 RESTful API 返回 JSON 数据。 |
MappingJackson2XmlHttpMessageConverter | 用于将 Java 对象转换为 XML 格式,支持使用 Jackson 库生成 XML。适用于需要返回 XML 数据的场景。 |
Jaxb2RootElementHttpMessageConverter | 用于将 Java 对象转换为 XML 格式,支持 JAXB(Java Architecture for XML Binding)。适合于有 JAXB 注解的类。 |
StringHttpMessageConverter | 用于处理文本格式的数据,支持将 String 类型的对象与文本消息进行转换。 |
FormHttpMessageConverter | 用于处理表单数据(application/x-www-form-urlencoded),将请求参数转换为 Java 对象。 |
ByteArrayHttpMessageConverter | 用于处理字节数组,将字节数组与 HTTP 消息进行转换,适合上传或下载文件的场景。 |
ResourceHttpMessageConverter | 用于处理资源(如文件),能够将资源转换为 HTTP 响应的内容。适合文件下载等场景。 |
AllEncompassingFormHttpMessageConverter | 提供表单与多部分(multipart)数据的完整处理,可以处理复杂的表单数据。 |
使用步骤
我们在这里通过继承ObjectMapper来实现一个工具类重新生成一个消息转换器用来实现日期的序列化的格式定义
创建类继承WebMvcConfigurationSupport或者实现WebMvcConfiguration接口
我们是通过重写extendMessageConverters方法来实现添加自定义的转换器
上面我们可以通过继承这个类或者接口来实现,他们都有extendMessageConverters这个方法来追加我们自定义的消息转换器
configureMessageConverters和extendMessageConverters的区别
configureMessageConverters():完全替换默认的消息转换器。
extendMessageConverters():在保留默认转换器的基础上扩展添加新的转换器。
即重写configureMessageConverters方法会清空原有的所有默认的消息转换器,而extendMessageConverters是在原有的消息转换器基础上来追加
实例代码
继承WebMvcConfigurationSupport的类
import com.part1.JSON.JacksonObjectMapper;
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.WebMvcConfigurationSupport;
import java.util.List;
@Configuration
public class WebConfiguration extends WebMvcConfigurationSupport {
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();//创建一个MappingJackson2HttpMessageConverter用来处理java对象于json字符串之间的转换
converter.setObjectMapper(new JacksonObjectMapper());//设置自定义解析器,来处理序列化和反序列化的时候的格式要求
converters.add(0,converter);//添加这个消息转换器到列表里面,并放在list的头部
}
}
为什么要放在列表的头部?
这里的 converters 是一个 HttpMessageConverter 类型的列表,通常用于存储多个消息转换器。通过将 converter 添加到索引位置 0,它会在转换器列表的最前面,意味着它将优先于其他转换器被调用。这对于确保使用特定的转换器处理请求和响应是非常重要的,尤其是在存在多个转换器的情况下。MVC在处理数据请求和响应的消息体的时候会将消息体的数据格式做处理,这时候他会从这个列表里面从头到尾去查找对应数据格式的消息转换器找到第一个符合条件的就不再找了,所以我们放在头部优先级高一些。
继承ObjectMapper自定义的类
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
public class JacksonObjectMapper extends ObjectMapper {
public JacksonObjectMapper() {
super();
//收到未知属性时不报异常
this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
//反序列化时,属性不存在的兼容处理
this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
this.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);//禁止在序列化日期的时候将其序列化为时间戳
this.registerModule(new JavaTimeModule());//注册java8的时间模块
SimpleModule module = new SimpleModule();
module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss")));//设置序列化的时候的时间格式
this.registerModule(module);
}
}
实体类
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TimeEntity {
private LocalDateTime localDateTime;
private LocalDate localDate;
private LocalTime localTime;
}
controller
import com.part1.Entity.TimeEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
@RestController
public class TestController {
@GetMapping("/test")
public TimeEntity test() {
TimeEntity timeEntity = new TimeEntity(LocalDateTime.now(), LocalDate.now(), LocalTime.now());
return timeEntity;
}
}
此时我们运行项目查看返回的数据
发现他返回的LocalDateTime的格式跟我们在自定义的JacksonObjectMapper这个类的设置的格式是一样的,至此我们就成功的自定义消息转换器了,而在反序列化的时候的逻辑是一样的这里就不作描述了,其思路都是一样的
先去创建类来继承WebMvcConfigurationSupport或者实现WebMvcConfiguration接口。然后再重写extendMessageConverters来追加我们要自定义的消息转换器,注意这里的消息转换器有很多类型,可以看上面的表格,然后给这个消息转换器添加自定义的解析器,这个解析器就包含了我们要序列化或者反序列化的时候的格式要求,然后再把这个消息转换器追加到消息转换器的头部,这个是为了提高优先级,能被优先使用。至此消息转换器的自定义的步骤就完成了
最后
本人的第十篇博客,以此来记录我的后端java学习。如文章中有什么问题请指出,非常感谢!!!