SpringHttpMessageConverter的作⽤及替换解析
相信使⽤过Spring的开发⼈员都⽤过@RequestBody、@ResponseBody注解,可以直接将输⼊解析成Json、将输出解析成Json,但HTTP 请求和响应是基于⽂本的,意味着浏览器和服务器通过交换原始⽂本进⾏通信,⽽这⾥其实就是HttpMessageConverter发挥着作⽤。
HttpMessageConverter
Http请求响应报⽂其实都是字符串,当请求报⽂到java程序会被封装为⼀个ServletInputStream流,开发⼈员再读取报⽂,响应报⽂则通过ServletOutputStream流,来输出响应报⽂。
从流中只能读取到原始的字符串报⽂,同样输出流也是。那么在报⽂到达SpringMVC / SpringBoot和从SpringMVC / SpringBoot出去,都存在⼀个字符串到java对象的转化问题。这⼀过程,在SpringMVC / SpringBoot中,是通过HttpMessageConverter来解决的。HttpMessageConverter接⼝源码:
public interface HttpMessageConverter<T> {
boolean canRead(Class<?> clazz, MediaType mediaType);
boolean canWrite(Class<?> clazz, MediaType mediaType);
List<MediaType> getSupportedMediaTypes();
T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
void write(T t, MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;
}
下⾯以⼀例⼦来说明,
@RequestMapping("/test")
@ResponseBody
public String test(@RequestBody String param) {
return "param '" + param + "'";
}
在请求进⼊test⽅法前,会根据@RequestBody注解选择对应的HttpMessageConverter实现类来将请求参数解析到param变量中,因为这⾥的参数是String类型的,所以这⾥是使⽤了StringHttpMessageConverter类,它的canRead()⽅法返回true,然后read()⽅法会从请求中读出请求参数,绑定到test()⽅法的param变量中。
同理当执⾏test⽅法后,由于返回值标识了@ResponseBody,SpringMVC / SpringBoot将使⽤StringHttpMessageConverter 的write()⽅法,将结果作为String值写⼊响应报⽂,当然,此时canWrite()⽅法返回true。
借⽤下图简单描述整个过程:
在Spring的处理过程中,⼀次请求报⽂和⼀次响应报⽂,分别被抽象为⼀个请求消息HttpInputMessage和⼀个响应消息HttpOutputMessage。
处理请求时,由合适的消息转换器将请求报⽂绑定为⽅法中的形参对象,在这⾥同⼀个对象就有可能出现多种不同的消息形式,如json、xml。同样响应请求也是同样道理。
在Spring中,针对不同的消息形式,有不同的HttpMessageConverter实现类来处理各种消息形式,⾄于各种消息解析实现的不同,则在不同的HttpMessageConverter实现类中。
替换@ResponseBody默认的HttpMessageConverter
这⾥使⽤SpringBoot演⽰例⼦,在SpringMVC / SpringBoot中@RequestBody这类注解默认使⽤的是jackson来解析json,看
下⾯例⼦:
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/testt")
@ResponseBody
public User testt() {
User user = new User("name", 18);
return user;
}
}
public class User {
private String username;
private Integer age;
private Integer phone;
private String email;
public User(String username, Integer age) {
super();
this.username = username;
this.age = age;
}
}
浏览器访问/user/testt返回如下:
这就是使⽤jackson解析的结果,现在来改成使⽤fastjson解析对象,这⾥就是替换默认的HttpMessageConverter,就是将其改成使⽤FastJsonHttpMessageConverter来处理Java对象与HttpInputMessage/HttpOutputMessage间的转化。
⾸先新建⼀配置类来添加配置FastJsonHttpMessageConverter,Spring4.x开始推荐使⽤Java配置加注解的⽅式,也就是⽆xml⽂件,SpringBoot就更是了。
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fig.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import t.annotation.Bean;
import t.annotation.Configuration;
import org.verter.HttpMessageConverter;
import java.nio.charset.Charset;
@Configuration
public class HttpMessageConverterConfig {
//引⼊Fastjson解析json,不使⽤默认的jackson
//必须在l引⼊fastjson的jar包,并且版必须⼤于1.2.10
@Bean
public HttpMessageConverters fastJsonHttpMessageConverters() {
//1、定义⼀个convert转换消息的对象
springmvc选择题FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
//2、添加fastjson的配置信息
FastJsonConfig fastJsonConfig = new FastJsonConfig();
SerializerFeature[] serializerFeatures = new SerializerFeature[]{
// 输出key是包含双引号
// SerializerFeature.QuoteFieldNames,
// 是否输出为null的字段,若为null 则显⽰该字段
// SerializerFeature.WriteMapNullValue,
// 数值字段如果为null,则输出为0
SerializerFeature.WriteNullNumberAsZero,
// List字段如果为null,输出为[],⽽⾮null
SerializerFeature.WriteNullListAsEmpty,
// 字符类型字段如果为null,输出为"",⽽⾮null
SerializerFeature.WriteNullStringAsEmpty,
/
/ Boolean字段如果为null,输出为false,⽽⾮null
SerializerFeature.WriteNullBooleanAsFalse,
// Date的⽇期转换器
SerializerFeature.WriteDateUseDateFormat,
// 循环引⽤
SerializerFeature.DisableCircularReferenceDetect,
};
fastJsonConfig.setSerializerFeatures(serializerFeatures);
fastJsonConfig.setCharset(Charset.forName("UTF-8"));
//3、在convert中添加配置信息
fastConverter.setFastJsonConfig(fastJsonConfig);
/
/4、将convert添加到converters中
HttpMessageConverter<?> converter = fastConverter;
return new HttpMessageConverters(converter);
}
}
这⾥将字符串类型的值如果是null就返回“”,数值类型的如果是null就返回0,重启应⽤,再次访问/user/testt接⼝,返回如下:
可以看到此时null都转化成“”或0了。
以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论