天天看點

Hessian實作Webservice簡單執行個體

Hessian實作Webservice簡單執行個體

Hessian是一個輕量級的remoting on http工具,采用的是Binary RPC協定,是以它很适合于發送二進制資料,同時又具有防火牆穿透能力。Hessian一般是通過Web應用來提供服務,是以非常類似于平時我們用的WebService。隻是它不使用SOAP協定,但相比webservice而言更簡單、快捷。

Hessian官網:http://hessian.caucho.com/

Hessian可通過Servlet提供遠端服務,需要将比對某個模式的請求映射到Hessian服務。也可Spring架構整合,通過它的DispatcherServlet可以完成該功能,DispatcherServlet可将比對模式的請求轉發到Hessian服務。Hessian的server端提供一個servlet基類, 用來處理發送的請求,而Hessian的這個遠端過程調用,完全使用動态代理來實作的,,建議采用面向接口程式設計,Hessian服務通過接口暴露。

Hessian處理過程示意圖:

用戶端——>序列化寫到輸出流——>遠端方法(伺服器端)——>序列化寫到輸出流 ——>用戶端讀取輸入流——>輸出結果

下面詳細介紹最常用的兩種方式實作Hessian提供webservice:

純Hessian實作

配合Spring架構實作

在開始之前當然需要到官網上下載下傳相關的lib包,放入項目的/WEB-INF/lib/下

【一】、純Hessian實作步驟:

1.基本代碼

首先編寫一個服務的接口類:HelloHessian.java

Java代碼

  1. package michael.hessian;     
  2. import java.util.List;     
  3. import java.util.Map;     
  4. public interface HelloHessian {     
  5.     String sayHello();     
  6.     MyCar getMyCar();     
  7.     List myLoveFruit();     
  8.     Map<string, string> myBabays();     
  9. }   

一個java bean檔案MyCar.java:

Java代碼

  1. package michael.hessian;     
  2. import java.io.Serializable;     
  3. public class MyCar implements Serializable {     
  4.     private static final long serialVersionUID = 4736905401908455439L;     
  5.     private String carName;     
  6.     private String carModel;     
  7.     public String getCarName() {     
  8.         return carName;     
  9.     }     
  10.     public String getCarModel() {     
  11.         return carModel;     
  12.     }     
  13.     public void setCarName(String pCarName) {     
  14.         carName = pCarName;     
  15.     }     
  16.     public void setCarModel(String pCarModel) {     
  17.         carModel = pCarModel;     
  18.     }     
  19.     @Override    
  20.     public String toString() {     
  21.         return "my car name:[" + this.carName + "] model:[" + this.carModel     
  22.                 + "].";     
  23.     }     
  24. }   

服務端接口的實作類:HelloHessianImpl.java

Java代碼

  1. package michael.hessian.impl;     
  2. import java.util.ArrayList;     
  3. import java.util.HashMap;     
  4. import java.util.List;     
  5. import java.util.Map;     
  6. import michael.hessian.HelloHessian;     
  7. import michael.hessian.MyCar;     
  8. public class HelloHessianImpl extends HessianServlet implements HelloHessian {     
  9.     public MyCar getMyCar() {     
  10.         MyCar car = new MyCar();     
  11.         car.setCarName("阿斯頓·馬丁");     
  12.         car.setCarModel("One-77");     
  13.         return car;     
  14.     }     
  15.     public Map<string, string> myBabays() {     
  16.         Map<string, string> map = new HashMap<string, string>();     
  17.         map.put("son", "孫吳空");     
  18.         map.put("daughter", "孫小美");     
  19.         return map;     
  20.     }     
  21.     public List myLoveFruit() {     
  22.         List list = new ArrayList();     
  23.         list.add("apple");     
  24.         list.add("kiwi");     
  25.         list.add("orange");     
  26.         return list;     
  27.     }     
  28.     public String sayHello() {     
  29.         return "welcom to Hessian";     
  30.     }     
  31. }   

