目录
1 定义Service
2 服务端发布Service
3 客户端访问Service
4 基于Spring的Jax-ws WebService
4.1 Service定义
4.2 服务端发布Service
4.3 客户端获取Service
Jax-ws是WebService的一种规范。
1 定义Service
Jax-ws的WebService定义是通过注解进行的,我们必须在其WebService类的接口上使用@WebService注解进行标记。
- @WebService
- public interface HelloWorld {
- public String sayHi(String who);
- }
如上,我们把HelloWorld定义为一个WebService,其对应有一个sayHi操作。其对应的实现类如下:
- public class HelloWorldImpl implements HelloWorld {
- @Override
- public String sayHi(String who) {
- return "Hi, " + who;
- }
- }
2 服务端发布Service
对于Jax-ws WebService而言,发布Service有两种方式。
第一种:
- public class Server {
- private final static String ADDRESS = "http://localhost:8080/test/jaxws/services/HelloWorld";
- public static void main(String args[]) {
- HelloWorld hw = new HelloWorldImpl();
- Endpoint.publish(ADDRESS, hw);
- }
- }
第二种:
- public class Server {
- private final static String ADDRESS = "http://localhost:8080/test/jaxws/services/HelloWorld";
- public static void main(String args[]) {
- HelloWorld hw = new HelloWorldImpl();
- JaxWsServerFactoryBean jwsFactory = new JaxWsServerFactoryBean();
- jwsFactory.setAddress(ADDRESS); //指定WebService的发布地址
- jwsFactory.setServiceClass(HelloWorld.class);//WebService对应的类型
- jwsFactory.setServiceBean(hw);//WebService对应的实现对象
- jwsFactory.create();
- }
- }
发布之后我们就可以通过发布地址?wsdl查看WebService的定义了(WSDL是WebService Document Location的简称,即WebService文档位置的意思)。通过在浏览器输入http://localhost:8080/test/jaxws/services/HelloWorld?wsdl我们可以看到如下内容:
- This XML file does not appear to have any style information associated
- with it. The document tree is shown below.
- <wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://jaxws.sample.cxftest.tiantian.com/"
- xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http"
- name="HelloWorldImplService" targetNamespace="http://jaxws.sample.cxftest.tiantian.com/">
- <wsdl:types>
- <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
- xmlns:tns="http://jaxws.sample.cxftest.tiantian.com/"
- elementFormDefault="unqualified" targetNamespace="http://jaxws.sample.cxftest.tiantian.com/"
- version="1.0">
- <xs:element name="sayHi" type="tns:sayHi" />
- <xs:element name="sayHiResponse" type="tns:sayHiResponse" />
- <xs:complexType name="sayHi">
- <xs:sequence>
- <xs:element minOccurs="0" name="arg0" type="xs:string" />
- </xs:sequence>
- </xs:complexType>
- <xs:complexType name="sayHiResponse">
- <xs:sequence>
- <xs:element minOccurs="0" name="return" type="xs:string" />
- </xs:sequence>
- </xs:complexType>
- </xs:schema>
- </wsdl:types>
- <wsdl:message name="sayHiResponse">
- <wsdl:part element="tns:sayHiResponse" name="parameters"></wsdl:part>
- </wsdl:message>
- <wsdl:message name="sayHi">
- <wsdl:part element="tns:sayHi" name="parameters"></wsdl:part>
- </wsdl:message>
- <wsdl:portType name="HelloWorld">
- <wsdl:operation name="sayHi">
- <wsdl:input message="tns:sayHi" name="sayHi"></wsdl:input>
- <wsdl:output message="tns:sayHiResponse" name="sayHiResponse"></wsdl:output>
- </wsdl:operation>
- </wsdl:portType>
- <wsdl:binding name="HelloWorldImplServiceSoapBinding"
- type="tns:HelloWorld">
- <soap:binding style="document"
- transport="http://schemas.xmlsoap.org/soap/http" />
- <wsdl:operation name="sayHi">
- <soap:operation soapAction="" style="document" />
- <wsdl:input name="sayHi">
- <soap:body use="literal" />
- </wsdl:input>
- <wsdl:output name="sayHiResponse">
- <soap:body use="literal" />
- </wsdl:output>
- </wsdl:operation>
- </wsdl:binding>
- <wsdl:service name="HelloWorldImplService">
- <wsdl:port binding="tns:HelloWorldImplServiceSoapBinding"
- name="HelloWorldImplPort">
- <soap:address location="http://localhost:8080/test/jaxws/services/HelloWorld" />
- </wsdl:port>
- </wsdl:service>
- </wsdl:definitions>
我们可以看到在上面我们的sayHi操作的参数who变成了arg0,这是因为接口在被编译为class文件的时候不能保存参数名,有时候这会影响可读性。如果需要参数名显示的可读性强一些的话,我们可以使用@WebParam来指定,如:
- @WebService(serviceName="!@#$%^", name="123456")
- public interface HelloWorld {
- public String sayHi(@WebParam(name="who") String who);
- }
@WebService的serviceName可以用来指定service的名称,默认情况下如果Service是通过Endpoint.publish()方法发布的则serviceName为实现类的简单名称+Service(如HelloWorldImplService),如果是通过JaxWsServerFactoryBean的create方法发布的则为接口的简单名称+Service(如HelloWorldService)。name属性可以用来指定service对应的portName,默认情况下如果Service是通过Endpoint.publish()方法发布的则portName为实现类的简单名称+Port(如HelloWorldImplPort),如果是通过JaxWsServerFactoryBean的create方法发布的则为接口的简单名称+Port(如HelloWorldPort)。
3 客户端访问Service
类似于WebService简单实现里面的ClientProxyFactoryBean,在使用Jax-ws时我们可以通过JaxWsProxyFactoryBean来访问服务,如:
- public class Client {
- private final static String ADDRESS = "http://localhost:8080/test/jaxws/services/HelloWorld";
- public static void main(String args[]) {
- JaxWsProxyFactoryBean jwpFactory = new JaxWsProxyFactoryBean();
- jwpFactory.setAddress(ADDRESS);
- jwpFactory.setServiceClass(HelloWorld.class);
- HelloWorld hw = (HelloWorld)jwpFactory.create();
- String response = hw.sayHi("world");
- System.out.println(response);
- }
- }
除了上面的方式之外,我们还可以这样获取Service:
- //第一个参数为服务发布的targetNameSpace,可以通过查看对应的wsdl文件获得,默认是发布Service所在包的包名倒过来的形式;第二个参数是serviceName
- private final static QName SERVICE_NAME = new QName("http://jaxws.sample.cxftest.tiantian.com/", "HelloWorldService");
- //第一个参数是服务发布的targetNameSpace,第二个参数是portName
- private final static QName PORT_NAME = new QName("http://jaxws.sample.cxftest.tiantian.com/", "HelloWorldPort");
- //服务发布的地址
- private final static String ADDRESS = "http://localhost:8080/test/jaxws/services/HelloWorld";
- public static void main(String args[]) {
- Service service = Service.create(SERVICE_NAME);
- //根据portName、服务发布地址、数据绑定类型创建一个Port。
- service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING, ADDRESS);//默认是SOAP1.1Binding
- //获取服务
- HelloWorld hw = service.getPort(HelloWorld.class);
- String response = hw.sayHi("world");
- System.out.println(response);
- }
在上面的代码中我们只需要有一个Service实例,就能通过它来获取真正的WebService,所以,我们如果把上面的代码改成如下形式也是可以的。
- //第一个参数为服务发布的targetNameSpace,可以通过查看对应的wsdl文件获得,默认是发布Service所在包的包名倒过来的形式;第二个参数是serviceName
- private final static QName SERVICE_NAME = new QName("http://jaxws.sample.cxftest.tiantian.com/", "HelloWorldService");
- //第一个参数是服务发布的targetNameSpace,第二个参数是portName
- private final static QName PORT_NAME = new QName("http://jaxws.sample.cxftest.tiantian.com/", "HelloWorldPort");
- //服务发布的地址
- private final static String ADDRESS = "http://localhost:8080/test/jaxws/services/HelloWorld";
- public static void main(String args[]) {
- Service service = Service.create(null);
- //根据portName、服务发布地址、数据绑定类型创建一个Port。
- service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING, ADDRESS);//默认是SOAP1.1Binding
- //获取服务
- HelloWorld hw = service.getPort(HelloWorld.class);
- String response = hw.sayHi("world");
- System.out.println(response);
- }
上面这种通过Service来获取WebService的方法是不适用前面介绍的简单WebService实现的,即不适用获取通过ServerFactoryBean发布的WebService。
4 基于Spring的Jax-ws WebService
4.1 Service定义
Service定义跟之前的定义是一样的。
4.2 服务端发布Service
首先在web.xml文件中定义一个CXFServlet,用于发布和拦截WebService请求。
- <!-- Jax-ws实现 -->
- <servlet>
- <display-name>jaxws-cxf</display-name>
- <servlet-name>jaxws-cxf</servlet-name>
- <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
- <load-on-startup>1</load-on-startup>
- <init-param>
- <param-name>config-location</param-name>
- <param-value>WEB-INF/jaxws-cxf-servlet.xml</param-value>
- </init-param>
- </servlet>
- <servlet-mapping>
- <servlet-name>jaxws-cxf</servlet-name>
- <url-pattern>/jaxws/services/*</url-pattern>
- </servlet-mapping>
接下来在我们的WebService配置文件里面定义我们的WebService发布,即CXFServlet指定的jaxws-cxf-servlet.xml文件(默认是cxf-servlet.xml文件)。这里我们定义如下:
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
- <!-- 相当于使用Endpoint.publish()进行服务发布 -->
- <jaxws:endpoint address="/HelloWorld" implementorClass="com.tiantian.cxftest.sample.jaxws.HelloWorldImpl"/>
- <!-- 相当于使用JaxWsServerFactoryBean进行服务发布 -->
- <jaxws:server address="/HelloWorld2" serviceClass="com.tiantian.cxftest.sample.jaxws.HelloWorldImpl"/>
- <!-- JaxWsServerFactoryBean使用外部bean作为服务进行发布 -->
- <jaxws:server address="/HelloWorld3" serviceBean="#hw"/>
- <!-- 普通bean对象 -->
- <bean id="hw" class="com.tiantian.cxftest.sample.jaxws.HelloWorldImpl"/>
- <!-- JaxWsServerFactoryBean使用内部bean作为服务进行发布 -->
- <jaxws:server address="/HelloWorld4">
- <jaxws:serviceBean>
- <bean class="com.tiantian.cxftest.sample.jaxws.HelloWorldImpl"/>
- </jaxws:serviceBean>
- </jaxws:server>
- </beans>
4.3 客户端获取Service
客户端可以直接从Spring的bean配置文件中把WebService配置为一个个普通的Spring bean对象进行使用。只是在定义之前需要往bean配置文件中引入Jax-ws的命名空间。这里我们在classpath下定义一个jaxws-cxf-client.xml文件,其内容如下所示:
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
- <jaxws:client id="hw"
- address="http://localhost:8080/test/jaxws/services/HelloWorld"
- serviceClass="com.tiantian.cxftest.sample.jaxws.HelloWorld" />
- <jaxws:client id="hw2"
- address="http://localhost:8080/test/jaxws/services/HelloWorld2"
- serviceClass="com.tiantian.cxftest.sample.jaxws.HelloWorld"/>
- <jaxws:client id="hw3"
- address="http://localhost:8080/test/jaxws/services/HelloWorld3"
- serviceClass="com.tiantian.cxftest.sample.jaxws.HelloWorld"/>
- <jaxws:client id="hw4"
- address="http://localhost:8080/test/jaxws/services/HelloWorld4"
- serviceClass="com.tiantian.cxftest.sample.jaxws.HelloWorld"/>
- </beans>
之后我们就可以把这些定义好的WebService当做一个普通的bean对象来使用了,如:
- public class SpringClient {
- public static void main(String args[]) {
- ApplicationContext context = new ClassPathXmlApplicationContext("jaxws-cxf-client.xml");
- accessService(context, "hw");
- accessService(context, "hw2");
- accessService(context, "hw3");
- accessService(context, "hw4");
- }
- private static void accessService(ApplicationContext context, String beanName) {
- HelloWorld hw = context.getBean(beanName, HelloWorld.class);
- System.out.println(hw.sayHi("world"));
- }
- }
浙公网安备 33010602011771号