目錄
1 定義Service 2 服務(wù)端發(fā)布Service 3 客戶端訪問Service 4 基于Spring的Jax-ws WebService 4.1 Service定義 4.2 服務(wù)端發(fā)布Service 4.3 客戶端獲取Service
Jax-ws是WebService的一種規(guī)范。 1 定義ServiceJax-ws的WebService定義是通過注解進(jìn)行的,我們必須在其WebService類的接口上使用@WebService注解進(jìn)行標(biāo)記。
@WebService public interface HelloWorld { public String sayHi(String who); }
如上,我們把HelloWorld定義為一個(gè)WebService,其對(duì)應(yīng)有一個(gè)sayHi操作。其對(duì)應(yīng)的實(shí)現(xiàn)類如下:
public class HelloWorldImpl implements HelloWorld { @Override public String sayHi(String who) { return "Hi, " + who; } } 2 服務(wù)端發(fā)布Service對(duì)于Jax-ws WebService而言,發(fā)布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的發(fā)布地址 jwsFactory.setServiceClass(HelloWorld.class);//WebService對(duì)應(yīng)的類型 jwsFactory.setServiceBean(hw);//WebService對(duì)應(yīng)的實(shí)現(xiàn)對(duì)象 jwsFactory.create(); } }
發(fā)布之后我們就可以通過發(fā)布地址?wsdl查看WebService的定義了(WSDL是WebService Document Location的簡(jiǎn)稱,即WebService文檔位置的意思)。通過在瀏覽器輸入http://localhost:8080/test/jaxws/services/HelloWorld?wsdl我們可以看到如下內(nèi)容:
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./2001/XMLSchema" xmlns:wsdl="http://schemas./wsdl/" xmlns:tns="http://jaxws.sample.cxftest./" xmlns:soap="http://schemas./wsdl/soap/" xmlns:ns1="http://schemas./soap/http" name="HelloWorldImplService" targetNamespace="http://jaxws.sample.cxftest./"> <wsdl:types> <xs:schema xmlns:xs="http://www./2001/XMLSchema" xmlns:tns="http://jaxws.sample.cxftest./" elementFormDefault="unqualified" targetNamespace="http://jaxws.sample.cxftest./" 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./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操作的參數(shù)who變成了arg0,這是因?yàn)榻涌谠诒痪幾g為class文件的時(shí)候不能保存參數(shù)名,有時(shí)候這會(huì)影響可讀性。如果需要參數(shù)名顯示的可讀性強(qiáng)一些的話,我們可以使用@WebParam來(lái)指定,如:
@WebService(serviceName="!@#$%^", name="123456") public interface HelloWorld { public String sayHi(@WebParam(name="who") String who); }
@WebService的serviceName可以用來(lái)指定service的名稱,默認(rèn)情況下如果Service是通過Endpoint.publish()方法發(fā)布的則serviceName為實(shí)現(xiàn)類的簡(jiǎn)單名稱+Service(如HelloWorldImplService),如果是通過JaxWsServerFactoryBean的create方法發(fā)布的則為接口的簡(jiǎn)單名稱+Service(如HelloWorldService)。name屬性可以用來(lái)指定service對(duì)應(yīng)的portName,默認(rèn)情況下如果Service是通過Endpoint.publish()方法發(fā)布的則portName為實(shí)現(xiàn)類的簡(jiǎn)單名稱+Port(如HelloWorldImplPort),如果是通過JaxWsServerFactoryBean的create方法發(fā)布的則為接口的簡(jiǎn)單名稱+Port(如HelloWorldPort)。 3 客戶端訪問Service類似于WebService簡(jiǎn)單實(shí)現(xiàn)里面的ClientProxyFactoryBean,在使用Jax-ws時(shí)我們可以通過JaxWsProxyFactoryBean來(lái)訪問服務(wù),如:
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:
//第一個(gè)參數(shù)為服務(wù)發(fā)布的targetNameSpace,可以通過查看對(duì)應(yīng)的wsdl文件獲得,默認(rèn)是發(fā)布Service所在包的包名倒過來(lái)的形式;第二個(gè)參數(shù)是serviceName private final static QName SERVICE_NAME = new QName("http://jaxws.sample.cxftest./", "HelloWorldService"); //第一個(gè)參數(shù)是服務(wù)發(fā)布的targetNameSpace,第二個(gè)參數(shù)是portName private final static QName PORT_NAME = new QName("http://jaxws.sample.cxftest./", "HelloWorldPort"); //服務(wù)發(fā)布的地址 private final static String ADDRESS = "http://localhost:8080/test/jaxws/services/HelloWorld"; public static void main(String args[]) { Service service = Service.create(SERVICE_NAME); //根據(jù)portName、服務(wù)發(fā)布地址、數(shù)據(jù)綁定類型創(chuàng)建一個(gè)Port。 service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING, ADDRESS);//默認(rèn)是SOAP1.1Binding //獲取服務(wù) HelloWorld hw = service.getPort(HelloWorld.class); String response = hw.sayHi("world"); System.out.println(response); }
在上面的代碼中我們只需要有一個(gè)Service實(shí)例,就能通過它來(lái)獲取真正的WebService,所以,我們?nèi)绻焉厦娴拇a改成如下形式也是可以的。
//第一個(gè)參數(shù)為服務(wù)發(fā)布的targetNameSpace,可以通過查看對(duì)應(yīng)的wsdl文件獲得,默認(rèn)是發(fā)布Service所在包的包名倒過來(lái)的形式;第二個(gè)參數(shù)是serviceName private final static QName SERVICE_NAME = new QName("http://jaxws.sample.cxftest./", "HelloWorldService"); //第一個(gè)參數(shù)是服務(wù)發(fā)布的targetNameSpace,第二個(gè)參數(shù)是portName private final static QName PORT_NAME = new QName("http://jaxws.sample.cxftest./", "HelloWorldPort"); //服務(wù)發(fā)布的地址 private final static String ADDRESS = "http://localhost:8080/test/jaxws/services/HelloWorld"; public static void main(String args[]) { Service service = Service.create(null); //根據(jù)portName、服務(wù)發(fā)布地址、數(shù)據(jù)綁定類型創(chuàng)建一個(gè)Port。 service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING, ADDRESS);//默認(rèn)是SOAP1.1Binding //獲取服務(wù) HelloWorld hw = service.getPort(HelloWorld.class); String response = hw.sayHi("world"); System.out.println(response); }
上面這種通過Service來(lái)獲取WebService的方法是不適用前面介紹的簡(jiǎn)單WebService實(shí)現(xiàn)的,即不適用獲取通過ServerFactoryBean發(fā)布的WebService。
4 基于Spring的Jax-ws WebService4.1 Service定義Service定義跟之前的定義是一樣的。 4.2 服務(wù)端發(fā)布Service首先在web.xml文件中定義一個(gè)CXFServlet,用于發(fā)布和攔截WebService請(qǐng)求。
<!-- Jax-ws實(shí)現(xiàn) --> <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>
接下來(lái)在我們的WebService配置文件里面定義我們的WebService發(fā)布,即CXFServlet指定的jaxws-cxf-servlet.xml文件(默認(rèn)是cxf-servlet.xml文件)。這里我們定義如下:
<beans xmlns="http://www./schema/beans" xmlns:xsi="http://www./2001/XMLSchema-instance" xmlns:jaxws="http://cxf./jaxws" xsi:schemaLocation=" http://www./schema/beans http://www./schema/beans/spring-beans.xsd http://cxf./jaxws http://cxf./schemas/jaxws.xsd"> <!-- 相當(dāng)于使用Endpoint.publish()進(jìn)行服務(wù)發(fā)布 --> <jaxws:endpoint address="/HelloWorld" implementorClass="com.tiantian.cxftest.sample.jaxws.HelloWorldImpl"/> <!-- 相當(dāng)于使用JaxWsServerFactoryBean進(jìn)行服務(wù)發(fā)布 --> <jaxws:server address="/HelloWorld2" serviceClass="com.tiantian.cxftest.sample.jaxws.HelloWorldImpl"/> <!-- JaxWsServerFactoryBean使用外部bean作為服務(wù)進(jìn)行發(fā)布 --> <jaxws:server address="/HelloWorld3" serviceBean="#hw"/> <!-- 普通bean對(duì)象 --> <bean id="hw" class="com.tiantian.cxftest.sample.jaxws.HelloWorldImpl"/> <!-- JaxWsServerFactoryBean使用內(nèi)部bean作為服務(wù)進(jìn)行發(fā)布 --> <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配置為一個(gè)個(gè)普通的Spring bean對(duì)象進(jìn)行使用。只是在定義之前需要往bean配置文件中引入Jax-ws的命名空間。這里我們?cè)?/span>classpath下定義一個(gè)jaxws-cxf-client.xml文件,其內(nèi)容如下所示:
<beans xmlns="http://www./schema/beans" xmlns:xsi="http://www./2001/XMLSchema-instance" xmlns:jaxws="http://cxf./jaxws" xsi:schemaLocation=" http://www./schema/beans http://www./schema/beans/spring-beans.xsd http://cxf./jaxws http://cxf./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當(dāng)做一個(gè)普通的bean對(duì)象來(lái)使用了,如:
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")); } }
|
|
來(lái)自: 藏經(jīng)閣_蒼穹 > 《常用框架》