场景:大多数时候Spring MVC自带的消息转化器已经满足需要了,为了学习此处还是编写一下自定义的消息转化器
原理:消息转化器的原理如下图
编码
1.编写自定义的消息转化器
public class CustomJsonHttpMessageConverter implements HttpMessageConverter {
private ObjectMapper mapper=new ObjectMapper();
private List supportedMediaTypes= Arrays.asList(MediaType.APPLICATION_JSON);
/**
* 判断转换器是否可以将输入内容转换成Java
* @param aClass
* @param mediaType
* @return
*/
@Override
public boolean canRead(Class aClass, MediaType mediaType) {
if(mediaType==null){
return false;
}
for(MediaType supportedMediaType : getSupportedMediaTypes()){
if(supportedMediaType.includes(mediaType)){
return true;
}
}
return false;
}
/**
* 判断转换器能否将Java类型转换成指定的输出内容
* @param aClass
* @param mediaType
* @return
*/
@Override
public boolean canWrite(Class aClass, MediaType mediaType) {
if(mediaType==null || MediaType.ALL.equals(mediaType)){
return true;
}
for(MediaType supportedMediaType:getSupportedMediaTypes()){
if(supportedMediaType.includes(mediaType)){
return true;
}
}
return false;
}
@Override
public List<MediaType> getSupportedMediaTypes() {
return supportedMediaTypes;
}
/**
* 读取请求内容将其中的Json转换为Java对象
* @param aClass 需要转化的Java类型
* @param httpInputMessage 请求对象
* @return
* @throws IOException
* @throws HttpMessageNotReadableException
*/
@Override
public Object read(Class aClass, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException {
return mapper.readValue(httpInputMessage.getBody(),aClass);
}
/**
* 将Java对象转化成Json返回内容
* @param o 需要转化的对象
* @param mediaType 返回类型
* @param httpOutputMessage 回执对象
* @throws IOException
* @throws HttpMessageNotWritableException
*/
@Override
public void write(Object o, MediaType mediaType, HttpOutputMessage httpOutputMessage) throws IOException, HttpMessageNotWritableException {
OutputStream outputStream=httpOutputMessage.getBody();
outputStream.write("hello world".getBytes());
mapper.writeValue(outputStream,o);
}
}
2.将消息转化器注册到Spring MVC中
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
/**
* 如果这里拦截全部 即 /** 的话,就会导致拦截器的方法被执行两次,原因还不明确
*/
registry.addInterceptor(httpTest()).addPathPatterns("/h1/h3"+"/**");
super.addInterceptors(registry);
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new CustomJsonHttpMessageConverter());
super.configureMessageConverters(converters);
}
}
3.编写测试代码
@RequestMapping(value = "h3")
public @ResponseBody Object testHeader(@RequestBody String haha) {
System.out.println("controller里面="+haha);
Pet pet=new Pet();
pet.setName("hello");
return pet;
}
标注了@RequestBody注解的Controller方法在获取到数据后,将会根据content-type 的类型找到合适的消息转化器,而被@ResponseBody标注的方法在返回数据的时候,同样的也会根据content-Type寻找合适的消息转换器转化为的相应的数据返回,上面的例子中使用了APPLICATION_JSON,同时也可以自定义Content-Type 为这种特定的content-Type编写相应的消息转换器。