POST提交XML时Content-Type设置不当导致获取不到请求正文问题总结

开发环境: JDK7, Tomcat7.0.54, Spring3.2.6

问题描述:

客户端: (外部系统)通过HTTP的POST方法提交了一个XML给我

但是请求头 Content-Type 被设置成了 application/x-www-form-urlencoded (浏览器form表单提交的默认编码类型)

也就是说, 请求的正文不是   &key1=value1&key2=value2   这样的格式  而是xml内容:  <?xml version="1.0" encoding="GBK"?><data><msg>test</msg></data>

代码类似于:

173714_dHm8_181985.jpg


服务端:通过request.getInputStream()获取到流, 然后读取流来获得POST过来的xml

但是, 就是获取到的xml却为空, 为什么? 

代码类似于:

174204_um6V_181985.jpg


于是到处找原因啊,找啊找啊找不到...................................

然后输出了下客户端请求是的Content-Type头,发现居然是application/x-www-form-urlencoded你这不是坑我吗~~~~~~~~~~~~~~~~~

马上联想到 reqeust.getParam* 一系列方法, 对于表单提交的字段, 可以通过这个方法来获取到, 但是原始的POST正文都是 &key1=value1&key2=value2 这种形式

于是猜想: 肯定是Tomcat帮我们做了解析, 一解析的话, 肯定得读流啊, 所以当我获取到流的时候, 流已经被处理掉了, 所以我获取不到原始的请求正文了.

为了证明猜想, 下载Tomcat7源码看了下,发现果然是这样的 (org.apache.catalina.connector.Request.parseParameters()), 如图所示:

175343_Yvd3_181985.jpg

但是, 这个方法只有在调用 request.getParam* 等方法的时候才会触发解析操作.  看我上面服务端代码截图,第一行就是读流操作, 并没有request.getParam* 等方法的调用

百思不得其姐..............................

于是祭出终极手段,  搭建tomcat源码工程, 具体步骤见: http://my.oschina.net/haogrgr/blog/294274

在解析方法打上断点, 目的是为了查看调用堆栈, 找到触发解析的点.

最后终于找到了.......

项目里面用了Spring mvc, 然后加上了org.springframework.web.filter.HiddenHttpMethodFilter这个过滤器

该过滤器是因为浏览器不支持HTTP的PUT, DELETE等方法, 于是Spirng想出来一种办法, 通过为表单添加一个隐藏域

类似于:  <input type="hidden" name="_method" value="PUT">

然后对每个请求拦截: 然后通过request.getParam("_method")来决定是不是要对request进行wrapper,如果该参数不为空,就包装为HttpMethodRequestWrapper,重写getMethod方法

妈的,跑题了.......

回到主题, 就是这个Filter调用了reqeuest.getParam()方法,而且 Content-Type为:application/x-www-form-urlencoded 所以触发了Tomcat对请求正文流的解析,导致我后面获取不到正文.

180916_3NgS_181985.jpg


于是怎么解决呢?  最简单的方法, 项目中没有用到除GET和POST外的其他HTTP方法, so 去掉这个Filter , 啊,这个世界清静了................

但是, 如果我项目硬是要用这个Filter呢, 怎 末 办 ...........

蛋疼的解决办法来了:

写个Filter,放在web.xml的最前面(第一个), 然后在里面讲流的内容读完放到byte[]数组中缓存起来.....(可以缓存起来放入RequestWrapper对象中)

然后该Filter只拦截需要获取请求正文的url, 否则,其他Servlet将无法从request.getParam中获取参数......

你说什么, 你又要获取请求正文,又要调用request.getParam方法获取参数,  行, 将RequestWrapper对象的getParam等方法重写,自己按标准解析Post正文....


其实: 最好的解决办法, 是让客户端按标准来, 将请求正文类型改成 text/xml

但是, 你懂的~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

对方不按套路来, 一般人根本就把持不住啊~~~~~~~~~~~~~~~~~~~~~~~~~~~~


转载于:https://my.oschina.net/haogrgr/blog/294995

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值