webservice接口开发
对于webservice接口的开发,本次使用的是maven+Spring+CXF 。
1、在maven工程中添加 Dynamic Web Module 。具体可参见:http://blog.csdn.net/chuyuqing/article/details/28879477 这篇文章是介绍如何为maven工程添加web
2、添加maven依赖,编辑pom文件。在文件中主要是添加Spring+cxf的依赖。
3、根据已有的wsdl文件生成代码。此处使用的工具是jdk。在DOS环境中的命令格式是:<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.bonc</groupId> <artifactId>wstest</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>wstest</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.3.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.3.RELEASE</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.1.8</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http</artifactId> <version>3.1.8</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project>
wsimport -keep -d D:\temp\d -s D:\temp\s -p com.map -verbose http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl -keep:是否生成Java源文件 -d:指定.class文件的输出目录 -s:指定.java文件的输出目录 -p:定义生成类的包名,不定义的话有默认包名 -verbose:在控制台显示输出信息 -b:指定jaxws/jaxb绑定文件或额外的schemas -extension:使用扩展来支持SOAP1.2
4、实现jdk生成代码中的接口。(这里是指java的语法接口,不是指编写的功能接口)。接口如下:在这里使用JDK生成的代码里会有一个bug,需要修改。这里是对于消息请求和消息返回中的实体类中需要为属性添加类型。package cn.XXXX.ws.XXXXser; import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebResult; import javax.jws.WebService; import javax.jws.soap.SOAPBinding; import javax.xml.bind.annotation.XmlSeeAlso; import cn.XXXX.ws.XXXXser.unibssbody.QRYUSERNUMBERINPUT; import cn.XXXX.ws.XXXXser.unibssbody.QRYUSERNUMBEROUTPUT; import cn.XXXX.ws.XXXXser.unibssbody.USERDATASYNCINPUT; import cn.XXXX.ws.XXXXser.unibssbody.USERDATASYNCOUTPUT; /** * This class was generated by the JAX-WS RI. * JAX-WS RI 2.2.9-b130926.1035 * Generated source version: 2.2 * */ @WebService(name = "XXXX", targetNamespace = "http://ws.XXXX.cn/XXXXSer/") @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE) @XmlSeeAlso({ cn.XXXX.ws.unibsshead.ObjectFactory.class, cn.XXXX.ws.XXXXser.unibssbody.ObjectFactory.class, cn.XXXX.ws.XXXXser.unibssbody.userdatasyncreq.ObjectFactory.class, cn.XXXX.ws.XXXXser.unibssbody.userdatasyncrsp.ObjectFactory.class, cn.XXXX.ws.XXXXser.unibssbody.qryusernumberreq.ObjectFactory.class, cn.XXXX.ws.XXXXser.unibssbody.qryusernumberrsp.ObjectFactory.class, cn.XXXX.ws.unibssattached.ObjectFactory.class }) public interface XXXXSer { /** * * @param parameters * @return * returns cn.XXXX.ws.XXXXser.unibssbody.OUTPUT */ @WebMethod(action = "http://ws.XXXX.cn/XXXXSer/userDataSync/") @WebResult(name = "xxx_OUTPUT", targetNamespace = "http://ws.XXXX.cn/XXXXSer/unibssBody", partName = "parameters") public xxxOUTPUT xxxSync( @WebParam(name = "xxx_INPUT", targetNamespace = "http://ws.XXXX.cn/XXXXSer/unibssBody", partName = "parameters") xxxINPUT parameters); /** * * @param parameters * @return * returns cn.XXXX.ws.XXXXser.unibssbody.ROUTPUT */ @WebMethod(operationName = "xxx", action = "http://ws.XXXX.cn/XXXXSer/QryUserNumber/") @WebResult(name = "xxx_OUTPUT", targetNamespace = "http://ws.XXXX.cn/XXXXSer/unibssBody", partName = "parameters") public xxxOUTPUT xxxNum( @WebParam(name = "xxx_INPUT", targetNamespace = "http://ws.XXXX.cn/XXXXSer/unibssBody", partName = "parameters") xxxINPUT parameters); }
原生的代码会是"",这里需要添加上,否则会在发送消息是报错:@XmlType(name = "", propOrder = {"sourcesystem", "provincecode", "tradetypecode", "tradeid", "tradeinfo", "para"})
16/11/26 12:58:57 WARN phase.PhaseInterceptorChain: Interceptor for {http://service.ws.chinaunicom.cn/}SelectUserNumImplService#{http://service.ws.chinaunicom.cn/}queryUserNum has thrown exception, unwinding now org.apache.cxf.interceptor.Fault: Unmarshalling Error: 意外的元素 (uri:"http://service.ws.chinaunicom.cn/", local:"CHECK_TYPE")。所需元素为<{http://ws.chinaunicom.cn/OneCardFiveUserSer/unibssBody/QryUserNumberReq}CERT_TYPE>,<{http://ws.chinaunicom.cn/OneCardFiveUserSer/unibssBody/QryUserNumberReq}PARA>,<{http://ws.chinaunicom.cn/OneCardFiveUserSer/unibssBody/QryUserNumberReq}CERT_NAME>,<{http://ws.chinaunicom.cn/OneCardFiveUserSer/unibssBody/QryUserNumberReq}CHECK_TYPE>,<{http://ws.chinaunicom.cn/OneCardFiveUserSer/unibssBody/QryUserNumberReq}CERT_NUM> at org.apache.cxf.jaxb.JAXBEncoderDecoder.unmarshall(JAXBEncoderDecoder.java:906) at org.apache.cxf.jaxb.JAXBEncoderDecoder.unmarshall(JAXBEncoderDecoder.java:712) at org.apache.cxf.jaxb.io.DataReaderImpl.read(DataReaderImpl.java:179)
如果要覆盖(重写)JDK生成的该接口,必须要加上:
否则会在测试时出现无法接受到请求报文,或者请求报文的格式不正确。@WebService(name = "XXXX", targetNamespace = "http://ws.XXXX.cn/XXXXSer/") @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE) @XmlSeeAlso({ cn.XXXX.ws.unibsshead.ObjectFactory.class, cn.XXXX.ws.XXXXser.unibssbody.ObjectFactory.class, cn.XXXX.ws.XXXXser.unibssbody.userdatasyncreq.ObjectFactory.class, cn.XXXX.ws.XXXXser.unibssbody.userdatasyncrsp.ObjectFactory.class, cn.XXXX.ws.XXXXser.unibssbody.qryusernumberreq.ObjectFactory.class, cn.XXXX.ws.XXXXser.unibssbody.qryusernumberrsp.ObjectFactory.class, cn.XXXX.ws.unibssattached.ObjectFactory.class })
在实现该接口时,注意要将@WebService(name = "", targetNamespace = "")注解加上且与接口保持一致
5、编写beans.xml文件<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <jaxws:endpoint id="xxxNum" implementor="cn.xxx.ws.service.xxxSerImpl" address="/xxxNum"> </jaxws:endpoint> <jaxws:endpoint id="xxxImpl" implementor="cn.xxx.ws.service.xxxImpl" address="/xxxync"> </jaxws:endpoint> </beans>
bean.xml文件中元素的含义:
id:这是指生成的bean的ID,可在生成的webservice接口的客户端中使用该id来创建对应的bean
implementor="填写接口的实现类"
address="访问"
6、配置web.xml文件在web.xml中配置的是:<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>queryusernum</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <!-- 配置beans.xml --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/beans.xml</param-value> </context-param> <!-- 应用启动的一个监听器 --> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <!-- 所有请求都会先经过cxf框架 --> <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>/select*/</url-pattern> --> <url-pattern>/api/*</url-pattern> </servlet-mapping> </web-app>
1、beans.xml文件所在位置
2、cxf servlert配置,在这里我开发的这个接口含有restful接口,不能将<url-pattern><url-pattern>节点写为<url-pattern>/*<url-pattern>这样会使所有的请求都经过cxf框架,使得restful接口也得经过,会报错为cxf无该服务。
7、关于测试工具:
测试webservice接口使用的工具是SOAP UI
***********************************************分割线*******************************************************
下面是针对我自己的项目接口开发的过程中遇到的问题:
1.maven的隐式依赖冲突,解决的办法是:
对每个依赖挨个的检查,删除后手动添加jar包放到web-info文件夹下的lib目录后build-path,还有一种解决方式是在maven中添加Spring-boot这种方式解决,但是不认为是一种好的方式,因为水平原因没有继续深入的挖掘更好的解决方案。
2.当程序报错时应当使其执行结束,查看报错信息。这是在maven的隐式依赖导致的jar包不完整导致的错误,但是每次我在执行的时候,发现出错,过于着急就把其停止运行而看不到报错信息。耽搁了好长时间,具体信息如下:
这是抛出的异常,但是程序执行结束后抛出的异常是缺少一个类,通过手动的添加jar包可以解决该问题。Exception in thread "main" java.lang.IllegalArgumentException: Path length must be > 0 at org.apache.zookeeper.common.PathUtils.validatePath(PathUtils.java:48) at org.apache.zookeeper.ZooKeeper.exists(ZooKeeper.java:1024) at org.apache.hadoop.hbase.zookeeper.RecoverableZooKeeper.exists(RecoverableZooKeeper.java:199) at org.apache.hadoop.hbase.zookeeper.ZKUtil.checkExists(ZKUtil.java:479) at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.checkIfBaseNodeAvailable(HConnectionManager.java:873) at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.access$600(HConnectionManager.java:572) at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation$StubMaker.makeStubNoRetries(HConnectionManager.java:1576) at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation$StubMaker.makeStub(HConnectionManager.java:1622) at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation$MasterServiceStubMaker.makeStub(HConnectionManager.java:1676) at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.getKeepAliveMasterService(HConnectionManager.java:1884) at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.isMasterRunning(HConnectionManager.java:899) at cn.chinaunicom.ws.hbase.HBaseClient.main(HBaseClient.java:123)
3、在webservice接口中开发restful接口
使用Spring-MVC开发的restful接口,这是就不能配置所有的请求都必须经过cxf框架。通过配置url-pattern来完成的。如果不区分开会导致请求经过cxf,响应也经过cxf框架。