程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 通過Spring使用遠程訪問和web服務

通過Spring使用遠程訪問和web服務

編輯:關於JAVA

簡介

Spring提供類用於集成各種遠程訪問技術。這種對遠程訪問的支持可以降低你在用POJO實現支持遠程訪問業務時的開發難度。目前,Spring提供對下面四種遠程訪問技術的支持:

遠程方法調用(RMI)。通過使用RmiProxyFactoryBean和RmiServiceExporter,Spring支持傳統的RMI(使用java.rmi.Remote interfaces 和 java.rmi.RemoteException)和通過RMI調用器(可以使用任何Java接口)的透明遠程調用。

Spring的HTTP調用器。Spring提供一種特殊的遠程調用策略支持任何Java接口(象RMI調用器一樣),它允許Java序列化能夠通過HTTP傳送。對應的支持類是HttpInvokerProxyFactoryBean和HttpInvokerServiceExporter。

Hessian。通過使用HessianProxyFactoryBean和HessianServiceExporter,你可以使用Caucho提供的輕量級基於HTTP的二進制協議透明地提供你的業務。

Burlap。Burlap是基於XML的,它可以完全代替Hessian。Spring提供的支持類有BurlapProxyFactoryBean和BurlapServiceExporter。

JAX RPC (TODO).

當討論Spring對遠程訪問的支持時,我們將使用下面的域模型和對應的業務:// Account domain object
public class Account implements Serializable{
private String name;
public String getName();
public void setName(String name) {
this.name = name;
}
}
// Account service
public interface AccountService {
public void insertAccount(Account acc);
public List getAccounts(String name);
}
// ... and corresponding implement doing nothing at the moment
public class AccountServiceImpl implements AccountService {
public void insertAccount(Account acc) {
// do something
}
public List getAccounts(String name) {
// do something
}
}

我們先演示使用RMI向遠程客戶提供業務,並且會談到使用RMI的缺點。然後我們將繼續演示一個Hessian的例子。

使用RMI提供業務

使用Spring的RMI支持,你可以透明地通過RMI提供你的業務。在配置好Spring的RMI支持後,你會看到一個和遠程EJB類似的配置,除了沒有對安全上下文傳遞和遠程事務傳遞的標准支持。當使用RMI調用器時,Spring對這些額外的調用上下文提供捕獲,所以你可以插入你的安全框架或安全信任邏輯。

使用RmiServiceExporter提供業務

使用RmiServiceExporter,我們可以將AccountServer對象作為RMI對象輸出接口。這個接口可以使用RmiProxyFactoryBean訪問,或使用簡單RMI把該接口當作傳統RMI業務來訪問。RmiServiceExporter支持通過RMI調用器提供任何非RMI業務。

當然,我們首先得在Spring的BeanFactory中設置我們的業務:<bean id="accountService" class="example.AccountServiceImpl">
<!-- any additional properties, maybe a DAO? -->
</bean>

接下來,我們使用RmiServiceExporter提供我們的業務:

<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<!-- does not necessarily have to be the same name as the bean to be exported -->
<property name="serviceName"><value>AccountService</value></property>
<property name="service"><ref bean="accountService"/></property>
<property name="serviceInterface"><value>example.AccountService</value></property>
<!-- defaults to 1099 -->
<property name="registryPort"><value>1199</value></property>
</bean>

正如你看到的,我們更換了RMI注冊的端口。通常,你的應用服務器會維護RMI注冊,我們最好不要干擾它。業務名被用來綁定業務。所以現在,業務就綁定在rmi://HOST:1199/AccountService上。我們將在客戶端使用URL來連接業務。

注意:我們漏了一個屬性,就是servicePort屬性,它缺省值為0。這個意味著該業務使用匿名端口通訊。當然你也可以指定一個端口。

客戶端連接業務

我們的客戶端是一個使用AccountService管理賬戶的簡單對象:public class SimpleObject {
private AccountService accountService;
public void setAccountService(AccountService accountService) {
this.accountService = accountService;
}
}

為了在客戶端連接業務,我們建立另一個bean工廠,它包含這個簡單對象和業務連接的配置信息:<bean class="example.SimpleObject">
<property name="accountService"><ref bean="accountService"/></bean>
</bean>
<bean id="accountService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl"><value>rmi://HOST:1199/AccountService</value></property>
<property name="serviceInterface"><value>example.AccountService</value></property>
</bean>

這就是我們在客戶端訪問遠程賬戶業務所需要做的。Spring透明地創建一個調用器,通過RmiServiceExporter遠程提供賬戶業務。在客戶端,我們使用RmiProxyFactoryBean來使用該業務。

使用Hessian或Burlap通過HTTP遠程調用業務

Hessian提供了一個基於HTTP的二進制遠程協議。它由Caucho創建,更多有關Hessian的信息可以訪問http://www.caucho.com。

為Hessian建立DispatcherServlet

Hessian使用一個特定的servlet來通過HTTP通訊。使用Spring的DispatcherServlet概念,你可以很容易地創建這樣的servlet來提供你的業務。首先我們必須在你的應用中創建一個新的servlet(下面來自web.xml):

<servlet>
<servlet-name>remote</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

你可能熟悉Spring的DispatcherServlet概念,如果是的話,你得在WEB-INF目錄下建立一個應用上下文,remote-servlet.xml 。這個應用上下文會在下一節中使用。

使用HessianServiceExporter提供你的bean

在這個新的應用上下文remote-servlet.xml中,我們將創建一個HessianServiceExporter來輸出你的業務:

<bean id="accountService" class="example.AccountServiceImpl">
<!-- any additional properties, maybe a DAO? -->
</bean>
<bean name="/AccountService" class="org.springframework.remoting.caucho.HessianServiceExporter">
<property name="service"><ref bean="accountService"/></property>
<property name="serviceInterface">
<value>example.AccountService</value>
</property>
</bean>

