zoukankan      html  css  js  c++  java
  • 总结! http post请求 application/x-www-form-urlencoded body体数据获取不到?

    首先,简单介绍下Http请求中Content-Type类型

    1. 类型格式:type/subtype(;parameter)? type  
    2. 主类型,任意的字符串,如text,如果是*号代表所有;   
    3. subtype 子类型,任意的字符串,如html,如果是*号代表所有;   
    4. parameter 可选,一些参数,如Accept请求头的q参数, Content-Type的 charset参数。   

    例如: Content-Type: text/html;charset=utf-8;

    常见的媒体格式类型如下:

    •     text/html : HTML格式
    •     text/plain :纯文本格式      
    •     text/xml :  XML格式
    •     image/gif :gif图片格式    
    •     image/jpeg :jpg图片格式 
    •     image/png:png图片格式

       以application开头的媒体格式类型:

    •    application/xhtml+xml :XHTML格式
    •    application/xml     : XML数据格式
    •    application/atom+xml  :Atom XML聚合格式    
    •    application/json    : JSON数据格式
    •    application/pdf       :pdf格式  
    •    application/msword  : Word文档格式
    •    application/octet-stream : 二进制流数据(如常见的文件下载)
    •    application/x-www-form-urlencoded : <form encType=””>中默认的encType,当form表单请求为get时,数据被编码为key/value格式(name1=value1&name2=value2…),然后把这个字串append到url后面,用?分割,加载这个新的url发送到服务器(表单默认的提交数据的格式);当请求为post时,浏览器把form数据封装到http body中,然后发送到server。(form的enctype属性为编码方式,常用有两种:application/x-www-form-urlencoded和multipart/form-data,默认为application/x-www-form-urlencoded。)

       另外一种常见的媒体格式是上传文件之时使用的:

    •     multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式

         以上就是我们在日常的开发中,经常会用到的若干content-type的内容格式。

    最近项目开发对接接口,那边发送http  post请求(

    已知是xml数据,类似  <?xml version="1.0" encoding="GBK"?><Advpay><PubInfo><ReturnCode>0000</ReturnCode>**其他节点略**</PubInfo</Advpay>),

    抓包显示,"Content-Type" 是 "application/x-www-form-urlencoded;charset=GBK",

    在body里用如下方式获取数据:(该方式获取不到数据

    public String parserRequest() {
            HttpServletRequest request = ServletActionContext.getRequest();
            StringBuffer sb = null;
            InputStream in = null;
            BufferedReader br = null;
            try {
                in = request.getInputStream();
                br = new BufferedReader(new InputStreamReader(in, "utf-8"));
                sb = new StringBuffer();
                String s = "";
                while ((s = br.readLine()) != null) {
                    sb.append(s);
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage(), e);
            } finally {
                try {
                    if (br != null) {
                        br.close();
                    }
                    if (in != null) {
                        in.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    
            String xml = sb.toString();
            if (xml != null && !"".equals(xml)) {
                logger.info("报文response xml = " + xml);
            }
            return xml;
    
    
        }

    这种方式可以:(觉得很怪。。。想着一般post请求,都body体读取流数据
    "Content-Type" = "application/x-www-form-urlencoded 这种格式要特别注意

    public String parserRequest() {
            HttpServletRequest request = ServletActionContext.getRequest();
            String reqXml = null;
            try {
                Map<String, String[]> map = request.getParameterMap();
                StringBuffer xmlBuf = new StringBuffer();
                for (Map.Entry<String, String[]> m : map.entrySet()) {
                    logger.info("返回的报文 key=" + m.getKey() + " Value[0]="
                            + m.getValue()[0]);
    //打印出来的key=<?xml version value[0]="1.0" encoding="GBK"?><Advpay><PubInfo><ReturnCode>0000</ReturnCode>**其他节点略**</PubInfo</Advpay>
    xmlBuf.append(m.getKey()); xmlBuf.append(
    "="); xmlBuf.append(m.getValue()[0]); } reqXml = xmlBuf.toString(); } catch (Exception e) { logger.error("Exception" + e.getMessage(), e); } if (reqXml != null && !"".equals(reqXml)) { logger.info("报文response reqXml = " + reqXml); } return reqXml; }

    原因如下:

    在servlet规范3.1.1节里

    1. The request is an HTTP or HTTPS request.

    2. The HTTP method is POST.

    3. The content type is application/x-www-form-urlencoded.

    4. The servlet has made an initial call of any of the getParameter family of methods on the request object.

    If the conditions are met, post form data will no longer be available for reading directly from the request object’s input stream.

     在tomcat的Request.parseParameters方法里,对于application/x-www-form-urlencoded是有做判断的,对这种编码会去解析body里的数据,填充到parameters里,所以后续想再通过流的方式读取body是读不到的(除非你没有触发过getParameter相关的方法)。

    tomcat源码。。。待续。。。。。。。。。。。。。

    另外,看了下 org.apache.commons.httpclient.HttpClient 的源码 ,设置body体数据编码格式,

    postMethod.setRequestEntity(new StringRequestEntity(body,contentType, charSet));

    当"Content-Type" = "application/x-www-form-urlencoded;charset=GBK"  

    charSet="UTF-8"  两个参数都传入时,到底用哪个编码?

    由源码看来,以第二个参数 charSet 为准。 

    源码如下: 

    未完待续。。。。。。

  • 相关阅读:
    Java-GZIPOutputStream踩坑
    Redis事务
    Netty实现简单群聊
    SpringMVC请求参数解析
    Netty实现WebSocket
    SpringBoot项目war包部署
    NIO实现群聊
    SpringMVC请求映射handler源码解读
    SpringMVC自定义兼容性HandlerMapping
    spring boot自定义类配置绑定在配置文件中自动提示
  • 原文地址:https://www.cnblogs.com/wuyun-blog/p/7724495.html
Copyright © 2011-2022 走看看