2.配置檔案web.xml修改

在web.xml配置檔案裡增加如下資訊:

Xml代碼

  1. <servlet>    
  2.         <servlet-name>HelloHessianservlet-name>    
  3.         <servlet-class>    
  4.             com.caucho.hessian.server.HessianServlet     
  5.         servlet-class>    
  6.         <init-param>    
  7.             <param-name>home-classparam-name>    
  8.             <param-value>michael.hessian.impl.HelloHessianImplparam-value>    
  9.         init-param>    
  10.         <init-param>    
  11.             <param-name>home-apiparam-name>    
  12.             <param-value>michael.hessian.HelloHessianparam-value>    
  13.         init-param>    
  14.         <load-on-startup>1load-on-startup>    
  15.     servlet>    
  16.     <servlet-mapping>    
  17.         <servlet-name>HelloHessianservlet-name>    
  18.         <url-pattern>/HessianServiceurl-pattern>    
  19.     servlet-mapping>    
  20.     <servlet-mapping>    

3.java用戶端驗證

Java代碼

  1. package michael.hessian.client;     
  2. import java.net.MalformedURLException;     
  3. import java.util.Map;     
  4. import michael.hessian.HelloHessian;     
  5. import michael.hessian.MyCar;     
  6. import com.caucho.hessian.client.HessianProxyFactory;     
  7. public class HessianClientTest {     
  8.     public static void main(String[] args) {     
  9.         String url = "http://localhost:8082/J2EE_sjsky/HessianService";     
  10.         HessianProxyFactory factory = new HessianProxyFactory();     
  11.         try {     
  12.             HelloHessian hello = (HelloHessian) factory.create(     
  13.                     HelloHessian.class, url);     
  14.             System.out.println(hello.sayHello());     
  15.             MyCar car = hello.getMyCar();     
  16.             System.out.println(car.toString());     
  17.             for (Map.Entry<string, string> entry : hello.myBabays().entrySet()) {     
  18.                 System.out.println(entry.getKey() + "   " + entry.getValue());     
  19.             }     
  20.             for (String str : hello.myLoveFruit()) {     
  21.                 System.out.println(str);     
  22.             }     
  23.         } catch (MalformedURLException e) {     
  24.             e.printStackTrace();     
  25.         }     
  26.     }     
  27. }    

運作結果如下:

Java代碼

  1. welcom to Hessian     
  2. my car name:[阿斯頓·馬丁] model:[One-77].     
  3. daughter   孫小美     
  4. son   孫吳空     
  5. apple     
  6. kiwi     
  7. orange   

【二】、spring+hessian 實作服務端:

1.基本代碼見上面的demo

2.修改配置檔案

在web.xml,增加内容如下:

Xml代碼

  1. <servlet>    
  2.         <servlet-name>springhessianservlet-name>    
  3.         <servlet-class>    
  4.             org.springframework.web.servlet.DispatcherServlet     
  5.         servlet-class>    
  6.     <bean name="/helloHessianService"    
  7.         class="org.springframework.remoting.caucho.HessianServiceExporter">    
  8.         <property name="service" ref="helloHessianImpl" />    
  9.         <property name="serviceInterface"    
  10.             value="michael.hessian.HelloHessian" />    
  11.     bean>    
  12. beans>  

3.java用戶端驗證

和上面的例子相似,隻需要把通路的url替換成新的即可如下:

Java代碼

  1. String url=http://localhost:8082/J2EE_sjsky/springhessian/helloHessianService   

運作結果和上面例子一樣。

4.spring配置用戶端

增加一個spring的bean配置檔案hessian-client.xml

