I believe that developers who have used Spring have used @RequestBody and @ResponseBody annotations, and can directly parse the input into Json and the output into Json. However, HTTP requests and responses are text-based, which means that the browser and server communicate by exchanging original text, and this is actually HttpMessageConverter playing a role.
HttpMessageConverter
The Http request response packet is actually a string. When the request message is entered into a java program, it will be encapsulated into a ServletInputStream stream. The developer will read the message, and the response packet will output the response packet through the ServletOutputStream stream.
Only the original string packet can be read from the stream, and the same is true for the output stream. Then when the message arrives at SpringMVC/SpringBoot and exits from SpringMVC/SpringBoot, there is a problem of converting strings to Java objects. This process, in SpringMVC/SpringBoot, is solved through HttpMessageConverter. HttpMessageConverter interface source code:
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;}Here is an example to illustrate,
@RequestMapping("/test")@ResponseBodypublic String test(@RequestBody String param) { return "param '" + param + "'";}Before the request enters the test method, the corresponding HttpMessageConverter implementation class will be selected according to the @RequestBody annotation to parse the request parameters into the param variable. Because the parameters here are of String, the StringHttpMessageConverter class is used here. Its canRead() method returns true, and then the read() method will read the request parameters from the request and bind to the param variable of the test() method.
Similarly, when the test method is executed, since the return value identifies @ResponseBody, SpringMVC/SpringBoot will use the write() method of StringHttpMessageConverter and write the result as a String value to the response message. Of course, the canWrite() method returns true at this time.
Borrow the following figure to briefly describe the entire process:
During Spring processing, a request message and a response message are abstracted into a request message HttpInputMessage and a response message HttpOutputMessage, respectively.
When processing a request, the appropriate message converter binds the request message into a formal parameter object in the method. Here, there may be multiple different message forms in the same object, such as json and xml. The same is true for responding to requests.
In Spring, for different message forms, there are different HttpMessageConverter implementation classes to handle various message forms. As for the different implementations of various message parsing, they are in different HttpMessageConverter implementation classes.
Replace @ResponseBody's default HttpMessageConverter
Here is an example of SpringBoot. In SpringMVC/SpringBoot, the @RequestBody annotation uses jackson to parse json by default. See the following example:
@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; }}Browser access /user/testt returns as follows:
This is the result of using jackson parsing. Now we will change it to using fastjson parsing object. Here we replace the default HttpMessageConverter, which means using FastJsonHttpMessageConverter to handle the conversion between Java objects and HttpInputMessage/HttpOutputMessage.
First, create a new configuration class to add configuration FastJsonHttpMessageConverter. Spring 4.x recommends using Java configuration annotation method, that is, there is no xml file, and SpringBoot is even more so.
import com.alibaba.fastjson.serializer.SerializerFeature;import com.alibaba.fastjson.support.config.FastJsonConfig;import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;import org.springframework.boot.autoconfigure.web.HttpMessageConverters;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.http.converter.HttpMessageConverter;import java.nio.charset.Charset;@Configurationpublic class HttpMessageConverterConfig { //Introduce Fastjson to parse json, do not use the default jackson //The fastjson jar package must be introduced in pom.xml, and the version must be greater than 1.2.10 @Bean public HttpMessageConverters fastJsonHttpMessageConverters() { //1. Define an object that converts the message FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); //2. Add fastjson configuration information FastJsonConfig fastJsonConfig = new FastJsonConfig(); SerializerFeature[] serializerFeatures = new SerializerFeature[]{ // The output key is a double quote // SerializerFeature.QuoteFieldNames, // Whether to output a field as null, if it is null, the field is displayed // SerializerFeature.WriteMapNullValue, // If the numeric field is null, the output is 0 SerializerFeature.WriteNullNumberAsZero, // If the List field is null, the output is [], not null SerializerFeature.WriteNullListAsEmpty, // If the character type field is null, the output is "", not null SerializerFeature.WriteNullStringAsEmpty, // If the Boolean field is null, the output is false, not null SerializerFeature.WriteNullBooleanAsFalse, // Date converter SerializerFeature.WriteDateUseDateFormat, // Circular reference SerializerFeature.DisableCircularReferenceDetect, }; fastJsonConfig.setSerializerFeatures(serializerFeatures); fastJsonConfig.setCharset(Charset.forName("UTF-8")); //3. Add configuration information in convert fastConverter.setFastJsonConfig(fastJsonConfig); //4. Add convert to converts HttpMessageConverter<?> converter = fastConverter; return new HttpMessageConverters(converter); }}Here, if the value of string type is null, it will return "", if the value of null, it will return 0, restart the application, access the /user/testt interface again, and return as follows:
You can see that null is converted to "" or 0 at this time.
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.