http Content-type及Spring的@RequestBody注解

来源:互联网 发布:向日葵虚拟局域网软件 编辑:程序博客网 时间:2024/05/20 00:15

1. content-type

    场景:使用JMeter测试spring的REST接口
     

                 

rest 接口定义如下

    @RequestMapping (value = "/client/join" , method = RequestMethod.POST)    @ResponseBody    public String clientJoined(@RequestBody String requestBody, HttpServletResponse response)       {             ... ...       }

     调试时发现@RequestBody标注的requestBody参数值是被encode过的字符串
     %3Ccontent%3E%0D%0A%09%3Cdict%3E%0D%0A%09%09%3CAPMacAddress%3E112211221122%3C%2FAPMacAddress%3E%0D%0A%09%09%3CUPID%3E%3C%2FUPID%3E%0D%0A%09%09%3CClientMacAddress%3E%3C%2FClientMacAddress%3E%0D%0A%09%09%3CIsProvisioning%3E%3C%2FIsProvisioning%3E%0D%0A%09%09%3CSecurityType%3E%3C%2FSecurityType%3E%0D%0A%09%09%3CSSID%3E%3C%2FSSID%3E%0D%0A%09%09%3CHMIPAddress%3E%3C%2FHMIPAddress%3E%0D%0A%09%09%3CHMHostName%3E%3C%2FHMHostName%3E%09%09%0D%0A%09%3C%2Fdict%3E%0D%0A%3C%2Fcontent%3E=

     原因是未指定http头content-type时,JMeter默认使用application/x-www-formurlencoded提交http请求。用wireshark抓包可以看到该行为


     因此为了能让让rest接口的@RequestBody注解获取到不经过encode的文本,需要为http添加content-type,可以是 text/plain

---------------------------------------------------------------------------------------------------------
2. @RequestBody注解

     Spring3.2对注解@RequestBody的解析代码段是

public InputStream getBody() throws IOException {    if (isFormPost(this.servletRequest)) {        return getBodyFromServletRequestParameters(this.servletRequest);    }    else {        return this.servletRequest.getInputStream();    }}

     其中的if分支判断request是否有http header content-type并且content-type包含字符串applicationx/x-www-form-urlencoded。如果成立那么spring会从request的parameter map构造一个request body,否则直接返回request的input stream。

     之所以有这个分支是因为以application/x-www-form-urlencoded提交的请求,web容器(如tomcat)需要读取request的input stream做参数的解析,消费了input stream的结果是得到了request的参数。由于input stream只能读取一次,因此当在web app层通过@RequestBody试图获取request body时,spring会遍历request参数重新构造request body,但参数的顺序可能会与原始http请求不同。图示如下

                         



0 0