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("<","<").replaceAll(">",">"); 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工具,界面如下