客户端使用 IE8 或 IE9 向我使用 Spring 3.1 的域发出 CORS 请求 - 就像这样。
if ($.browser.msie && window.XDomainRequest)
{
var xdr = new XDomainRequest();
xdr.open("post", "http://example.com/corstest/testPost");
xdr.onload = function() {
var dom = new ActiveXObject("Microsoft.XMLDOM");
dom.async = false;
dom.loadXML(xdr.responseText);
$("#corsdiv").html(xdr.responseText);
};
xdr.send("param1=abc");
return false;
}
else
{
$.ajax({
url: "http://example.com/corstest/testPost",
type: "POST",
data: "param1=abc",
success: function( data ) {
$("#corsdiv").html(data);
},
});
return false;
}
在服务器上,在控制器中:
@RequestMapping(value = "/testPost", method = RequestMethod.POST)
public @ResponseBody String testPost(@RequestParam Map<String,String> body, Model model, HttpServletRequest request)
{
logger.info("Content-type: " + request.getContentType() + ";" + request.getContentLength() + ";" + request.getParameter("param1"));
logger.info("body:" + body.toString() );
return "Success";
}
给出以下输出:
For IE9:
INFO : Content-type: null;10;null
INFO : body:{}
For Firefox:
INFO : Content-type: application/x-www-form-urlencoded; charset=UTF-8;10;abc
INFO : body:{param1=abc}
我知道对于 IE8/9 CORS 请求,请求的 Content-Type 标头仅支持 text/plain。(参考: http: //blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx)据我了解,这就是Spring不绑定请求的原因IE8/IE9 - 因为它期望 application/x-www-form-urlencoded 作为 Content-Type。
我使用过滤器拦截传入的请求,并将所有请求的 ContentType 设置为“application/x-www-form-urlencoded; charset=UTF-8”(现在用于测试目的)。
参考使用 servlet filter 修改请求参数,我将 HttpServletRequest 包装在 HttpServletRequestWrapper 中,它覆盖了 getContentType、getCharacterEncoding、getHeader、getHeaderNames 和 getHeaders 方法,并将其传递给 Filter 上的 chain.doFilter() 方法。
我得到的输出是:
For IE9:
INFO : Content-type application/x-www-form-urlencoded; charset=UTF-8;10;null
INFO : body:{}
For Firefox:
INFO : Content-type: application/x-www-form-urlencoded; charset=UTF-8;10;abc
INFO : body:{param1=abc}
绑定不生效。
我的问题是:
- 是否可以使用这种方法让 spring 绑定来自 IE8/9 CORS 请求的数据。如果是 - 我做错了什么?
- 如果不是 - 为什么,我还有哪些其他选择才能完成这项工作?
更新:
在进一步调查中,我发现 Spring 使用 request.getParameterMap() 在 WebRequestDatabinder 中绑定请求数据——我没有在 HttpServletRequestWrapper 中覆盖它。
以下是在将 FORM 后的数据填充到 servlet 容器设置的参数之前必须满足的条件(http://java.boot.by/wcd-guide/ch01s02.html):
- 该请求是 HTTP 或 HTTPS 请求。
- HTTP 方法是 POST。
- 内容类型为 application/x-www-form-urlencoded。
- servlet 已对请求对象的任何“getParameter”系列方法进行了初始调用。
由于 servlet 容器将 content-Type 视为 text/plain,因此它不会将请求正文解析为 Parameter Map。Spring 找到一个空的 Parameter Map,因此不绑定数据。