1. 程式人生 > >httpInvoker提供遠端服務呼叫總結(一)

httpInvoker提供遠端服務呼叫總結(一)

1 使用httpInvoker提供遠端服務

使用HttpInvoker,不需要額外的類庫。和Hessian的輕量級傳輸協議不同的是,SpringHttpInvoker使用Java序列化來序列化引數和返回值,然後基於HTTP協議傳輸經序列化後的物件。當引數或返回值是複雜型別,並且不能通過Hessian的序列化機制序列化時,HttpInvoker就很有優勢。

2 輸出業務物件

通過HttpInvoker提供遠端服務與Hessian非常相似:Spring為Hessian提供HessianServiceExporter,Spring為HttpInvoker提供HttpInvokerServiceExporter。該類也可將普通baen例項輸出成遠端服務。配置方法與HessianServiceExporter也非常相似。

下面是使用HttpInvokerServiceExporter提供遠端服務的示例。在該示例裡,遠端服務bean的方法會返回一個Person物件,注意:Person物件必須實現Serializable或Externalizable介面,因為採用了Java序列化機制來傳輸引數和返回值。下面是遠端服務提供類:

public class HelloImpl implements Hello

{

        //遠端服務方法,該方法返回一個可序列化的物件

    publicPerson hello(String name)

    {

          Person p = new Person();

                  p.setName(name);

                  p.setAge(13);

                  return p;

    }

}

下面是Person的實現類,該類實現了Serializable介面:

public class Person implements Serializable

{

        //Person類的兩個屬性

        private String name;

        private int age;

        //name屬性的getter方法

        public String getName()

        {

                  return name;

        }

        //name屬性的setter方法

        public void setName(String name)

        {

                  this.name = name;

        }

        //age屬性的getter方法

        public int getAge()

        {

                  return age;

        }

        //age屬性的setter方法

        public void setAge(int age)

        {

                  this.age = age;

        }

}

然後修改web.xml配置檔案,該配置檔案裡,需要讓DispatcherServlet攔截匹配模式的請求,該請求由DispatcherServlet轉發給context中對應的bean處理。修改後的web.xml配置檔案如下:

<?xml version="1.0" encoding="ISO-8859-1"?>

<!-- Web應用配置檔案的檔案頭,包含dtd等資訊-->

<!DOCTYPE web-app

    PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"

"http://java.sun.com/dtd/web-app_2_3.dtd">

<!--  Web應用配置檔案的根元素-->

<web-app>

        <!--  配置DispatcherServlet-->

   <servlet>

         <servlet-name>remoting</servlet-name>

         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

                  <!--  配置該Servlet隨應用啟動時候啟動-->

         <load-on-startup>1</load-on-startup>

   </servlet>

        <!--  配置DispatcherServlet對映的url-->

   <servlet-mapping>

         <servlet-name>remoting</servlet-name>

         <url-pattern>/remoting/*</url-pattern>

   </servlet-mapping>

</web-app>

上面配置檔案中,沒有使用ContextLoaderListener來初始化ApplicationContext,也沒有指定ApplicationContext配置檔案的位置。這些都是通過DispatcherServlet預設載入的,DispatcherServlet在建立時,會載入ApplicationContext,預設查詢的配置檔案為:[servlet-name]-servlet.xml檔案。對該配置預設載入remoting-servlet.xml檔案。因此,在WEB-INF下提供remoting-servlet.xml檔案即可。remoting-servlet.xml檔案如下:

<?xml version="1.0" encoding="UTF-8"?>

<!-- Spring配置檔案的檔案頭,包含dtd等資訊-->

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

"http://www.springframework.org/dtd/spring-beans.dtd">

<!--  Spring配置檔案的根元素-->

<beans>

<!--  配置業務服務bean-->

    <beanid="helloService" class="lee.HelloImpl"/>

   <!--  將業務服務bean暴露成遠端服務-->

    <beanname="/helloService"

                  class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">

                  <!--  指定需要暴露的業務服務bean-->

          <property name="service"ref="helloService"/>

                  <!--  指定暴露的遠端服務實現的介面-->

          <propertyname="serviceInterface" value="lee.Hello"/>

   </bean>

</beans>

DispatcherServlet轉發請求的預設策略是:將請求轉發到context中與請求同名的bean。上面配置中遠端服務的url為:http://localhost:8888/httpInvoker/remoting/helloService,其中httpInvoker為該應用的虛擬路徑。

3 客戶端連線服務

Spring提供了HttpInvokerProxyFactoryBean工廠bean連線服務。類似於Hessian的HessianProxyFactoryBean,配置HttpInvokerProxyFactoryBean時,只需指定服務的url以及服務實現的介面。通過使用代理,Spring可將呼叫轉換成POST請求傳送到指定服務。詳細的配置如下:

<?xml version="1.0" encoding="UTF-8"?>

<!-- Spring配置檔案的檔案頭,包含dtd等資訊-->

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

   "http://www.springframework.org/dtd/spring-beans.dtd">

<!--  Spring配置檔案的根元素-->

<beans>

        <!-- 配置測試bean,該測試bean依賴於遠端服務bean-->

    <beanid="test" class="lee.Test">

                  <!--  配置依賴注入-->

          <propertyname="hello">

               <reflocal="helloService"/>

          </property>

   </bean>

        <!--  配置連線遠端服務的bean-->

    <beanid="helloService"class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">

                  <!--  遠端服務的url-->

                  <property name="serviceUrl"value="http://localhost:8888/httpInvoker/remoting/helloService"/>

                  <!--  遠端服務所實現的介面-->

          <propertyname="serviceInterface" value="lee.Hello"/>

   </bean>

</beans>

通過上面的配置,客戶端可以訪問httpInvoker提供的服務,預設情況下,HttpInvokerPropxy使用J2SE的HTTPClient功能。可通過設定httpInvokerRequestExecutor屬性使用CommonsHttpClient。通過對配置檔案簡單修改,將

    <beanid="helloService"class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">

                  <!--  遠端服務的url-->

                  <property name="serviceUrl"value="http://localhost:8888/httpInvoker/remoting/helloService"/>

                  <!--  遠端服務所實現的介面-->

          <propertyname="serviceInterface" value="lee.Hello"/>

   </bean>

修改成:

    <beanid="helloService"class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">

                  <!--  遠端服務的url-->

                  <property name="serviceUrl"value="http://localhost:8888/httpInvoker/remoting/helloService"/>

                  <!--  遠端服務所實現的介面-->

          <propertyname="serviceInterface" value="lee.Hello"/>

                  <!--  指定使用Commons HttpClient功能-->

                  <property name="httpInvokerRequestExecutor">

                           <bean

                                    class="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor"/>

                  </property>

   </bean>

測試程式碼:    
               HelloService  service=(HelloService)applicationContext.getBean("helloService"); 
                Person person=service. hello (“my name”); 
               System.out.println("hello='"   +  person.getName()  +  "'");  

客戶端可不配置,類似如下:

            HttpInvokerProxyFactoryBeanhttpInvoker = new HttpInvokerProxyFactoryBean();

               httpInvoker.setServiceInterface(com.synda.remote.ITerminal.class);

               httpInvoker.setServiceUrl("http://172.16.1.174:8080/remote/terminalHttpInvoker");

               ITerminal iterminal = (Iterminal)httpInvoker.getObject();