会计考友 发表于 2012-8-4 12:44:44

Java认证:小小试Hessian实现webservice

Java认证:小小试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代码
package michael.hessian;
import java.util.List;
import java.util.Map;
/**
* @author michael
*
*/
public interface HelloHessian {
String sayHello();
MyCar getMyCar();
List《String》 myLoveFruit();
Map《String, String》 myBabays();
}
package michael.hessian;
import java.util.List;
import java.util.Map;
/**
* @author michael
*
*/
public interface HelloHessian {
String sayHello();
MyCar getMyCar();
List《String》 myLoveFruit();
Map《String, String》 myBabays();
}
一个java bean文件MyCar.java:
Java代码
package michael.hessian;
import java.io.Serializable;


/**
* @author michael
*
*/
public class MyCar implements Serializable {
/**
*
*/
private static final long serialVersionUID = 4736905401908455439L;
private String carName;
private String carmodel;
/**
* @return the carName
*/
public String getCarName() {
return carName;
}
/**
* @return the carmodel
*/
public String getCarmodel() {
return carmodel;
}
/**
* @param pCarName the carName to set
*/
public void setCarName(String pCarName) {
carName = pCarName;
}
/**
* @param pCarModel the carmodel to set
*/
public void setCarModel(String pCarmodel) {
carModel = pCarmodel;
}
/**
* @see java.lang.Object#toString()
* @return
*/
@Override
public String toString() {
return “my car name:[” + this.carName + “] model:[” + this.carmodel
+ “]。”;
}
}
package michael.hessian;
import java.io.Serializable;
/**
* @author michael
*
*/
public class MyCar implements Serializable {
/**
*
*/
private static final long serialVersionUID = 4736905401908455439L;
private String carName;
private String carmodel;
/**
* @return the carName
*/
public String getCarName() {
return carName;
}
/**
* @return the carmodel
*/
public String getCarmodel() {
return carmodel;
}
/**
* @param pCarName the carName to set
*/
public void setCarName(String pCarName) {
carName = pCarName;
}
/**
* @param pCarModel the carmodel to set
*/
public void setCarModel(String pCarmodel) {
carModel = pCarmodel;
}
/**
* @see java.lang.Object#toString()
* @return
*/
@Override
public String toString() {
return “my car name:[” + this.carName + “] model:[” + this.carmodel
+ “]。”;
}
}
服务端接口的实现类:HelloHessianImpl.java
Java代码
package michael.hessian.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import michael.hessian.HelloHessian;
import michael.hessian.MyCar;
/**
* @author michael
*
*/
public class HelloHessianImpl extends HessianServlet implements HelloHessian {
public MyCar getMyCar() {
MyCar car = new MyCar();
car.setCarName(“阿斯顿·马丁”);
car.setCarmodel(“One-77”);
return car;
}
public Map《String, String》 myBabays() {
Map《String, String》 map = new HashMap《String, String》();
map.put(“son”, “孙吴空”);
map.put(“daughter”, “孙小美”);
return map;
}
public List《String》 myLoveFruit() {
List《String》 list = new ArrayList《String》();
list.add(“apple”);
list.add(“kiwi”);
list.add(“orange”);
return list;
}
public String sayHello() {
return “welcom to Hessian”;
}
}


