天天看點

Spring學習 HTTP Invoker

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學習 HTTP Invoker

用戶端通過Spring的HttpInvoker,完成對遠端函數的調用。涉及的類有:

Spring學習 HTTP Invoker

用戶端調用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″));

    }

其調用流程用時序圖可表示為:

Spring學習 HTTP Invoker

圖中粉紅色表示基于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>