Ajax跨域之ContentType為application/json請求失敗的問題


項目里的接口都是用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過濾器里是這樣

 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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM