小试Hessian实现webservice

2024-01-04 16:38

本文主要是介绍小试Hessian实现webservice,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

[color=red]blog迁移至[/color]:[url=http://www.micmiu.com]http://www.micmiu.com[/url]

[size=large]Hessian[/size]是一个轻量级的remoting on http工具,采用的是Binary RPC协议,所以它很适合于发送二进制数据,同时又具有防火墙穿透能力。Hessian一般是通过Web应用来提供服务,因此非常类似于平时我们用的WebService。只是它不使用SOAP协议,但相比webservice而言更简单、快捷。

[size=medium]Hessian官网:[url=http://hessian.caucho.com/]http://hessian.caucho.com/[/url][/size]

Hessian可通过Servlet提供远程服务,需要将匹配某个模式的请求映射到Hessian服务。也可Spring框架整合,通过它的DispatcherServlet可以完成该功能,DispatcherServlet可将匹配模式的请求转发到Hessian服务。Hessian的server端提供一个servlet基类, 用来处理发送的请求,而Hessian的这个远程过程调用,完全使用动态代理来实现的,,建议采用面向接口编程,Hessian服务通过接口暴露。

[size=medium]Hessian处理过程示意图:[/size]
[color=red]客户端——>序列化写到输出流——>远程方法(服务器端)——>序列化写到输出流 ——>客户端读取输入流——>输出结果[/color]

[size=medium]下面详细介绍最常用的两种方式实现Hessian提供webservice:[/size]
[color=blue][list]
[*]纯Hessian实现
[*]配合Spring框架实现
[/list][/color]
在开始之前当然需要到官网上下载相关的lib包,放入项目的/WEB-INF/lib/下
[color=blue][size=large]【一】、纯Hessian实现步骤:[/size][/color]
[size=medium]1.基本代码[/size]
首先编写一个服务的接口类:HelloHessian.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();

}

一个java bean文件MyCar.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
+ "].";
}

}

服务端接口的实现类:HelloHessianImpl.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";
}

}

[size=medium]2.配置文件web.xml修改[/size]
在web.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>

[size=medium]3.java客户端验证[/size]
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();
}

}

}

运行结果如下:
welcom to Hessian
my car name:[阿斯顿·马丁] model:[One-77].
daughter 孙小美
son 孙吴空
apple
kiwi
orange


[color=blue][size=large]【二】、spring+hessian 实现服务端:[/size][/color]
[size=medium]1.基本代码见上面的demo[/size]
[size=medium]2.修改配置文件[/size]
在web.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>

在/WEB-INF/增加一个叫[color=red]servlet-name[/color]-servlet.xml配置文件。该文件的命名有一定的规则,红色[color=red]servlet-name[/color]需要和web.xml中的<servlet-name>springhessian</servlet-name>定义的名称相匹配,比如本例子应叫[color=red]springhessian-servlet.xml[/color],这样简单也不容易出错。
[color=blue]当然该文件也可以自己任意命名。如果是自定义的文件名称不符合上述默认的规则,需要在<servlet>中增加<init-param>相关属性,人为指定加载配置文件,否则会报错。[/color]
范例:springhessian-servlet.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>


[size=medium]3.java客户端验证[/size]
和上面的例子相似,只需要把访问的url替换成新的即可如下:
String url=http://localhost:8082/J2EE_sjsky/springhessian/helloHessianService

运行结果和上面例子一样。

[size=medium]4.spring配置客户端[/size]
增加一个spring的bean配置文件hessian-client.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>


测试代码HessianSpringClient.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();
}

}

}

运行结果和上面完全一致。
[size=medium]5.com.caucho.hessian.io.HessianProtocolException: expected string at 0x6d异常处理[/size]
我在spring+hessian整合测试过程中,客户端调用时,发生了异常,而服务端错误内容如下:
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导入项目,一切运行正常,测试完全通过。

-----------------------------------分 ------------------------------------隔 ------------------------------------线 --------------------------------------

这篇关于小试Hessian实现webservice的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/569945

相关文章

windos server2022里的DFS配置的实现

《windosserver2022里的DFS配置的实现》DFS是WindowsServer操作系统提供的一种功能,用于在多台服务器上集中管理共享文件夹和文件的分布式存储解决方案,本文就来介绍一下wi... 目录什么是DFS?优势:应用场景:DFS配置步骤什么是DFS?DFS指的是分布式文件系统(Distr

NFS实现多服务器文件的共享的方法步骤

《NFS实现多服务器文件的共享的方法步骤》NFS允许网络中的计算机之间共享资源,客户端可以透明地读写远端NFS服务器上的文件,本文就来介绍一下NFS实现多服务器文件的共享的方法步骤,感兴趣的可以了解一... 目录一、简介二、部署1、准备1、服务端和客户端:安装nfs-utils2、服务端:创建共享目录3、服

C#使用yield关键字实现提升迭代性能与效率

《C#使用yield关键字实现提升迭代性能与效率》yield关键字在C#中简化了数据迭代的方式,实现了按需生成数据,自动维护迭代状态,本文主要来聊聊如何使用yield关键字实现提升迭代性能与效率,感兴... 目录前言传统迭代和yield迭代方式对比yield延迟加载按需获取数据yield break显式示迭

Python实现高效地读写大型文件

《Python实现高效地读写大型文件》Python如何读写的是大型文件,有没有什么方法来提高效率呢,这篇文章就来和大家聊聊如何在Python中高效地读写大型文件,需要的可以了解下... 目录一、逐行读取大型文件二、分块读取大型文件三、使用 mmap 模块进行内存映射文件操作(适用于大文件)四、使用 pand

python实现pdf转word和excel的示例代码

《python实现pdf转word和excel的示例代码》本文主要介绍了python实现pdf转word和excel的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录一、引言二、python编程1,PDF转Word2,PDF转Excel三、前端页面效果展示总结一

Python xmltodict实现简化XML数据处理

《Pythonxmltodict实现简化XML数据处理》Python社区为提供了xmltodict库,它专为简化XML与Python数据结构的转换而设计,本文主要来为大家介绍一下如何使用xmltod... 目录一、引言二、XMLtodict介绍设计理念适用场景三、功能参数与属性1、parse函数2、unpa

C#实现获得某个枚举的所有名称

《C#实现获得某个枚举的所有名称》这篇文章主要为大家详细介绍了C#如何实现获得某个枚举的所有名称,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下... C#中获得某个枚举的所有名称using System;using System.Collections.Generic;usi

Go语言实现将中文转化为拼音功能

《Go语言实现将中文转化为拼音功能》这篇文章主要为大家详细介绍了Go语言中如何实现将中文转化为拼音功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 有这么一个需求:新用户入职 创建一系列账号比较麻烦,打算通过接口传入姓名进行初始化。想把姓名转化成拼音。因为有些账号即需要中文也需要英

C# 读写ini文件操作实现

《C#读写ini文件操作实现》本文主要介绍了C#读写ini文件操作实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录一、INI文件结构二、读取INI文件中的数据在C#应用程序中,常将INI文件作为配置文件,用于存储应用程序的

C#实现获取电脑中的端口号和硬件信息

《C#实现获取电脑中的端口号和硬件信息》这篇文章主要为大家详细介绍了C#实现获取电脑中的端口号和硬件信息的相关方法,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 我们经常在使用一个串口软件的时候,发现软件中的端口号并不是普通的COM1,而是带有硬件信息的。那么如果我们使用C#编写软件时候,如