Ajax跨域之ContentType为application/json请求失败的问题
2017-12-14 19:39
495 查看
项目里的接口都是用springmvc写的,其中在@requestmapping接口中定义了consumes="application/json",也就是该接口只接受ContentType为application/json的请求。
接口写好用工具测试接口都是可以正常请求,但是在浏览器中用ajax请求就不行。
百度一下,原来在使用Ajax跨域请求时,如果设置Header的ContentType为application/json,会分两次发送请求。第一次先发送Method为OPTIONS的请求到服务器,这个请求会询问服务器支持哪些请求方法(GET,POST等),支持哪些请求头等等服务器的支持情况。等到这个请求返回后,如果原来我们准备发送的请求符合服务器的规则,那么才会继续发送第二个请求,否则会在Console中报错。
为什么在跨域的时候设置ContentType为application/json时会请求两次?其实JQuery的文档对此有做说明。
contentType (default: 'application/x-www-form-urlencoded; charset=UTF-8')
Type: Boolean or String
When sending data to the server, use this content type. Default is "application/x-www-form-urlencoded; charset=UTF-8", which is fine for most cases. If you explicitly pass in a content-type to $.ajax(), then it is always sent to the server (even if no data is sent). As of jQuery 1.6 you can pass false to tell jQuery to not set any content type header. Note: The W3C XMLHttpRequest specification dictates that the charset is always UTF-8; specifying another charset will not force the browser to change the encoding. Note: For cross-domain requests, setting the content type to anything other than application/x-www-form-urlencoded, multipart/form-data, or text/plain will trigger the browser to send a preflight OPTIONS request to the server.
注意Note后面的描述,在跨域的时候,除了contentType为application/x-www-form-urlencoded,multipart/form-data或者text/plain外,都会触发浏览器先发送方法为OPTIONS的请求。
比如说,你原来的请求是方法方法POST,如果第一个请求返回的结果Header中的Allow属性并没有POST方法,那么第二个请求是不会发送的,此时浏览器控制台会报错,告诉你POST方法并不被服务器支持。
图中箭头指向的Allow就是服务器返回的支持的方法。
不仅如此,如果想要用ContentType:application/json发送跨域请求,服务器端还必须设置一个名为Access-Control-Allow-Headers的Header,将它的值设置为 Content-Type,表明服务器能够接收到前端发送的请求中的ContentType属性并使用它的值。否则第二次请求也是发不出去的,浏览器console会报错,并提示你服务器没有设置Access-Control-Allow-Headers。
对应到我java程序的filter过滤器里是这样
接口写好用工具测试接口都是可以正常请求,但是在浏览器中用ajax请求就不行。
百度一下,原来在使用Ajax跨域请求时,如果设置Header的ContentType为application/json,会分两次发送请求。第一次先发送Method为OPTIONS的请求到服务器,这个请求会询问服务器支持哪些请求方法(GET,POST等),支持哪些请求头等等服务器的支持情况。等到这个请求返回后,如果原来我们准备发送的请求符合服务器的规则,那么才会继续发送第二个请求,否则会在Console中报错。
为什么在跨域的时候设置ContentType为application/json时会请求两次?其实JQuery的文档对此有做说明。
contentType (default: 'application/x-www-form-urlencoded; charset=UTF-8')
Type: Boolean or String
When sending data to the server, use this content type. Default is "application/x-www-form-urlencoded; charset=UTF-8", which is fine for most cases. If you explicitly pass in a content-type to $.ajax(), then it is always sent to the server (even if no data is sent). As of jQuery 1.6 you can pass false to tell jQuery to not set any content type header. Note: The W3C XMLHttpRequest specification dictates that the charset is always UTF-8; specifying another charset will not force the browser to change the encoding. Note: For cross-domain requests, setting the content type to anything other than application/x-www-form-urlencoded, multipart/form-data, or text/plain will trigger the browser to send a preflight OPTIONS request to the server.
注意Note后面的描述,在跨域的时候,除了contentType为application/x-www-form-urlencoded,multipart/form-data或者text/plain外,都会触发浏览器先发送方法为OPTIONS的请求。
比如说,你原来的请求是方法方法POST,如果第一个请求返回的结果Header中的Allow属性并没有POST方法,那么第二个请求是不会发送的,此时浏览器控制台会报错,告诉你POST方法并不被服务器支持。
图中箭头指向的Allow就是服务器返回的支持的方法。
不仅如此,如果想要用ContentType:application/json发送跨域请求,服务器端还必须设置一个名为Access-Control-Allow-Headers的Header,将它的值设置为 Content-Type,表明服务器能够接收到前端发送的请求中的ContentType属性并使用它的值。否则第二次请求也是发不出去的,浏览器console会报错,并提示你服务器没有设置Access-Control-Allow-Headers。
对应到我java程序的filter过滤器里是这样
1 public class MyFilter implements Filter { 2 3 @Override 4 public void destroy() { 5 //System.out.println("过滤器销毁"); 6 } 7 8 @Override 9 public void doFilter(ServletRequest request, ServletResponse response, 10 HttpServletRequest httpRequest = (HttpServletRequest) request; 11 String type=httpRequest.getMethod(); 12 13 if (type.toUpperCase().equals("OPTIONS")==true) { 14 httpResponse.setHeader("Access-Control-Allow-Headers", "content-type, accept"); 15 httpResponse.setHeader("Access-Control-Allow-Methods", "POST"); 16 httpResponse.setStatus(200); 17 httpResponse.setContentType("text/plain;charset=utf-8"); 18 httpResponse.setCharacterEncoding("utf-8"); 19 responseContentByte="{\"test\":\"OPTIONS\"}".getBytes(); 20 } 21 } 22 23 @Override 24 public void init(FilterConfig arg0) throws ServletException { 25 //System.out.println("过滤器初始化"); 26 } 27 28 }
相关文章推荐
- dhl:ajax无法跨域改用getJSON(解决服务器返回json数据中文为乱码的问题$.ajaxSetup({ scriptCharset: "utf-8" , contentType: "application/json; chars)
- token获取不到,原来是数据格式的问题 要和后台的数据格式一致,$.ajax中contentType: “application/json” 的用法
- 前端使用Jquery的getJSON方法,后台使用PHP,解决IE和火狐Firefox中存在的跨域ajax请求问题。
- ajax请求里的contentType: "application/json"作用
- ajax请求json类型无法跨域传递cookie的问题解决
- 夺命雷公狗jquery---62通过$.getJSON来解决Ajax跨域请求问题
- 使用jsonp解决ajax请求json跨域问题
- java ajax post跨域请求传递json格式数据问题
- AJAX 跨域请求 - JSONP获取JSON数据
- AJAX 跨域请求 - JSONP获取JSON数据
- Ajax 跨域请求 Access-Control-Allow-Origin 问题
- 解决ajax请求返回Json无法解析"\"字符的问题
- 关于AJAX请求JSON数据(解决responseText空的问题)
- AJAX 跨域请求 - JSONP获取JSON数据
- AJAX 跨域请求 - JSONP获取JSON数据
- 解决ajax跨域请求问题
- Ajax跨域请求SessionID不相同问题
- nginx配置 解决ajax请求跨域问题
- AJAX跨域请求json数据的实现方法
- AJAX 跨域请求 - JSONP获取JSON数据