Use cases of @RequestBody and @ResponseBody and http message conversion of RestTemplate

Two annotations, @RequestBody and @ResponseBody, respectively complete the conversion of request message to object and object to response message.

@RequestBody

1. The @requestBody annotation is often used to process content whose content-type is not the default application/x-www-form-urlcoded encoding.

For example: application/json or application/xml, etc. In general, it is used to handle application/json types.

effect:

  • content-TypeThe annotation is used to convert the method parameters of the Controller into JAVA classes through the appropriate HttpMessageConverter according to the content of the HTTP Request Header
  • Then bind the object data returned by HttpMessageConverter to the parameters of the method in the controller.

Description: The data encoding format of the body part of the request is specified by the Content-Type of the header part;

 

2. Through @requestBody, the JSON string in the request body can be bound to the corresponding bean. Of course, it can also be bound to the corresponding string respectively. For example, say the following:

  $.ajax({
        url:"/login",
        type:"POST",
        data:'{"userName":"admin","pwd","admin123"}',
        content-type:"application/json charset=utf-8",
        success:function(data){
          alert("request success ! ");
        }
    });

    @requestMapping("/login")
    public void login(@requestBody String userName,@requestBody String pwd){
      System.out.println(userName+""+pwd);
    }

In this case, the values ​​of the two variables in the JSON string are assigned to two strings respectively, but if I have a User class with the following fields:
 String userName;
 String pwd;
Then the above parameters can be changed to the following form : @requestBody User user This form will assign the value in the JSON string to the corresponding attribute in the user. It
should be noted that the key in the JSON string must correspond to the attribute name in the user, otherwise the request cannot be passed.

In addition, it should be noted here that @RequestBody actually receives a string of a Json object, not a Json object.

The difference between a Json object and a Json string is whether there are single quotes when it is defined or not. . .

If the ajax request passes a Json object, the object can be turned into a string later by JSON.stringify(data).

At the same time, you should also specify dataType: "json", contentType: "application/json" when requesting ajax, so that you can easily pass an object or List to the Java side, and use @RequestBody to bind the object or List.

<script type="text/javascript">  
    $(document).ready(function(){  
        var saveDataAry=[];  
        var data1={"userName":"test","address":"gz"};  
        var data2={"userName":"ququ","address":"gr"};  
        saveDataAry.push (data1);  
        saveDataAry.push (data2);         
        $.ajax({
            type:"POST", 
            url:"user/saveUser", 
            dataType:"json",      
            contentType:"application/json",               
            data:JSON.stringify(saveData),
            success:function(data){
                                       
            }
         });
    });  
</script>

Reference blog: Difference and mutual conversion between json objects and json strings

 

@ResponseBody

This annotation is used to convert the object returned by the Controller method according to Acceptthe content of the HTTP Request Header,

After appropriate HttpMessageConverterconversion to the specified format, it is written to the body data area of ​​the Response object.

Usually, after using @RequestMapping, the return value is usually parsed as a jump path. After adding @Responsebody, the return result will not be parsed as a jump path, but directly written into the HTTP response body. 

 

HTTP requests and responses are text-based, meaning that the browser and server communicate by exchanging raw text. However, with Spring, methods in the controller class return plain 'String' type and domain models (or other Java built-in objects).

How to serialize/deserialize objects to raw text? This is handled by HttpMessageConverter.

Http request and response messages are essentially a string of strings. When the request message comes to the java world, it will be encapsulated into an input stream of ServletInputStream for us to read the message. The response message is output through a ServletOutputStream output stream to output the response message.

From the stream, we can only read the original string message, and similarly, we can only write the original character to the output stream.

In the java world, the processing of business logic is based on each object with business significance as the processing dimension, so there is a problem of impedance between a string and a java object when the message arrives and leaves SpringMVC.

This process cannot be manually converted by the developer. We know that in Struts2, OGNL is used to deal with this problem, and in SpringMVC, it is the HttpMessageConverter mechanism.

Please see:

Analysis of SpringMVC source code (5) - message converter HttpMessageConverter

HttpMessageConverter (message converter) and @responsebody use

 

http message conversion processing in RestTemplate

In RestTemplate,

We know that the data content passed by calling the reseful interface is a json-formatted string, and the returned response is also a json-formatted string.

However restTemplate.postForObject, the request parameters RequestBeanand return parameters of the method ResponseBeanare all java classes. It does RestTemplatethe HttpMessageConverterconversion for us automatically.

By default, RestTemplatea group is automatically registered for us HttpMessageConverterto handle some different contentTyperequests.

to StringHttpMessageConverterdeal with text/plain; MappingJackson2HttpMessageConverterto deal with application/json; MappingJackson2XmlHttpMessageConverterto deal with application/xml.