package michael.hessian.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import michael.hessian.HelloHessian;
import michael.hessian.MyCar;
/**
* @author michael
*
*/
public class HelloHessianImpl extends HessianServlet implements HelloHessian {
public MyCar getMyCar() {
MyCar car = new MyCar();
car.setCarName(“阿斯顿·马丁”);
car.setCarmodel(“One-77”);
return car;
}
public Map《String, String》 myBabays() {
Map《String, String》 map = new HashMap《String, String》();
map.put(“son”, “孙吴空”);
map.put(“daughter”, “孙小美”);
return map;
}
public List《String》 myLoveFruit() {
List《String》 list = new ArrayList《String》();
list.add(“apple”);
list.add(“kiwi”);
list.add(“orange”);
return list;
}
public String sayHello() {
return “welcom to Hessian”;
}
}
2.配置文件web.xml修改
在web.xml配置文件里增加如下信息:
Xml代码
《servlet》
《servlet-name》HelloHessian《/servlet-name》
《servlet-class》
com.caucho.hessian.server.HessianServlet
《/servlet-class》
《init-param》
《param-name》home-class《/param-name》
《param-value》michael.hessian.impl.HelloHessianImpl《/param-value》
《/init-param》
《init-param》
《param-name》home-api《/param-name》
《param-value》michael.hessian.HelloHessian《/param-value》
《/init-param》
《load-on-startup》1《/load-on-startup》
《/servlet》
《servlet-mapping》
《servlet-name》HelloHessian《/servlet-name》
《url-pattern》/HessianService《/url-pattern》
《/servlet-mapping》
《servlet-mapping》
《servlet》
《servlet-name》HelloHessian《/servlet-name》
《servlet-class》
com.caucho.hessian.server.HessianServlet
《/servlet-class》
《init-param》
《param-name》home-class《/param-name》
《param-value》michael.hessian.impl.HelloHessianImpl《/param-value》
《/init-param》
《init-param》
《param-name》home-api《/param-name》
《param-value》michael.hessian.HelloHessian《/param-value》
《/init-param》
《load-on-startup》1《/load-on-startup》
《/servlet》
《servlet-mapping》
《servlet-name》HelloHessian《/servlet-name》
《url-pattern》/HessianService《/url-pattern》
《/servlet-mapping》
《servlet-mapping》
3.java客户端验证
Java代码
package michael.hessian.client;
import java.net.MalformedURLException;
import java.util.Map;
import michael.hessian.HelloHessian;
import michael.hessian.MyCar;
import com.caucho.hessian.client.HessianProxyFactory;
/**
* @author michael
*
*/
public class HessianClientTest {
/**
* @param args
*/
public static void main(String[] args) {
String url = “http://localhost:8082/J2EE_sjsky/HessianService”;
HessianProxyFactory factory = new HessianProxyFactory();
try {
HelloHessian hello = (HelloHessian) factory.create(
HelloHessian.class, url);
System.out.println(hello.sayHello());
MyCar car = hello.getMyCar();
System.out.println(car.toString());
for (Map.Entry《String, String》 entry : hello.myBabays().entrySet()) {
System.out.println(entry.getKey() + “ ” + entry.getValue());
}
for (String str : hello.myLoveFruit()) {
System.out.println(str);
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
package michael.hessian.client;
import java.net.MalformedURLException;
import java.util.Map;
import michael.hessian.HelloHessian;
import michael.hessian.MyCar;
import com.caucho.hessian.client.HessianProxyFactory;
/**
* @author michael
*
*/
public class HessianClientTest {
/**
* @param args
*/
public static void main(String[] args) {
String url = “http://localhost:8082/J2EE_sjsky/HessianService”;
HessianProxyFactory factory = new HessianProxyFactory();
try {
HelloHessian hello = (HelloHessian) factory.create(
HelloHessian.class, url);
System.out.println(hello.sayHello());
MyCar car = hello.getMyCar();
System.out.println(car.toString());
for (Map.Entry《String, String》 entry : hello.myBabays().entrySet()) {
System.out.println(entry.getKey() + “ ” + entry.getValue());
}
for (String str : hello.myLoveFruit()) {
System.out.println(str);
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
运行结果如下:


Java代码
welcom to Hessian
my car name:[阿斯顿·马丁] model:[One-77]。
daughter 孙小美
son 孙吴空
apple
kiwi
orange
welcom to Hessian
my car name:[阿斯顿·马丁] model:[One-77]。
daughter 孙小美
son 孙吴空
apple
kiwi
orange
【二】、spring+hessian 实现服务端:
1.基本代码见上面的demo
2.修改配置文件
在web.xml,增加内容如下:
Xml代码
《servlet》
《servlet-name》springhessian《/servlet-name》
《servlet-class》
org.springframework.web.servlet.DispatcherServlet
《/servlet-class》
《!--
《init-param》
《param-name》contextConfigLocation《/param-name》
《param-value》/WEB-INF/springhessian-servlet.xml《/param-value》
《/init-param》
--》
《load-on-startup》1《/load-on-startup》
《/servlet》
《servlet-mapping》
《servlet-name》springhessian《/servlet-name》
《url-pattern》/springhessian/*《/url-pattern》
《/servlet-mapping》
《servlet》
《servlet-name》springhessian《/servlet-name》
《servlet-class》
org.springframework.web.servlet.DispatcherServlet
《/servlet-class》
《!--
《init-param》
《param-name》contextConfigLocation《/param-name》
《param-value》/WEB-INF/springhessian-servlet.xml《/param-value》
《/init-param》
--》
《load-on-startup》1《/load-on-startup》
《/servlet》
《servlet-mapping》
《servlet-name》springhessian《/servlet-name》
《url-pattern》/springhessian/*《/url-pattern》
《/servlet-mapping》
在/WEB-INF/增加一个叫servlet-name-servlet.xml配置文件。该文件的命名有一定的规则,红色servlet-name需要和web.xml中的《servlet-name》springhessian《/servlet-name》定义的名称相匹配,比如本例子应叫springhessian-servlet.xml,这样简单也不容易出错。
当然该文件也可以自己任意命名。如果是自定义的文件名称不符合上述默认的规则,需要在《servlet》中增加《init-param》相关属性,人为指定加载配置文件,否则会报错。
范例:springhessian-servlet.xml
Xml代码
《?xml version=“1.0” encoding=“UTF-8”?》
《!DOCTYPE beans PUBLIC “-//SPRING//DTD BEAN//EN” “http://www.springframework.org/dtd/spring-beans.dtd”》
《beans》
《bean id=“helloHessianImpl”
class=“michael.hessian.impl.HelloHessianImpl” /》
《!-- 使用HessianServiceExporter 将bean生成Hessian服务--》
《bean name=“/helloHessianService”
class=“org.springframework.remoting.caucho.HessianServiceExporter”》
《!-- 定义需要生成服务的实现类--》
《property name=“service” ref=“helloHessianImpl” /》
《!-- Hessian 提供服务的接口--》
《property name=“serviceInterface”
value=“michael.hessian.HelloHessian” /》
《/bean》
《/beans》
《?xml version=“1.0” encoding=“UTF-8”?》
《!DOCTYPE beans PUBLIC “-//SPRING//DTD BEAN//EN” “http://www.springframework.org/dtd/spring-beans.dtd”》
《beans》
《bean id=“helloHessianImpl”
class=“michael.hessian.impl.HelloHessianImpl” /》
《!-- 使用HessianServiceExporter 将bean生成Hessian服务--》
《bean name=“/helloHessianService”
class=“org.springframework.remoting.caucho.HessianServiceExporter”》
《!-- 定义需要生成服务的实现类--》
《property name=“service” ref=“helloHessianImpl” /》
《!-- Hessian 提供服务的接口--》
《property name=“serviceInterface”
value=“michael.hessian.HelloHessian” /》
《/bean》
《/beans》
3.java客户端验证
和上面的例子相似,只需要把访问的url替换成新的即可如下:
Java代码
String url=http://localhost:8082/J2EE_sjsky/springhessian/helloHessianService
String url=http://localhost:8082/J2EE_sjsky/springhessian/helloHessianService
运行结果和上面例子一样。
4.spring配置客户端
增加一个spring的bean配置文件hessian-client.xml
Xml代码
《?xml version=“1.0” encoding=“UTF-8”?》
《!DOCTYPE beans PUBLIC “-//SPRING//DTD BEAN//EN” “http://www.springframework.org/dtd/spring-beans.dtd”》
《beans》
《bean id=“helloHessianClient”
class=“org.springframework.remoting.caucho.HessianProxyFactoryBean”》
《property name=“serviceUrl”》
《value》
http://localhost:8082/J2EE_sjsky/springhessian/helloHessianService
《/value》
《/property》
《property name=“serviceInterface”
value=“michael.hessian.HelloHessian” /》
《/bean》
《/beans》
《?xml version=“1.0” encoding=“UTF-8”?》
《!DOCTYPE beans PUBLIC “-//SPRING//DTD BEAN//EN” “http://www.springframework.org/dtd/spring-beans.dtd”》
《beans》
《bean id=“helloHessianClient”
class=“org.springframework.remoting.caucho.HessianProxyFactoryBean”》
《property name=“serviceUrl”》
《value》
http://localhost:8082/J2EE_sjsky/springhessian/helloHessianService
《/value》
《/property》
《property name=“serviceInterface”
value=“michael.hessian.HelloHessian” /》
《/bean》
《/beans》
测试代码HessianSpringClient.java:
Java代码
package michael.hessian.client;
import java.util.Map;
import michael.hessian.HelloHessian;
import michael.hessian.MyCar;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author michael
*
*/


public class HessianSpringClient {
/**
* @param args
*/
public static void main(String[] args) {
try {
ApplicationContext context = new ClassPathXmlApplicationContext(
“hessian-client.xml”);
HelloHessian hello = (HelloHessian) context
.getBean(“helloHessianClient”);
System.out.println(hello.sayHello());
MyCar car = hello.getMyCar();
System.out.println(car.toString());
for (Map.Entry《String, String》 entry : hello.myBabays().entrySet()) {
System.out.println(entry.getKey() + “ ” + entry.getValue());
}
for (String str : hello.myLoveFruit()) {
System.out.println(str);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
package michael.hessian.client;
import java.util.Map;
import michael.hessian.HelloHessian;
import michael.hessian.MyCar;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author michael
*
*/
public class HessianSpringClient {
/**
* @param args
*/
public static void main(String[] args) {
try {
ApplicationContext context = new ClassPathXmlApplicationContext(
“hessian-client.xml”);
HelloHessian hello = (HelloHessian) context
.getBean(“helloHessianClient”);
System.out.println(hello.sayHello());
MyCar car = hello.getMyCar();
System.out.println(car.toString());
for (Map.Entry《String, String》 entry : hello.myBabays().entrySet()) {
System.out.println(entry.getKey() + “ ” + entry.getValue());
}
for (String str : hello.myLoveFruit()) {
System.out.println(str);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果和上面完全一致
5.com.caucho.hessian.io.HessianProtocolException: expected string at 0x6d异常处理
我在spring+hessian整合测试过程中,客户端调用时,发生了异常,而服务端错误内容如下:
Java代码
2011-4-25 16:14:44 org.apache.catalina.core.StandardWrapperValve invoke
严重: Servlet.service() for servlet remoting threw exception
com.caucho.hessian.io.HessianProtocolException: expected string at 0x6d
at com.caucho.hessian.io.Hessian2Input.error(Hessian2Input.java:2882)
at com.caucho.hessian.io.Hessian2Input.expect(Hessian2Input.java:2830)
at com.caucho.hessian.io.Hessian2Input.readString(Hessian2Input.java:1362)
at com.caucho.hessian.io.Hessian2Input.readMethod(Hessian2Input.java:272)
at com.caucho.hessian.server.HessianSkeleton.invoke(HessianSkeleton.java:249)
at com.caucho.hessian.server.HessianSkeleton.invoke(HessianSkeleton.java:221)
at org.springframework.remoting.caucho.Hessian2SkeletonInvoker.invoke(Hessian2SkeletonInvoker.java:67)
at org.springframework.remoting.caucho.HessianServiceExporter.handleRequest(HessianServiceExporter.java:147)
at org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter.handle(HttpRequestHandlerAdapter.java:49)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:819)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:754)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:399)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:364)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:261)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:581)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:619)
2011-4-25 16:14:44 org.apache.catalina.core.StandardWrapperValve invoke
严重: Servlet.service() for servlet remoting threw exception
com.caucho.hessian.io.HessianProtocolException: expected string at 0x6d
at com.caucho.hessian.io.Hessian2Input.error(Hessian2Input.java:2882)
at com.caucho.hessian.io.Hessian2Input.expect(Hessian2Input.java:2830)
at com.caucho.hessian.io.Hessian2Input.readString(Hessian2Input.java:1362)
at com.caucho.hessian.io.Hessian2Input.readMethod(Hessian2Input.java:272)
at com.caucho.hessian.server.HessianSkeleton.invoke(HessianSkeleton.java:249)
at com.caucho.hessian.server.HessianSkeleton.invoke(HessianSkeleton.java:221)


at org.springframework.remoting.caucho.Hessian2SkeletonInvoker.invoke(Hessian2SkeletonInvoker.java:67)
at org.springframework.remoting.caucho.HessianServiceExporter.handleRequest(HessianServiceExporter.java:147)
at org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter.handle(HttpRequestHandlerAdapter.java:49)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:819)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:754)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:399)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:364)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:261)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:581)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:619)
经查资料发现原始是hessian和spring的版本不兼容引起的,重新下载hessian-3.1.6.jar导入项目,一起运行正常,测试完全通过。
页: [1]
查看完整版本: Java认证:小小试Hessian实现webservice