Spring對遠程調用提供了良好支持,它支持的主要遠程調用協議有:RMI、基於HTTP的遠程調用(使用org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter實現)、Hessian、Burlap、SOAP及Spring-WS(Web Services)等。因爲本章主要講述Web服務的實現方法,那麼我們就來看看Spring對SOAP及Spring-WS的支持。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
Spring-WS之基礎
Spring-WS可以從Spring網站單獨下載,它不包含在Spring核心包中。Spring-WS支持契約最先式的Web服務開發方法。因此,要在Spring中開發Web服務,開發者首先要準備好Web服務契約,即WSDL文件,這對每位開發者來說,並不是一件非常容易的事,尤其對那些不能手動創建WSDL的開發者來說更是如此。在這種情況下,另一種可選方法是使用工具先創建WSDL,然後使用Spring-WS來實現Web服務。
我們在前面已經學習過,如何使用Axis開發Web服務。現在,我們需要利用Spring的以下特性來實現Web服務:
1) 依賴注入
2) 對象交織(Object Wiring,即把對象連接在一起以便它們相互之間能夠通信)
前面我們提到,我們還需要一個生成WSDL的工具,爲了使Spring開發Web服務的過程更加簡單直接,我們可以使用一種混合的方法,即使用Axis+Spring來實現Web服務,這樣,我們可充分利用它們的長處。下面,我們看一下其具體實現過程。
使用Spring實現Web服務
因爲我們前面已經學習瞭如何部署基於Axis的Web服務,因此,我們可以以前面例子的爲基礎,將它集成到Spring中。Spring提供了一個名爲org.springframework.remoting.jaxrpc.ServletEndpointSupport的Servlet,它是JAX-RPC Servlet的基類,我們可以使用它非常方便地實現Web服務,這個類還包含了當前Spring應用上下文的引用,因此我們能夠對Spring中的Java Bean進行查找或加載資源等操作。
服務器端和客戶端代碼
我們將使用前面Axis例子的代碼略加改動,來實現服務器端。因此,本節代碼和上節有所重複,您可以在本書源代碼的ch03/03_Spring/WebService/src目錄中找到服務器端代碼。
IHello.java
IHello是一個非常簡單的業務接口,它只有一個hello方法。因爲我們想把該接口和客戶端共享,所以我們把它放到一個共用的單獨目錄(ch03/03_Spring/Common/src)中。
- public interface IHello {
- String hello(String param);
- }
IHelloWeb.java
IHelloWeb接口和IHello接口不同,它是我們的Web服務接口,我們只從該接口生成WSDL契約。
public interface IHelloWeb extends IHello{
}
HelloWebService.java
與前面的Axis例子不同,這裏的HelloWebService繼承自ServletEndpointSupport,因此,我們可以在這個類中得到當前Spring應用上下文的引用。
- public class HelloWebService extends ServletEndpointSupport implements
- IHelloWeb {
- private IHello iHello;
- public HelloWebService() {
- System.out.println("Inside HelloWebService.HelloWebService...");
- }
- protected void onInit() {
- System.out.println("Inside HelloWebService.onInit...");
- this.iHello = (IHello) getWebApplicationContext().getBean("hello");
- }
- public void setHello(IHello iHello) {
- this.iHello = iHello;
- }
- public String hello(String param) {
- System.out.println("Inside HelloWebService.hello...");
- return iHello.hello(param);
- }
- }
在上面的onInit方法中,我們得到Spring上下文,根據bean的名字”hello”得到Spring中Java Bean,這個bean是另一個業務bean的引用,該業務bean的實現代碼解釋如下。
Hello.java
Hello是一個Spring bean,其配置見applicationContext.xml文件,該bean實現了業務方法。
- public class Hello implements IHello {
- public Hello() {
- System.out.println("Inside Hello.Hello...");
- }
- public String hello(String param) {
- System.out.println("Inside Hello.hello...");
- return "Hello " + param;
- }
- }
applicationContext.xml
applicationContext.xml文件位於ch03/03_Spring/WebService/config文件夾中,這個文件定義了所有的Spring bean。
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
- <beans>
- <bean id="hello" class="com.binildas.apache.axis.AxisSpring.Hello">
- </bean>
- </beans>
web.xml
web.xml位於ch03/03_Spring/WebService/config目錄,它演示瞭如何在當前Web應用上下文中嵌入Spring上下文。但我們對Web檔案進行打包時,我們需要將applicationContext.xml 放到web.xml中定義的路徑中(即/WEB-INF/)。
- <?xml version="1.0" encoding="ISO-8859-1"?>
- <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web
- Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
- <web-app>
- <listener>
- <listener-class>
- org.springframework.web.context.ContextLoaderListener
- </listener-class>
- </listener>
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>
- /WEB-INF/applicationContext.xml
- </param-value>
- </context-param>
- <servlet>
- <servlet-name>AxisServlet</servlet-name>
- <display-name>Apache-Axis Servlet</display-name>
- <servlet-class>
- org.apache.axis.transport.http.AxisServlet
- </servlet-class>
- <load-on-startup>1</load-on-startup>
- </servlet>
- <servlet-mapping>
- <servlet-name>AxisServlet</servlet-name>
- <url-pattern>/services/*</url-pattern>
- </servlet-mapping>
- </web-app>
Client.java
在客戶端代碼中,我們也簡單地應用了Spring,請閱讀下面的代碼,看看它是如何實現的。
- public class Client {
- private ApplicationContext ctx;
- private ClientObject clientObject;
- public Client() {
- String[] paths = { "/applicationContextClient.xml" };
- ctx = new ClassPathXmlApplicationContext(paths);
- clientObject = (ClientObject) ctx.getBean("clientObject");
- }
- public void finalize() throws Throwable {
- super.finalize();
- clientObject = null;
- ctx = null;
- }
- private void test1() {
- log(clientObject.hello("Binil"));
- }
- public static void main(String[] args) throws Exception {
- Client client = new Client();
- client.test1();
- }
- }
上面的 Client類中使用了另一個Spring bean,即ClientObject,這個bean配置詳見applicationContextClient.xml。
ClientObject.java
ClientObject只是一個輔助bean,其源碼如下:
- public class ClientObject {
- private IHello helloService;
- public void setHelloService(IHello helloService) {
- this.helloService = helloService;
- }
- public String hello(String param) {
- return helloService.hello(param);
- }
- }
在上面的代碼中,我們將遠程服務的代理注入到該bean中,因此,所有的調用將被委派到Web服務,服務代理的配置參見applicationContextClient.xml 。
在applicationContextClient.xml文件中,我們不但配置一個ClientObject的Spring bean,而且還配置了一個遠程Web服務的代理bean。爲了配置服務代理,您需要定義JaxRpcPortProxyFactoryBean,從而該代理將實現遠程接口。因爲我們使用Axis實現了基於Spring的Web服務,我們可只使用Axis本身作爲客戶端,調用Web服務。因此,您必須指定org.apache.axis.client.ServiceFactory 作爲服務工廠類。然後,您還需要爲JaxRpcPortProxyFactoryBean定義一些其它的參數,它們顯示如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
- "http://www.springframework.org/dtd/spring-beans.dtd">
- <beans>
- <bean id="helloService"
- class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean">
- <property name="serviceFactoryClass">
- <value>org.apache.axis.client.ServiceFactory</value>
- </property>
- <property name="serviceInterface" value="com.binildas.apache.axis.AxisSpring.IHello" />
- <property name="wsdlDocumentUrl"
- value="http://localhost:8080/AxisSpring/
- services/HelloWebService?wsdl" />
- <property name="namespaceUri" value="http://AxisSpring.axis.apache.binildas.com" />
- <property name="serviceName" value="IHelloWebService" />
- <property name="portName" value="HelloWebService" />
- </bean>
- <bean id="clientObject" class="com.binildas.apache.axis.AxisSpring.ClientObject">
- <property name="helloService" ref="helloService" />
- </bean>
- </beans>
運行服務器端和客戶端
要編譯服務器端代碼,請執行下面命令:
cd ch03/03_Spring
ant
上面的命令將編譯服務器端和客戶端代碼,編譯完成後,我們可在下面的目錄中找到一個可部署的Web歸檔文件(AxisSpring.war):
ch03/03_Spring/WebService/dist
現在,您就可以把這個war文件拷貝到您的Web服務器的Webapps目錄,然後,重啓服務器。如果部署沒有問題,您就可以訪問http://localhost:8080/AxisSpring/services/HelloWebService?wsdl獲取該Web服務的WSDL。
接下來您就可以執行客戶端代碼測試您的Web服務,要執行客戶端代碼,請使用下列命令:
cd ch03/03_Spring
ant run
下圖顯示了客戶端的執行界面: