WebServices 开发规范java版
第一章 开发前提
2.1开发工具
采用Eclipse或MyEclipse为基本开发工具。
2.2开发环境
CXF已安装,我们采用CXF 2.2.4版本。
JDK已安装,CXF 2.2.4版本需要JDK1.5或更高版本。
WEB容器已安装,我们采用tomcat6.0。
第二章:完全基于CXF2.2.4框架的实现
方法:wsdl优先
步骤一:获取WSDL及SCHEMA文件,作为服务开发阶段WSDL及SCHEMA文件可以从ESB服务管理平台下载。
示例:HelloESBService服务:
headerOfResponse.xsd
HelloESBService.xsd
HelloService.wsdl
步骤二:新建两个web工程,一个作为服务端程序,一个作为客户端程序。在服务端工程及客户端工程中创建ant build.xml文件,以生成相应的服务端代码和客户端代码。服务端的Ant脚本如下。
<?xml version="1.0" encoding="UTF-8"?> <project name="cxf wsdl2java" default="cxfWSDLToJava" basedir="."> <property name="cxf.home" location ="E:\backup\jar\apache-cxf-2.2.4"/>
<path id="cxf.classpath"> <fileset dir="${cxf.home}/lib"> <include name="*.jar"/> </fileset> </path>
<target name="cxfWSDLToJava"> <ant target="helloESBCodeGenServer"></ant> </target>
<target name="helloESBCodeGenServer"> <java classname="org.apache.cxf.tools.wsdlto.WSDLToJava" fork="true"> <arg value="-impl"/> <arg value="-server"/> <arg value="-d"/> <arg value="src"/> <arg value="-quiet"/> <arg value="wsdl/HelloESB/HelloESBService.wsdl"/> <classpath> <path refid="cxf.classpath"/> </classpath> </java> </target> </project> |
生成客户端的Ant脚本如下。
<?xml version="1.0" encoding="UTF-8"?> <project name="cxf wsdl2java" default="cxfWSDLToJava" basedir="."> <property name="cxf.home" location ="E:\backup\jar\apache-cxf-2.2.4"/>
<path id="cxf.classpath"> <fileset dir="${cxf.home}/lib"> <include name="*.jar"/> </fileset> </path>
<target name="cxfWSDLToJava"> <ant target="helloESBCodeGen"></ant> </target>
<target name="helloESBCodeGen"> <java classname="org.apache.cxf.tools.wsdlto.WSDLToJava" fork="true"> <arg value="-client"/> <arg value="-d"/> <arg value="src"/> <arg value="-quiet"/> <arg value="resources/wsdl/helloesbservice/HelloESBService.wsdl"/> <classpath> <path refid="cxf.classpath"/> </classpath> </java> </target> </project> |
注:根据情况更改红色部分的参数,location属性表示CXF的安装路径,arg部分表示wsdl的相对路径。
运行ant脚本,生成服务端和客户端代码。
步骤三:在服务端工程中实现服务端业务逻辑。
在服务端工程中打开自动生成的HelloESBServiceImpl.java,在sayHello方法中添加自己的逻辑。
/** * Please modify this class to meet your needs * This class is not complete */
package org.example.helloesbservice;
import java.util.logging.Logger; 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 com.srcb.esb.ResponseHeaderType;
/** * This class was generated by Apache CXF 2.2.4 * Mon Dec 21 09:47:49 CST 2009 * Generated source version: 2.2.4 * */
@javax.jws.WebService( serviceName = "HelloESBService", portName = "HelloESBServiceSOAP", targetNamespace = "http://www.example.org/HelloESBService/", wsdlLocation = "classpath:wsdl/helloesbservice/HelloESBService.wsdl", endpointInterface = "org.example.helloesbservice.HelloESBService")
public class HelloESBServiceImpl implements HelloESBService { private static final Logger LOG = Logger.getLogger(HelloESBServiceImpl.class.getName()); Public HelloESBResponseType sayHello(HelloESBRequestType parameters) { LOG.info("Executing operation sayHello"); System.out.println(parameters); try { HelloESBResponseType _return = null; _return = new HelloESBResponseType(); ResponseHeaderType rht = new ResponseHeaderType(); rht.setResponseCode("000000"); rht.setResponseType("this is a successful message!"); _return.setReplyInformation(rht); _return.setResponseMessage("hello,ESB,welcome!"); return _return; } catch (Exception ex) { ex.printStackTrace(); throw new RuntimeException(ex); } }
} |
步骤四:集成spring发布服务。CXF中常用的SOAP传输方式有两种,即HTTP方式及jms/mq方式,当用jms/mq传输soap时,jms资源引用主要有JNDI资源方式及spring bean配置方式(本文只介绍JNDI配置方法)。
集成spring
在服务端工程的web.xml中加入如下配置
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--CXFServlet --> <servlet> <servlet-name>cxfServlet</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> <load-on-startup>3</load-on-startup> </servlet> <servlet-mapping> <servlet-name>cxfServlet</servlet-name> <url-pattern>/WS/*</url-pattern> </servlet-mapping> |
客户端工程的web.xml中加入如下配置
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> |
HTTP传输配置
注意:采用HTTP方式时,要把wsdl里面的
<soap:binding style="document"transport="http://cxf.apache.org/transports/jms"/>
改成
<soap:binding style="document" transport=" http://schemas.xmlsoap.org/soap/http"/>
Spring配置
服务端
<?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:cxf="http://cxf.apache.org/core" xmlns:soap="http://cxf.apache.org/bindings/soap" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://cxf.apache.org/bindings/soap http://cxf.apache.org/schema/bindings/soap.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd ">
<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-extension-local.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-http.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<bean id="helloESBServiceImpl" class="org.example.helloesbservice.HelloESBServiceImpl"></bean>
<jaxws:endpoint id="HelloESBService" implementor="#helloESBServiceImpl" address="/HelloESBService" /> </beans>
|
配置说明
<bean id="helloESBServiceImpl" class="org.example.helloesbservice.HelloESBServiceImpl"></bean> |
配置服务端实现bean,可以使用spring的依赖注入功能。
<jaxws:endpoint id="HelloESBService" implementor="#helloESBServiceImpl" address="/HelloESBService"></jaxws:endpoint> |
Jaxws:endpoint发布一个服务端点。
Implementor属性:指定服务的实现。可以是一个服务实现类的类名,也可以是一个bean的id,当为一个bean的id时,需加”#”前缀。
客户端
<?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:cxf="http://cxf.apache.org/core" xmlns:soap="http://cxf.apache.org/bindings/soap" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://cxf.apache.org/bindings/soap http://cxf.apache.org/schema/bindings/soap.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd ">
<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-extension-local.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-http.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxws:client id=" helloESBServiceClient" serviceClass="org.example.helloesbservice.HelloESBService" address=" http://localhost:9999/CXF/WS/HelloESBService"> </jaxws:client> </beans>
|
配置说明
<jaxws:client id=" helloESBServiceClient" serviceClass="org.example.helloesbservice.HelloESBService" address=" http://localhost:9999/CXF/WS/HelloESBService"> </jaxws:client> |
配置服务客户端bean,serviceClass属性指定服务接口,address指定服务地址。
部署服务
将服务端程序部署到web容器中,启动容器,服务将发布成功。
测试服务
在客户端程序中新建一个jsp,通过访问jsp来测试webservice。Jsp中测试代码如下。
<% ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getSession().getServletContext()); HelloESBService helloEsb = (HelloESBService)context.getBean("helloESBServiceClient"); HelloESBRequestType responseType = new HelloESBRequestType(); responseType.setRequestName("youname"); System.out.println(helloEsb.sayHello(responseType).getResponseMessage()); %> |
context.getBean("helloESBServiceClient"):从spring Ioc中获得服务客户端bean。
访问该jsp将测试该服务的连通性。
Jms/mq传输JNDI资源方式
Spring配置
服务端
<?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:cxf="http://cxf.apache.org/core" xmlns:soap="http://cxf.apache.org/bindings/soap" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jms="http://cxf.apache.org/transports/jms" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://cxf.apache.org/bindings/soap http://cxf.apache.org/schema/bindings/soap.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://cxf.apache.org/transports/jms http://cxf.apache.org/schemas/configuration/jms.xsd">
<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-extension-local.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-http.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-jms.xml" />
<!-- jms目的地配置 --> <jms:destination name="{http://esb.service.huateng.com/abstraction/atomic/technical.HelloService/1_0}HelloService.jms-destination"> <jms:runtimePolicy useMessageIDAsCorrelationID="true" transactional="true"/> <jms:address destinationStyle="queue" jndiConnectionFactoryName="ESBQCF" jndiDestinationName="REQUESTQ"> <jms:JMSNamingProperty name="java.naming.factory.initial" value="com.sun.jndi.fscontext.RefFSContextFactory" /> <jms:JMSNamingProperty name="java.naming.provider.url" value="file:/D:/JndiCfg" /> </jms:address> </jms:destination>
<jaxws:endpoint id="HelloServiceJmsEpr" implementor="com.huateng.service.esb.abstraction.atomic.technical_helloservice._1_0.HelloServicePortTypeImpl" address="jms:/" />
</beans>
|
配置说明
<jaxws:endpoint id="HelloServiceJmsEpr" implementor="com.huateng.service.esb.abstraction.atomic.technical_helloservice._1_0.HelloServicePortTypeImpl" address="jms:/" /> |
jaxws:endpoint : 发布一个服务端点,制定服务实现类和地址。其他详细参数见jaxws.xsd定义。
implementor: 指定服务实现类。
address: 指定服务地址(当用SOAPover jms方式时,address值总为jms:/)。
<jms:destination name="{http://esb.service.huateng.com/abstraction/atomic/technical.HelloService/1_0}HelloService.jms-destination"> <jms:runtimePolicy useMessageIDAsCorrelationID="true" transactional="true"/> <jms:address destinationStyle="queue" jndiConnectionFactoryName="ESBQCF" jndiDestinationName="REQUESTQ"> <jms:JMSNamingProperty name="java.naming.factory.initial" value="com.sun.jndi.fscontext.RefFSContextFactory" /> <jms:JMSNamingProperty name="java.naming.provider.url" value="file:/D:/JndiCfg" /> </jms:address> </jms:destination> |
jms:destination : 服务的JMS配置信息配置节点。拥有一个属性name
name指定的服务类型规则为:{WSDLNamespace}.WSDLPortName.jms-destination
WSDLNamespace:指服务契约中的目标名称空间.
WSDLPortName:指wsdl:port中name的值.
jms:address JMS相关信息配置
ü destinationStyle:目标类型有两种类型队列和主题(queue/topic)。
ü jndiConnectionFactoryName:队列连接工厂的JNDI名称。
ü jndiDestinationName:目的队列的JNDI名称(指定服务端从哪个队列里面取SOAP消息)。
jms:JMSNamingProperty – JNDI属性配置
<jms:JMSNamingProperty name="java.naming.factory.initial"
value="com.sun.jndi.fscontext.RefFSContextFactory"/>
指定初始化连接工厂.
<jms:JMSNamingProperty name="java.naming.provider.url"
value="file:/D:/JndiCfg"/>
指定连接工厂提供的URL。
jms:runtimePolicy 运行时配置
useMessageIDAsCorrelationID" 服务方是否根据请求消息的MessageID作为相关标识(CorrelationID)
transactional服务方是否开启事务管理。
客户端
<?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:cxf="http://cxf.apache.org/core" xmlns:soap="http://cxf.apache.org/bindings/soap" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jms="http://cxf.apache.org/transports/jms" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://cxf.apache.org/bindings/soap http://cxf.apache.org/schema/bindings/soap.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://cxf.apache.org/transports/jms http://cxf.apache.org/schemas/configuration/jms.xsd">
<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-extension-local.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-http.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-jms.xml" />
<jms:conduit name="{http://esb.service.huateng.com/abstraction/atomic/technical.HelloService/1_0}HelloService.jms-conduit"> <jms:clientConfig clientReceiveTimeout="30000"/> <jms:address destinationStyle="queue" jndiConnectionFactoryName="ESBQCF" jndiDestinationName="REQUESTQ" jndiReplyDestinationName="REPLYQ"> <jms:JMSNamingProperty name="java.naming.factory.initial" value="com.sun.jndi.fscontext.RefFSContextFactory" /> <jms:JMSNamingProperty name="java.naming.provider.url" value="file:/D:/JndiCfg" /> </jms:address> </jms:conduit>
<jaxws:client id="helloGSPServiceClient" xmlns:s="http://esb.service.huateng.com/abstraction/atomic/technical.HelloService/1_0" serviceClass="com.huateng.service.esb.abstraction.atomic.technical_helloservice._1_0.HelloServicePortType" serviceName="s:HelloService" endpointName="s:HelloService" wsdlLocation="classpath:wsdl/HelloService.wsdl" address="jms:/" /> </beans>
|
配置说明
<jaxws:client id="helloGSPServiceClient" xmlns:s="http://esb.service.huateng.com/abstraction/atomic/technical.HelloService/1_0" serviceClass="com.huateng.service.esb.abstraction.atomic.technical_helloservice._1_0.HelloServicePortType" serviceName="s:HelloService" endpointName="s:HelloService" wsdlLocation="classpath:wsdl/HelloService.wsdl" address="jms:/" /> |
jaxws:client:定义一个客户端bean
ü id: bean名称
ü serviceClass:服务接口类
ü serviceName:服务名称。由[名称空间前缀:服务名]构成。服务名对应WSDL中的wsdl:service@name的名称
ü endpointName:端点名称。由[名称空间前缀:端口名]构成。端口名对应WSDL中的wsdl:port@name的名称
ü wsdlLocation:WSDL地址。可以是类路径地址。实际地址或远端地址。Classpath表示在类加载路劲下。
ü address:服务地址。对于JMS协议地址为jms:/
<jms:conduit name="{http://esb.service.huateng.com/abstraction/atomic/technical.HelloService/1_0}HelloService.jms-conduit"> <jms:clientConfig clientReceiveTimeout="30000"/> <jms:address destinationStyle="queue" jndiConnectionFactoryName="ESBQCF" jndiDestinationName="REQUESTQ" jndiReplyDestinationName="REPLYQ"> <jms:JMSNamingProperty name="java.naming.factory.initial" value="com.sun.jndi.fscontext.RefFSContextFactory" /> <jms:JMSNamingProperty name="java.naming.provider.url" value="file:/D:/JndiCfg" /> </jms:address> </jms:conduit>
|
jms:conduit: 客户端的JMS配置信息配置节点。拥有一个属性name
name指定的服务类型规则为:{WSDLNamespace}.WSDLPortName.jms-destination
WSDLNamespace:指服务契约中的目标名称空间.
WSDLPortName:指wsdl:port中name的值.
jms:address JMS相关信息配置
ü destinationStyle:目标类型有两种类型队列和主题(queue/topic)。
ü jndiConnectionFactoryName:队列连接工厂的JNDI名称。
ü jndiDestinationName:队列的JNDI名称(表示请求SOAP放入哪个队列)
ü jndiReplyDestinationName:返回队列的JNDI名称(表示从哪个队列取应答SOAP)
jms:JMSNamingProperty – JNDI属性配置
<jms:JMSNamingProperty name="java.naming.factory.initial"
value="com.sun.jndi.fscontext.RefFSContextFactory"/>
指定初始化连接工厂.
<jms:JMSNamingProperty name="java.naming.provider.url"
value="file:/C:/JndiCfg"/>
指定连接工厂提供的URL。
jms:clientConfig客户端配置
clientReceiveTimeout:设置客户端超时时间,单位:ms(毫秒)
部署服务
同HTTP方式。
测试服务
同HTTP方式。
JNDI配置
此部分请参见《JNDI的配置流程.doc》
CXF依赖的jar包说明
l lib(目录)
lib 目录中包含CXF及其运行时所需要的和可选的第三方支持类包(.jar 文件),可以根据不同项目所需的CXF特性选择所需要的支持类包。如果不想一一去区分的话,可以直接在Web 项目中包含所有的CXF及其运行时所需要的第三方支持类包(.jar 文件)即可。
其中cxf-2.2.4.jar是CXF框架的二进制包文件,包含了全部的模块
(modules),cxf-manifest.jar是列表清单文件manifestjar 。
以下的jar 包是所有CXF项目所必需的:(一般后面带有版本号,根据不同的版本实际对应 比如cxf-2.2.4.jar)
Ø cxf.jar
Ø commons-logging.jar
Ø geronimo-activation.jar (Or the Sun equivalent)
Ø geronimo-annotation.jar (Or the Sun equivalent)
Ø geronimo-javamail.jar (Or the Sun equivalent)
Ø neethi.jar
Ø jaxb-api.jar
Ø jaxb-impl.jar
Ø stax-api.jar
Ø XmlSchema.jar
Ø wstx-asl.jar
Ø xml-resolver.jar
对于 Java2WSDL 和WSDL2Java,除了必需的之外,还需要再增加如下jar包:
ü jaxb-xjc.jar
ü veliocity.jar
ü velocity-dep.jar
为了支持JAX-WS ,除了必需的之外,还需要再增加如下jar包:
ü jaxws-api.jar
ü saaj-api.jar
ü saaj-impl.jar
ü asm.jar (可选的,但是可以提升包装类型的性能)
为了支持XML 配置,除了必需的之外,还需要再增加如下jar包:
ü aopalliance.jar
ü spring-beans.jar
ü spring-context.jar
ü spring-core.jar
ü spring.web.jar
为了独立的HTTP 服务支持,除了必需的之外,还需要再增加如下jar包:
ü geronimo-servlet.jar
ü jetty.jar
ü jetty-sslengine.jar
ü jetty-util.jar
sl4j.jar& sl4j-jdk14.jar (可选的,但是可以提升日志logging)
为了支持Aegis ,除了必需的之外,还需要再增加如下jar包:
ü jaxen.jar
ü jdom.jar
ü stax-utils.jar
为了支持WS-Security,除了必需的之外,还需要再增加如下jar 包:
ü bcprov-jdk14.jar
ü wss4j.jar
ü xalan.jar
ü xmlsec.jar
为了支持HTTPBinding ,除了必需的之外,还需要再增加如下jar 包:
ü jra.jar
ü jettison.jar (仅为JSON 服务所需的)