hessian-demo和hessian与spring整合demo

  Hessian是一个轻量级的remoting on http工具,使用简单的方法提供了RMI(Remote Method Invocation,远程方法调用)的功能。采用的是二进制RPC(Remote Procedure Call Protocol,远程过程调用协议)协议,因为采用的是二进制协议,所以它很适合于发送二进制数据。

  在进行基于Hessian的项目开发时,应当注意以下几点:

  ▲JAVA服务器端必须具备以下几点:

  ·包含Hessian的jar包。

  ·设计一个接口,用来给客户端调用。

  ·实现该接口的功能。

  ·配置web.xml,配好相应的servlet。

  ·对象必须实现Serializable 接口。

  ·对于复杂对像可以使用Map的方法传递。

  ▲客户端必须具备以下几点:

  ·java客户端包含Hessian.jar的包。

  ·具有和服务器端结构一样的接口。

·利用HessianProxyFactory调用远程接口。

下面是一个hessian的简单例子。

Java服务器端:

环境:j2sdk1.4.2、Tomcat6.0

依赖的包:hessian-3.1.6.jar

新建一个名为HessianServer的web project。将hessian-3.1.6.jar放入WEB-INF/lib文件夹中。

创建接口:

package server.demo;

public interface DemoApi {

public void setName(String name);

public String sayHello();

public User getUser();

}

实现接口:

package server.demo;

public class DemoService implements DemoApi {

private String name;

public String sayHello() {

return "Hello "+name;

}

public void setName(String name) {

this.name=name;

System.out.println("Hello "+name);

}

public User getUser() {

return new User("lingling", "pass");

}

}

创建User类,注意:一定要implements Serializable。

package server.demo;

import java.io.Serializable;