You can org.springframework.http.converterfind all the converters that spring has implemented for us under the package.

If the existing converter does not meet your needs, you can also implement it yourself.

See: How to use RestTemplate to access restful services

Notice:

StringHttpMessageConverterThe default character set used is ISO-8859-1that there will be garbled characters when encountering Chinese, so you need to remove the default StringHttpMessageConvertermodified character set of RestTemplate and reset it.

Spring's json converter uses Jackson by default. If the json string and the corresponding Entity have fields that do not match, an error will be reported. This is a bit inconsistent with the national conditions, while FastJson will not report an error, so FastJSON is often used to replace the default. Jackson.

Configuration example:

@Configuration
public class RestAutoConfig {

    public  static  class RestTemplateConfig {

        @Bean // restTemplate for load balancing 
        @LoadBalanced // spring customizes the restTemplate bean and adds the loadbalance interceptor to replace ip:port
                     // " http://user/getusername , which can be resolved to http: // 127.0. 0.1:8083 // getusername 
        RestTemplate lbRestTemplate(HttpClient httpclient) {
            RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory(httpclient));
            template.getMessageConverters().add(0,new StringHttpMessageConverter(Charset.forName("utf-8")));
            template.getMessageConverters().add(1,new FastJsonHttpMessageConvert5());
            return template;
        }
        
        @Bean // Directly connected restTemplat, at this time only http: // 127.0.0.1:8083 // getusername address cannot be resolved http: // user/getusername 
        RestTemplate directRestTemplate(HttpClient httpclient) {
            RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory(httpclient));
            template.getMessageConverters().add(0,new StringHttpMessageConverter(Charset.forName("utf-8")));
            template.getMessageConverters().add(1,new FastJsonHttpMessageConvert5());
            return template;
        }
        
        // FastJsonHttpMessageConvert4 has a bug, it supports MediaType.ALL by default, and spring will recognize it as a byte stream instead of json when processing MediaType.ALL. Here we will transform and process it. 
         public  static  class FastJsonHttpMessageConvert5 extends FastJsonHttpMessageConverter4{
              
              static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
              
                  public FastJsonHttpMessageConvert5(){
                setDefaultCharset(DEFAULT_CHARSET);
                setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON,new MediaType("application","*+json")));
              }

            }
    }

}
View Code

HTTPclient Bean get class:

@Configuration
@ConditionalOnClass({HttpClient.class})
@EnableConfigurationProperties(HttpClientProperties.class)
public class HttpClientAutoConfiguration {

    private final HttpClientProperties properties;
    
    
    public HttpClientAutoConfiguration(HttpClientProperties properties){
        this.properties = properties;
    }
    
    /**
     * Definition of httpclient bean
     * @return
     */
    @Bean
    @ConditionalOnMissingBean(HttpClient.class)
    public HttpClient httpClient() {
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(properties.getConnectTimeOut())
                .setSocketTimeout(properties.getSocketTimeOut()).build();// 构建requestConfig
        HttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig)
                .setUserAgent(properties.getAgent())
                .setMaxConnPerRoute(properties.getMaxConnPerRoute())
                .setMaxConnTotal(properties.getMaxConnTotaol())
                .build();
        return client;
    }
}
View Code

HTTPClient parameter class:

@ConfigurationProperties(prefix="spring.httpclient")
public class HttpClientProperties {
    
    private Integer connectTimeOut = 1000;
    
    private Integer socketTimeOut = 1000000;

    private String agent = "agent";
    private Integer maxConnPerRoute = 10;
    private Integer maxConnTotaol   = 50;
    public Integer getConnectTimeOut() {
        return connectTimeOut;
    }
    public void setConnectTimeOut(Integer connectTimeOut) {
        this.connectTimeOut = connectTimeOut;
    }
    public Integer getSocketTimeOut() {
        return socketTimeOut;
    }
    public void setSocketTimeOut(Integer socketTimeOut) {
        this.socketTimeOut = socketTimeOut;
    }
    public String getAgent() {
        return agent;
    }
    public void setAgent(String agent) {
        this.agent = agent;
    }
    public Integer getMaxConnPerRoute() {
        return maxConnPerRoute;
    }
    public void setMaxConnPerRoute(Integer maxConnPerRoute) {
        this.maxConnPerRoute = maxConnPerRoute;
    }
    public Integer getMaxConnTotaol() {
        return maxConnTotaol;
    }
    public void setMaxConnTotaol(Integer maxConnTotaol) {
        this.maxConnTotaol = maxConnTotaol;
    }
    
    
    
}
View Code

 



 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326592551&siteId=291194637