Xml代碼

  1. xml version="1.0" encoding="UTF-8"?>    
  2. >    
  3. <beans>    
  4.     <bean id="helloHessianClient"    
  5.         class="org.springframework.remoting.caucho.HessianProxyFactoryBean">    
  6.         <property name="serviceUrl">    
  7.             <value>    
  8.                 http://localhost:8082/J2EE_sjsky/springhessian/helloHessianService     
  9.             value>    
  10.         property>    
  11.         <property name="serviceInterface"    
  12.             value="michael.hessian.HelloHessian" />    
  13.     bean>    
  14. beans>    

測試代碼HessianSpringClient.java:

Java代碼

  1. package michael.hessian.client;     
  2. import java.util.Map;     
  3. import michael.hessian.HelloHessian;     
  4. import michael.hessian.MyCar;     
  5. import org.springframework.context.ApplicationContext;     
  6. import org.springframework.context.support.ClassPathXmlApplicationContext;     
  7. public class HessianSpringClient {     
  8.     public static void main(String[] args) {     
  9.         try {     
  10.             ApplicationContext context = new ClassPathXmlApplicationContext(     
  11.                     "hessian-client.xml");     
  12.             HelloHessian hello = (HelloHessian) context     
  13.                     .getBean("helloHessianClient");     
  14.             System.out.println(hello.sayHello());     
  15.             MyCar car = hello.getMyCar();     
  16.             System.out.println(car.toString());     
  17.             for (Map.Entry<string, string> entry : hello.myBabays().entrySet()) {     
  18.                 System.out.println(entry.getKey() + "   " + entry.getValue());     
  19.             }     
  20.             for (String str : hello.myLoveFruit()) {     
  21.                 System.out.println(str);     
  22.             }     
  23.         } catch (Exception e) {     
  24.             e.printStackTrace();     
  25.         }     
  26.     }     
  27. }   

運作結果和上面完全一緻。

5.com.caucho.hessian.io.HessianProtocolException: expected string at 0x6d異常處理

我在spring+hessian整合測試過程中,用戶端調用時,發生了異常,而服務端錯誤内容如下:

Java代碼

  1. 2011-4-25 16:14:44 org.apache.catalina.core.StandardWrapperValve invoke     
  2. 嚴重: Servlet.service() for servlet remoting threw exception     
  3. com.caucho.hessian.io.HessianProtocolException: expected string at 0x6d    
  4.     at com.caucho.hessian.io.Hessian2Input.error(Hessian2Input.java:2882)     
  5.     at com.caucho.hessian.io.Hessian2Input.expect(Hessian2Input.java:2830)     
  6.     at com.caucho.hessian.io.Hessian2Input.readString(Hessian2Input.java:1362)     
  7.     at com.caucho.hessian.io.Hessian2Input.readMethod(Hessian2Input.java:272)     
  8.     at com.caucho.hessian.server.HessianSkeleton.invoke(HessianSkeleton.java:249)     
  9.     at com.caucho.hessian.server.HessianSkeleton.invoke(HessianSkeleton.java:221)     
  10.     at org.springframework.remoting.caucho.Hessian2SkeletonInvoker.invoke(Hessian2SkeletonInvoker.java:67)     
  11.     at org.springframework.remoting.caucho.HessianServiceExporter.handleRequest(HessianServiceExporter.java:147)     
  12.     at org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter.handle(HttpRequestHandlerAdapter.java:49)     
  13.     at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:819)     
  14.     at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:754)     
  15.     at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:399)     
  16.     at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:364)     
  17.     at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)     
  18.     at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)     
  19.     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)     
  20.     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)     
  21.     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)     
  22.     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)     
  23.     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)     
  24.     at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)     
  25.     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)     
  26.     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:261)     
  27.     at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)     
  28.     at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:581)     
  29.     at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)     
  30.     at java.lang.Thread.run(Thread.java:619)   

經查資料發現原始是hessian和spring的版本不相容引起的,重新下載下傳hessian-3.1.6.jar導入項目,一起運作正常,測試完全通過。

原文出處:http://developer.51cto.com/art/201104/257498.htm