Spring HTTP Invoker一種JAVA遠端方法調用架構實作,原理與JDK的RMI基本一緻,是以我們先跟其它JAVA遠端方法調用實作做下簡單比較。
- RMI:使用JRMP協定(基于TCP/IP),不允許穿透防火牆,使用JAVA系列化方式,使用于任何JAVA應用之間互相調用。
- Hessian:使用HTTP協定,允許穿透防火牆,使用自己的系列化方式,支援JAVA、C++、.Net等跨語言使用。
- Burlap: 與Hessian相同,隻是Hessian使用二進制傳輸,而Burlap使用XML格式傳輸(兩個産品均屬于caucho公司的開源産品)。
- Spring HTTP Invoker: 使用HTTP協定,允許穿透防火牆,使用JAVA系列化方式,但僅限于Spring應用之間使用,即調用者與被調用者都必須是使用Spring架構的應用。
為什麼使用Spring HTTP Invoker?我們可以看下Spring源碼中的注釋說明:
1 2 3 4 5 |
Spring一定希望大家盡量使用它的産品,但實際項目中我們還是要根據需求來決定選擇哪個架構,下面我們來看看Spring HTTP Invoker的使用。
代碼結構圖如下:
用戶端通過Spring的HttpInvoker,完成對遠端函數的調用。涉及的類有:
用戶端調用User類的服務UserService,完成對實作類UserServiceImpl的addUser(User u)方法調用。其中User類為普通Pojo對象,UserService為接口,UserServiceImpl為UserService的具體實作。代碼如下:
public interface UserService {
void addUser(User u);
}
public class UserServiceImpl implements UserService {
public void addUser(User u) {
System.out.println(“add user ["+u.getUsername()+ "] ok !!!”);
}
}
用戶端調用時,主方法代碼為:
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
new String[] {“ApplicationContext.xml” });
UserService us = (UserService)ctx.getBean(“ServletProxy”);
us.addUser(new User(“Hook1″));
UserService us2 = (UserService)ctx.getBean(“UrlPathProxy”);
us2.addUser(new User(“Hook2″));
}
其調用流程用時序圖可表示為:
圖中粉紅色表示基于Url映射方式的配置時程式的處理流程,紅色表示基于Servlet配置時的處理流程。
當以示基于Url映射方式的配置時,遠端系統處理請求的方式同SpringMVC的controller類似,所有的請求通過在web.xml中的org.springframework.web.servlet.DispatcherServlet統一處理,根據url映射,去對應的【servlet名稱-servlet.xml】檔案中,查詢跟請求的url比對的bean配置;而基于Servlet配置時,由org.springframework.web.context.support.HttpRequestHandlerServlet去攔截url-pattern比對的請求,如果比對成功,去ApplicationContext中查找name與servlet-name一緻的bean,完成遠端方法調用。
當使用URL映射配置時,實力配置如下(application-servlet.xml):
<bean name=”/userHttpInvokerService” class=”org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter”>
<property name=”service” ref=”userService”/>
<property name=”serviceInterface” value=”com.handou.httpinvoker.service.UserService”/>
</bean>
web.xml檔案配置:
<servlet>
<servlet-name>application</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>application</servlet-name>
<url-pattern>