1. 概念了解
WebService是两个系统的远程调用,使两个系统进行数据交互,如应用:天气预报服务、银行ATM取款、使用邮箱账号登录各网站等。
WebService之间的调用是跨语言的调用。Java、.Net、php,发送Http请求,使用的数据格式是XML格式。
webxml.com.cn上面有一些免费的WebService服务,可以进去看看。
2. 客户端实现的几种方式
2.1 Wsimport实现方式
概念理解:
WSDL – WebService Description Language – Web服务描述语言。通过XML形式说明服务在什么地方-地址。address location通过XML形式说明服务提供什么样的方法 – 如何调用。operation注意:该种方式使用简单,但一些关键的元素在代码生成时写死到生成代码中,不方便维护,所以仅用于测试。
实现方式: (1)Wsimport命令介绍 Wsimport就是jdk(1.6版本之后)提供的的一个工具,他的作用就是根据WSDL地址生成客户端代码; Wsimport位置JAVA_HOME/bin Wsimport常用的参数: -s,生成java文件的 -d,生成class文件的,默认的参数 -p,指定包名的,如果不加该参数,默认包名就是wsdl文档中的命名空间的倒序;
public class MobileClient { public static void main(String[] args) { //创建服务访问点集合的对象 ,wsdl文档中:<wsdl:service name="MobileCodeWS"> MobileCodeWS mobileCodeWS = new MobileCodeWS(); //获取服务实现类,wsdl中:<wsdl:portType name="MobileCodeWSSoap"> MobileCodeWSSoap mobileCodeWSSoap = mobileCodeWS.getPort(MobileCodeWSSoap.class); //根据服务访问点的集合中的服务访问点的绑定对象来获得绑定的服务类 MobileCodeWSSoap mobileCodeWSSoap = mobileCodeWS.getMobileCodeWSSoap(); String mobileCodeInfo = mobileCodeWSSoap.getMobileCodeInfo("18518114962", ""); System.out.println(mobileCodeInfo); } }2.2 service实现方式
service编程调用方式 ,这种方式其实就是只需引用服务的方法类就行,不需要全部引用。
public class ServiceClient { public static void main(String[] args) throws IOException { //创建WSDL的URL,注意不是服务地址 URL url = new URL("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl"); //创建服务名称 //1.namespaceURI - 命名空间地址 (wsdl文档中的targetNamespace) //2.localPart - 服务视图名 ,wsdl文档中:<wsdl:service name="MobileCodeWS"> QName qname = new QName("http://WebXml.com.cn/", "MobileCodeWS"); / /wsdlDocumentLocation - wsdl地址 ,serviceName - 服务名称 Service service = Service.create(url, qname); //获取服务实现类 wsdl中:<wsdl:portType name="MobileCodeWSSoap"> MobileCodeWSSoap mobileCodeWSSoap = service.getPort(MobileCodeWSSoap.class); //调用查询方法 String result = mobileCodeWSSoap.getMobileCodeInfo("1866666666", ""); System.out.println(result); } }2.3 HttpURLConnection调用方式
操作步骤,开发步骤: 第一步:创建服务地址 第二步:打开一个通向服务地址的连接 第三步:设置参数 设置POST,POST必须大写,如果不大写,报异常 第四步:组织SOAP数据,发送请求 第五步:接收服务端响应,打印
public class HttpURLConectionMode { public static void main(String[] args) throws IOException { //第一步:创建服务地址,不是WSDL地址 URL url = new URL("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx"); //第二步:打开一个通向服务地址的连接 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); //第三步:设置参数 //3.1发送方式设置:POST必须大写 connection.setRequestMethod("POST"); //3.2设置数据格式:content-type connection.setRequestProperty("content-type", "text/xml;charset=utf-8"); //3.3设置输入输出,因为默认新创建的connection没有读写权限, connection.setDoInput(true); connection.setDoOutput(true); //第四步:组织SOAP数据,发送请求 String soapXML = getXML("15226466316"); OutputStream os = connection.getOutputStream(); os.write(soapXML.getBytes()); //第五步:接收服务端响应,打印(xml格式数据) int responseCode = connection.getResponseCode(); if(200 == responseCode){//表示服务端响应成功 InputStream is = null; InputStreamReader isr = null; BufferedReader br = null; StringBuilder sb = null; try { is = connection.getInputStream(); isr = new InputStreamReader(is); br = new BufferedReader(isr); sb = new StringBuilder(); String temp = null; while(null != (temp = br.readLine())){ sb.append(temp); } System.out.println(sb.toString()); } catch (Exception e) { e.printStackTrace(); throw e; } finally { br.close(); isr.close(); is.close(); } } os.close(); } public static String getXML(String phoneNum){ String soapXML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +"<soap:Body>" +"<getMobileCodeInfo xmlns=\"http://WebXml.com.cn/\">" +"<mobileCode>"+phoneNum+"</mobileCode>" +"<userID></userID>" +"</getMobileCodeInfo>" +"</soap:Body>" +"</soap:Envelope>"; return soapXML; } }2.4 Ajax调用方式
jsonp无法实现跨域,因为webservice服务的响应格式为xml格式;
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script type="text/javascript"> function queryMobile(){ //创建XMLHttpRequest对象 var xhr = new XMLHttpRequest(); //打开连接 xhr.open("post","http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx",true); //设置数据类型 xhr.setRequestHeader("content-type","text/xml;charset=utf-8"); //设置回调函数 xhr.onreadystatechange=function(){ //判断是否发送成功和判断服务端是否响应成功 if(4 == xhr.readyState && 200 == xhr.status){ alert(xhr.responseText); } } //组织SOAP协议数据 var soapXML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +"<soap:Body>" +"<getMobileCodeInfo xmlns=\"http://WebXml.com.cn/\">" +"<mobileCode>"+document.getElementById("phoneNum").value+"</mobileCode>" +"<userID></userID>" +"</getMobileCodeInfo>" +"</soap:Body>" +"</soap:Envelope>"; alert(soapXML); //发送数据 xhr.send(soapXML); } </script> </head> <body> 手机号查询:<input type="text" id="phoneNum"/> <input type="button" value="查询" onclick="javascript:queryMobile();"/> </body> </html>下面图是展示wsdl文档中的关键字段,以及对服务方法的如何使用以及功能描述
3 .服务端的实现
服务端使用cfx+spring和注解实现服务端发布
pom文件添加jar包
<!-- 添加cxfwebservice依赖jar包 2018-07-05 --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>2.5.1</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http</artifactId> <version>2.5.1</version> </dependency>web.xml添加配置
<!-- cxf WEBSERVICE配置 --> <servlet> <servlet-name>CXFServlet</servlet-name> <servlet-class> org.apache.cxf.transport.servlet.CXFServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>CXFServlet</servlet-name> <url-pattern>/renewal/*</url-pattern> </servlet-mapping>spring配置文件添加配置
<!-- 添加cxfwebservice文件 --> <import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <!--下面的class属性值一定要跟你项目中服务实现类的包路径完全一致 --> <jaxws:endpoint id="renewalPaymentLock" implementor="com.sinosoft.sinopay.web.weixinpay.biz.service.impl.RenewalPaymentLockServiceImpl" address="/RenewalPaymentLock" />最终生成是地址是: ip/renewal/RenewalPaymentLock?wsdl (web.xml+springd拼接而成的)
接口中伪代码实现:
@WebService public interface RenewalPaymentLockService { @WebMethod public String RenewalPaymentLock(String renewalJson); }实现类注解:
@WebService(endpointInterface = "com.sinosoft.sinopay.web.weixinpay.biz.service.RenewalPaymentLockService") endpointInterface 是接口中的地址(包名)参考文章:https://blog.csdn.net/menghuanzhiming/article/details/78475785