客戶端連接業務

我們在客戶端使用HessianProxyFactoryBean來連接業務。和RMI例子中的原則一樣。我們將創建一個單獨的bean工廠或應用上下文,在SimpleObject使用AccountService來管理賬戶的地方將會提到下列bean:<bean class="example.SimpleObject">
<property name="accountService"><ref bean="accountService"/></property>
</bean>
<bean id="accountService" class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
<property name="serviceUrl"><value>http://remotehost:8080/AccountService</value></property>
<property name="ServiceInterface"><value>example.AccountService</value></property>
</bean>

就是這樣簡單。

使用Burlap

我們不在這裡討論Burlap,它只不過是Hessian的基於XML實現。因為它和上面的Hessian的例子以相同的方式配置。只要你把Hessian替換成Burlap就可以了。

在通過Hessian或Burlap輸出的業務中應用HTTP基本認證

Hessian和Burlap的優點之一就是我們能很容易地應用HTTP認證,因為兩者都是基於HTTP的協議。例如,普通的HTTP服務器安全機制可以很容易地通過使用web.xml安全功能來應用。通常,你不會為每個用戶都建立不同的安全信任,而是在Hessian/Burlap的ProxyFactoryBean中定義可共享的信任(和JDBC DataSource相類似)。<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="authorizationInterceptor"/>
</list>
</property>
</bean>
<bean id="authorizationInterceptor"
class="org.springframework.web.servlet.handler.UserRoleAuthorizationInterceptor">
<property name="authorizedRoles">
<list>
<value>administrator</value>
<value>operator</value>
</list>
</property>
</bean>

這個例子中,我們用到了BeanNameUrlHandlerMapping,並設置了一個攔截器,它只允許管理員和操作員調用這個應用上下文中的bean。

注意:當然,這個例子並沒有演示靈活的安全設施。如果考慮更靈活的安全設置,可以去看看Acegi Security System,http://acegisecurity.sourceforge.net。

使用HTTP調用器輸出業務

和Burlap和Hessian使用自身序列化機制的輕量級協議相反,Spring HTTP調用器使用標准Java序列化機制來通過HTTP輸出業務。如果你的參數或返回值是復雜類型,並且不能通過Hessian和Burlap的序列化機制序列化,HTTP調用器就很有優勢(參閱下一節,選擇遠程技術時的考慮)。

實際上,Spring可以使用J2SE提供的標准功能或Commons的HttpClient來實現HTTP調用。如果你需要更先進,更好用的功能,就使用後者。你可以參考jakarta.apache.org/commons/httpclient。

輸出業務對象

為業務對象設置HTTP調用器和你在Hessian或Burlap中使用的方式類似。就象Hessian提供HessianServiceExporter,Spring的HTTP調用器提供了org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter。為了輸出AccountService,使用下面的配置:

<bean name="/AccountService" class="org.sprfr.remoting.httpinvoker.HttpInvokerServiceExporter">
<property name="service"><ref bean="accountService"/></property>
<property name="serviceInterface">
<value>example.AccountService</value>
</property>
</bean>

在客戶端連接業務

同樣,從客戶端連接業務與你使用Hessian或Burlap時做的類似。使用代理,Spring可以將你的調用翻譯成HTTP 的POST請求到指向輸出業務的URL。

<bean id="httpInvokerProxy" class="org.sprfr.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
<property name="serviceUrl">
<value>http://remotehost:8080/AccountService</value>
</property>
<property name="serviceInterface">
<value>example.AccountService</value>
</property>
</bean>

就象上面說的一樣,你可以選擇使用你想使用的HTTP客戶端。缺省情況下,HttpInvokerPropxy使用J2SE的HTTP功能,但是你也可以通過設置httpInvokerRequestExecutor屬性選擇使用Commons HttpClient:

<property name="httpInvokerRequestExecutor">
<bean class="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor"/>
</property>

在選擇這些技術時的一些考慮

這裡提到的每種技術都有它的缺點。你在選擇這些技術時,應該仔細考慮你的需要,你所輸出的業務和你在遠程訪問時傳送的對象。

當使用RMI時,通過HTTP協議訪問對象是不可能的,除非你用HTTP包裹RMI流。RMI是一種很重的協議,因為他支持完全的對象序列化,這樣的序列化在要求復雜數據結構在遠程傳輸時是非常重要的。然而,RMI-JRMP只能綁定到Java客戶端:它是一種Java-to-Java的遠程訪問的方案。

如果你需要基於HTTP的遠程訪問而且還要求使用Java序列化,Spring的HTTP調用器是一個很好的選擇。它和RMI調用器使用相同的基礎設施,僅僅使用HTTP作為傳輸方式。注意HTTP調用器不僅只能用在Java-to-Java的遠程訪問,而且在客戶端和服務器端都必須使用Spring。(Spring為非RMI接口提供的RMI調用器也要求客戶端和服務器端都使用Spring)

當在異構環境中,Hessian和Burlap就非常有用了。因為它們可以使用在非Java的客戶端。然而,對非Java支持仍然是有限制的。已知的問題包括含有延遲初始化的collection對象的Hibernate對象的序列化。如果你有一個這樣的數據結構,考慮使用RMI或HTTP調用器,而不是Hessian。

最後但也很重要的一點,EJB優於RMI,因為它支持標准的基於角色的認證和授權,以及遠程事務傳遞。用RMI調用器或HTTP調用器來支持安全上下文的傳遞是可能的,雖然這不是由核心Spring提供:而是由第三方或在定制的解決方案中插入攔截器來解決的。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved