ajax訪問WebService跨域問題


1、先看一個網站介紹,了解跨域問題    HTTP訪問控制(CORS)

2、像谷歌、火狐瀏覽器對一些非簡單請求會觸發預檢請求,首先使用 OPTIONS   方法發起一個預檢請求到服務器,然而IE瀏覽器沒有預檢請求

 

3、發起預檢請求,如果想要后台處理成功,那么就需要服務器處理返回響應,設置允許的請求頭,設置允許跨域等(對WebService研究較淺,沒有找到對預檢請求設置的方法,后期會深入學習)

 

4、在測試中使用谷歌,如果不設置contenttype,默認為 text/plain;charset=UTF-8或application/x-www-form-urlencoded,更改為其他兩個都不會觸發預檢請求

5、谷歌瀏覽器ajax設置contenttype為text/xml時,對JDK發布的WebService和CXF發布的WebService錯誤顯示如下

JDK發布的WebService服務

1)后台報錯、找到com.sun.xml.internal.ws.transport.http.server.WSHttpHandler這個類,在handle方法處打斷點,可以在參數中看到請求的信息,method為options;然后運行完控制台報錯(使用IE就沒事)

com.sun.xml.internal.ws.transport.http.server.WSHttpHandler handleExchange
警告: Cannot handle HTTP method: OPTIONS

這就是瀏覽器的預檢請求導致,網上有設置如果檢測到請求方法是OPTIONS就設置返回狀態為200

 2)前台報錯、console下報錯:OPTIONS http://localhost:8088/aaa net::ERR_EMPTY_RESPONSE

然后在network下找到發送的ajax請求,點擊,Request Headers有警告Provisional headers are shown

正常情況下請求頭會顯示一些其他信息如Accept-Language、Accept-Encoding等

3)ajax不設置contenttype、請求后台就報錯

Unsupported Content-Type: text/plain;charset=UTF-8 Supported ones are: [text/xml]
com.sun.xml.internal.ws.server.UnsupportedMediaException: Unsupported Content-Type: text/plain;charset=UTF-8 Supported ones are: [text/xml]

也就是建議設置Content-Type為text/xml;但是設置成text/xml就會觸發預檢測

前台Console報錯   No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8083' is therefore not allowed access. The response had HTTP status code 415.估計是后台異常,沒有設置響應頭非同源訪問的權限

此處可以看到請求頭默認Content-Type為text/plain;charset=UTF-8

CXF發布的WebService服務

1)、后台報錯、找到類org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor斷點到handleMessage方法,查看message參數

后台報錯

Interceptor for {http://server.hjp.com/}PersonService1Service has thrown exception, unwinding now
org.apache.cxf.binding.soap.SoapFault: Error reading XMLStreamReader.

可見也是預檢測請求導致

2)前端報錯:OPTIONS http://localhost:5555/hello 500 (Server Error)和Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.  network中的ajax請求頭中沒有Content-Type

3)如果去掉ajax對contenttype設置,前端會報錯No 'Access-Control-Allow-Origin' header is present on the requested resource

6、ajax請求WebService代碼(使用IE訪問沒問題)

1)、jQuery形式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="jquery-3.1.0.min.js"></script>
</head>
<body>
<div id="d"></div>
<script type="text/javascript">
    $.ajax({
        url: "http://localhost:5555/hello",
        type: "POST",
        contentType:"text/xml;charset=UTF-8",
        data: getPostData(),
        success: function (data) {
            var doc = $(data).find('return');
            doc.each(function(){
                $('#d').html($(this).text());
            });
        }
    });
//定義滿足SOAP協議的參數。
    function getPostData() {
        var soap='<?xml version="1.0" encoding="UTF-8"?>'+
                '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://server.hjp.com/">' +
                '<soapenv:Header/>' +
                '<soapenv:Body>' +
                '<ser:sayHello>' +
                '<arg0>aaa</arg0>' +
                '</ser:sayHello>' +
                '</soapenv:Body>' +
                '</soapenv:Envelope>';
        return soap;
    }