public class User implements Serializable {

String name = "kitty";

String password = "nopass";

public User() {

super();

}

public User(String name, String password) {

super();

this.name = name;

this.password = password;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

}

配置web.xml:

<servlet>

<servlet-name>first</servlet-name>

<servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class>

<init-param>

<param-name>service-class</param-name>

<param-value>server.demo.DemoService</param-value>

</init-param>

</servlet>

<servlet-mapping>

<servlet-name>first</servlet-name>

<url-pattern>/helloworld</url-pattern>

</servlet-mapping>

将项目发布到tomcat服务器上。

Java客户端:

环境:j2sdk1.4.2

依赖的包:hessian-3.1.6.jar

创建一个名为HessianClient的java project,载入hessian-3.1.6.jar。

创建与服务器一样的接口及User类,注意它们所在的包路径也要与服务器相同,否则会出现java.lang.ClassNotFoundException。

接口:

package server.demo;

public interface DemoApi {

public void setName(String name);

public String sayHello();

public User getUser();

}

User类:

package server.demo;

import java.io.Serializable;

public class User implements Serializable {

String name = "kitty";

String password = "nopass";

public User() {

super();

}

public User(String name, String password) {

super();

this.name = name;

this.password = password;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

}

客户端程序:

package client.demo;

import java.net.MalformedURLException;

import server.demo.DemoApi;

import com.caucho.hessian.client.HessianProxyFactory;

public class ClientTest {

public static void main(String[] args) throws MalformedURLException,

ClassNotFoundException {

String url = "http://localhost:9520/HessianServer/helloworld";

HessianProxyFactory factory = new HessianProxyFactory();

DemoApi api = (DemoApi) factory.create(url);

api.setName("test");

System.out.println(api.sayHello());

System.out.println(api.getUser().getName());

System.out.println(api.getUser().getPassword());

}

}

现在,启动tomcat,运行ClientTest。运行结果:

Hello test

lingling

pass

现在,在以上基础上将hessian与spring整合。

Java服务器端(即我们上面建的名为HessianServer的web project):

环境:j2sdk1.4.2、Tomcat6.0

依赖的包:

Hessian包:hessian-3.1.6.jar

spring-framework-2.0.2包:

aopalliance.jar

commons-logging.jar

log4j-1.2.14.jar

spring.jar

spring-aop.jar

spring-beans.jar

spring-context.jar

spring-core.jar

spring-jdbc.jar

spring-jms.jar

spring-web.jar

spring-webmvc.jar

配置web.xml,web.xml中增加:

<servlet>

<servlet-name>remote</servlet-name>

<servlet-class>

org.springframework.web.servlet.DispatcherServlet

</servlet-class>

<init-param>

<param-name>namespace</param-name>

<param-value>classes/remote-servlet</param-value>

</init-param>

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

</servlet>

<servlet-mapping>

<servlet-name>remote</servlet-name>

<url-pattern>/remote/*</url-pattern>

</servlet-mapping>

写spring的发布hessian服务的配置文件remote-servlet.xml,这个文件就建在工程的src下,即deploy到tomcat后,在WEB-INF/classes目录下。注意:这个文件为什么叫remote-servlet.xml呢?因为我们在web.xml中有配置:<servlet-name>remote</servlet-name>。所以remote-servlet.xml的文件名必须以<servlet-name>中配置的servlet-name作为文件名的开头,且文件名的格式必须是[servlet-name]-servlet.xml格式,否则出错。

<param-value>classes/remote-servlet</param-value>所以文件名为remote-servlet.xml。

以下是remote-servlet.xml的内容:

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

<bean id="demoService" class="server.demo.DemoService" />

<bean name="/helloSpring"

class="org.springframework.remoting.caucho.HessianServiceExporter">

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

<property name="serviceInterface" value="server.demo.DemoApi" />

</bean>

</beans>

好了,现在可以测试一下了。在刚才建的名为HessianClient的java project中修改client.demo.ClientTest.java如下:

package client.demo;

import java.net.MalformedURLException;

import server.demo.DemoApi;

import com.caucho.hessian.client.HessianProxyFactory;

public class ClientTest {

public static void main(String[] args) throws MalformedURLException,

ClassNotFoundException {

// String url = "http://localhost:9520/HessianServer/helloworld";

String url = "http://localhost:9520/HessianServer/remote/helloSpring";

HessianProxyFactory factory = new HessianProxyFactory();

DemoApi api = (DemoApi) factory.create(DemoApi.class, url);

api.setName("test");

System.out.println(api.sayHello());

System.out.println(api.getUser().getName());

System.out.println(api.getUser().getPassword());

}

}

现在,启动tomcat,运行ClientTest。运行结果:

Hello test

lingling

pass

如果客户端也使用spring呢?现在做一个spring整合hessian的客户端demo。首先载入spring-framework-2.0.2包:

aopalliance.jar

commons-logging.jar

log4j-1.2.14.jar

spring.jar

spring-aop.jar

spring-beans.jar

spring-context.jar

spring-core.jar

spring-jdbc.jar

spring-jms.jar

spring-web.jar

spring-webmvc.jar

在名为HessianClient的java project中src目录下,新建一个remote-client.xml,这个文件可随意命名。remote-client.xml内容为:

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

<bean id="helloSpring"

class="org.springframework.remoting.caucho.HessianProxyFactoryBean">

<property name="serviceUrl">

<value>

http://localhost:9520/HessianServer/remote/helloSpring

</value>

</property>

<property name="serviceInterface">

<value>server.demo.DemoApi</value>

</property>

</bean>

</beans>

在刚才建的名为HessianClient的java project中修改client.demo.ClientTest.java如下:

package client.demo;

import java.net.MalformedURLException;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import server.demo.DemoApi;

public class ClientTest {

public static void main(String[] args) throws MalformedURLException,

ClassNotFoundException {

// String url = "http://localhost:9520/HessianServer/helloworld";

// String url =

// "http://localhost:9520/HessianServer/remote/helloSpring";

// HessianProxyFactory factory = new HessianProxyFactory();

// DemoApi api = (DemoApi) factory.create(DemoApi.class, url);

ApplicationContext context = new ClassPathXmlApplicationContext(

"remote-client.xml");

DemoApi api = (DemoApi) context.getBean("helloSpring");

api.setName("test");

System.out.println(api.sayHello());

System.out.println(api.getUser().getName());

System.out.println(api.getUser().getPassword());

}

}

现在,启动tomcat,运行ClientTest。运行结果:

Hello test

lingling

pass

至此over~

PS:有时候可能因hessian或spring的版本问题使程序不能运行。

/**

* @version 1.1

* @author iam00@qq.com

* @add Mar 18, 2010

*/

反映问题:

假设有多个应用,需要不止一个接口是向下面这样加上吗?

<init-param>

        <param-name>service-class</param-name>

        <param-value>server.demo.DemoService</param-value>

 </init-param>

答:这样加上肯定是不行的,可以再配置一个servlet啊, 这个servlet的类还是com.caucho.hessian.server.HessianServlet,但init-param可以是另外一个,url-pattern也是另一个。如:

<servlet>

<servlet-name>mul</servlet-name>

<servlet-class>

com.caucho.hessian.server.HessianServlet

</servlet-class>

<init-param>

<param-name>service-class</param-name>

<param-value>server.mul.MulService</param-value>

</init-param>

</servlet>

<servlet-mapping>

<servlet-name>mul</servlet-name>

<url-pattern>/hellomul</url-pattern>

</servlet-mapping>

这样,在客户端用HessianProxyFactory工厂创建对象的时候,url也变为第二个servlet所设置的url-pattern。

这 协议是用二进制传输的,所以需要序列化是把,但如果是复杂的对象,而且对象之间还有复杂的关系,如果传输这样一些对象,怎样能维护他们的关系不被序列化破 坏呢

其实,以我的理解,hessian是为了远程调用方法。百度查到:对于复杂对象可以使用Map的方法传递。我现在对此问题没有更深入的研究。你所说的对象是不是实体类的对象?因为服务器端的实体类在客户端也会有相同的实体类,当然各实体类之间的关系也完全一样,客户端也会有一个服务器端的接口(api),用以调用方法。也就是说,客户端比服务器端只少一个service(即真正实现api所有方法的类)。