</script>
</body>
</html>

2)、原生Ajax形式

<html>
<head>
    <meta charset="UTF-8"/>
    <title>通過ajax調用WebService服務</title>
    <script>
        function getXhr(){
            var xhr = null;
            if(window.XMLHttpRequest){
                //非ie瀏覽器
                xhr = new XMLHttpRequest();
            }else{
                //ie瀏覽器
                xhr = new ActiveXObject('Microsoft.XMLHttp');
            }
            return xhr;
        }
        var xhr =getXhr();
        function sendMsg(){
            var name = document.getElementById('name').value;
            //服務的地址
            var wsUrl = 'http://localhost:8088/tongwei';

            //請求體
            var soap=getPostData(name);

            //打開連接
            xhr.open('POST',wsUrl,true);

            //重新設置請求頭
            xhr.setRequestHeader("content-type","text/xml");

            //設置回調函數
            xhr.onreadystatechange = _back;

            //發送請求
            xhr.send(soap);
        }

        function _back(){
            if(xhr.readyState == 4){
                if(xhr.status == 200){
                    var ret = xhr.responseXML;
                    var msg = ret.getElementsByTagName('return')[0];
                    document.getElementById('showInfo').innerHTML = msg.textContent;
                }
            }
        }
        //定義滿足SOAP協議的參數。
        function getPostData(name) {
            var postdata ='<?xml version="1.0" encoding="UTF-8"?>'+
                    '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ton="http://tongwei/">' +
                '<soapenv:Header/>' +
                '<soapenv:Body>' +
                '<ton:test>' +
                '<parStr>'+name+'</parStr>' +
                '</ton:test>' +
                '</soapenv:Body>' +
                '</soapenv:Envelope>';
        return postdata;
        }
    </script>
</head>
<body>
<input type="button" value="發送SOAP請求" onclick="sendMsg();">
<input type="text" id="name">
<div id="showInfo">
</div>
</body>
</html>

7、java后台URL請求WebService方式

public static void main(String[] args) throws IOException {


          /*
         *1.創建一個url
         *2.打開一個連接
         *3.設置相關參數
         *4.創建輸出流,用來發送SAOP請求
         *5.發送完,接收數據
         *6.用輸入流獲取webservice中的內容
         */

        URL url = new URL("http://localhost:5555/hello");
        HttpURLConnection connection = (HttpURLConnection)url.openConnection();
        connection.setRequestMethod("POST");//必須設置為POST方式,而且必須是大寫的
        connection.setDoInput(true);//因為有輸入參數也有輸出參數所以都為真
        connection.setDoOutput(true);
        connection.setRequestProperty("Content-Type", "text/xml;charset=utf-8");

        OutputStream out = connection.getOutputStream();
//下面替換尖括號是測試傳送xml文本字符串測試的
        //String str="<list><item><email>aaa!qq</email></item></list>";
        //str=str.replaceAll("<","&lt;").replaceAll(">","&gt;");
        StringBuilder soap=new StringBuilder();
        soap.append("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ser=\"http://server.hjp.com/\">");
        soap.append("<soapenv:Header/>");
        soap.append("<soapenv:Body>");
        soap.append("<ser:sayHello>");
        soap.append("<arg0>aaa</arg0>");
        soap.append("</ser:sayHello>");
        soap.append("</soapenv:Body>");
        soap.append("</soapenv:Envelope>");
        String argo=soap.toString();
        System.out.println(argo);
        out.write(argo.getBytes());//發送SAOP請求
        InputStream stream = connection.getInputStream();
        byte[] b = new byte[1024];
        int len=0;
        StringBuffer buffer = new StringBuffer();
        while((len=stream.read(b))!=-1){
            String s = new String(b, 0, len, "utf-8");
            buffer.append(s);
        }

        System.out.println(buffer.toString());

    }

8、請求頭和響應頭編寫及處理返回值是借助SOAPUI工具,界面如下

 


免責聲明!

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



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