posts - 1,  comments - 1,  trackbacks - 0
一、Hessian简介(摘自百度百科)

Hessian是一个轻量级的remoting onhttp工具,使用简单的方法提供了RMI的功能. 相比WebService,Hessian更简单、快捷。采用的是二进制RPC协议,因为采用的是二进制协议,所以它很适合于发送二进制数据

二、Hessian开发要点
1、JAVA服务器端必须具备以下几点:

(1)包含Hessian的jar包
(2)设计一个接口,用来给客户端调用
(3)该接口的实现类
(4)配置web.xml中的servlet
(5)对象必须实现Serializable 接口
(6)对于复杂对象可以使用Map的方法传递
7)不支持JDK1.6+weblogic11g+Spring
-2、客户端必须具备以下几点:
(1)包含Hessian的jar包。
(2)具有和服务器端结构一样的接口和交互对象。
(3)利用HessianProxyFactory调用远程接口。

三、基于Spring2.0的Hessian开发实例
1、环境:
(1)服务端:JDK1.4+weblogic8.1
(2)客户端:JDK1.6+weblogic11g
2、相关JAR包:
(1)服务端:spring.jar、hessian-2.1.12.jar、commons-logging-1.0.4.jar
(2)客户端:spring.jar、hessian-2.1.12.jar、commons-logging-1.0.4.jar
四、服务端的实现
1、相关model(com.govdo.model)
(1)ServiceRequest.java 客户端请求服务类,用于接受客户端请求数据 
ServiceRequest.java
(2)ServiceResponse.java 客户端响应服务类,用于返回客户端响应数据
package com.govdo.model;

import java.io.Serializable;
import java.util.Map;

public class ServiceResponse implements Serializable {

    
private static final long serialVersionUID = 1L;
    
public static final String SERVICE_RESPONSE_RESULT = "SERVICE_RESPONSE_RESULT";
    
public static final String BUSINESS_SUCCESS = "0";
    
public static final String BUSINESS_FAILURE = "1";

    
private Map model = null;

    
public ServiceResponse() {}
    
public ServiceResponse(Map model) {
        
this.model = model;
    }

    
public Map getModel() {
        
return model;
    }


    
public void setModel(Map model) {
        
this.model = model;
    }


}
(3)QueryCityInfoIn.java 城市信息客户端请求对象,实现Serializable,源码略
(4)QueryCityInfoOut.java 城市信息客户端响应对象,实现Serializable,源码略
2、用于客户端调用的公共接口及实现
(1)Action.java 暴露给客户端的抽象公共接口
package com.govdo.action;

import com.govdo.model.ServiceRequest;
import com.govdo.model.ServiceResponse;

public abstract interface Action {

    
public abstract ServiceResponse perform(ServiceRequest request) throws Exception;
}
(2)AbstractAction.java 实现Action、BeanFactoryAware接口的抽象类
package com.govdo.action;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;

import com.govdo.model.ServiceRequest;
import com.govdo.model.ServiceResponse;

public abstract class AbstractAction implements Action, BeanFactoryAware {

    
protected BeanFactory context;
    
public void setBeanFactory(BeanFactory context) throws BeansException {
        
this.context = context;
    }


    
public abstract ServiceResponse perform(ServiceRequest request)
            
throws Exception;
}
(3)RemotingAction 继承AbstractAction的公共类,用于远程实现接口Action,其中serviceID是真正实现功能的bean,这个bean必须实现perform方法
package com.govdo.action;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.govdo.model.ServiceRequest;
import com.govdo.model.ServiceResponse;
import com.govdo.util.StringUtils;

public class RemotingAction extends AbstractAction {

    
private Log logger = LogFactory.getLog(getClass());
    
public ServiceResponse perform(ServiceRequest request)
            
throws Exception {
        String serviceID 
= (String)request.getRequestedServiceID();
        
if (StringUtils.isBlank(serviceID)) {
            logger.error(
"service id isn't allowed to be null!");
            
throw new IllegalArgumentException("service id isn't allowed to be null!");
        }

        Action action 
= (Action)context.getBean(serviceID);
        
return action.perform(request);
    }

}
3、服务端的相关配置
(1)remoting-servlet.xml 在WEB-INF下添加这个xml文件,其中/myHessian是暴露给客户端的访问路经,Action是调用接口,remotingAction是公共实现类
<?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="remotingAction" class="com.govdo.action.RemotingAction">
    
</bean>
    
<bean name="/myHessian"
        class
="org.springframework.remoting.caucho.HessianServiceExporter">
        
<property name="service" ref="remotingAction" />
        
<property name="serviceInterface" value="com.govdo.action.Action" />
    
</bean>
</beans>
(2)web.xml中增加相应的servlet配置,这里采用Spring的org.springframework.web.servlet.DispatcherServlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation
="http://java.sun.com/xml/ns/j2ee
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
>

    
<welcome-file-list>
        
<welcome-file>index.jsp</welcome-file>
    
</welcome-file-list>

    
<servlet>
        
<servlet-name>remoting</servlet-name>
        
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        
<init-param>
            
<param-name>contextConfigLocation</param-name>
            
<param-value>
            ,/WEB-INF/remoting-servlet.xml
            
</param-value>
        
</init-param>
        
<load-on-startup>1</load-on-startup>
    
</servlet>

    
<servlet-mapping>
        
<servlet-name>remoting</servlet-name>
        
<url-pattern>/remoting/*</url-pattern>
    
</servlet-mapping>

</web-app>
4、增加具体实现功能的bean
(1)HessianTestImpl.java具体实现类,继承AbstractAction相当于实现了Action接口,这里对请求数据做了简单处理,对城市名称后加了(by remoting),然后返回客户端,注意要实现perform方法
package com.govdo.test.action;

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.BeanUtils;

import com.govdo.action.AbstractAction;
import com.govdo.model.QueryCityInfoIn;
import com.govdo.model.QueryCityInfoOut;
import com.govdo.model.ServiceRequest;
import com.govdo.model.ServiceResponse;

public class HessianTestImpl extends AbstractAction {

    
public ServiceResponse perform(ServiceRequest request) throws Exception {

        Map resultMap 
= new HashMap();
        QueryCityInfoIn in 
= (QueryCityInfoIn)request.getCurrentRequestObject();
        QueryCityInfoOut out 
= new QueryCityInfoOut();
        BeanUtils.copyProperties(in, out);
        out.setCityName(out.getCityName()
+"(by remoting)");
        resultMap.put(ServiceResponse.BUSINESS_SUCCESS, out);
        Map model 
= new HashMap();
        model.put(ServiceResponse.SERVICE_RESPONSE_RESULT, resultMap);
        
return new ServiceResponse(model);
    }

}
(2)在Spring提供bean服务的XML配置文件中增加一个Bean(不妨就加在remoting-servlet.xml中,也可以另写一个xml,但必须在web.xml中加载),后面客户端实现会用到这个bean。
<bean id="hessianTest" class="com.govdo.test.action.HessianTestImpl">
    
</bean>
到这里服务端实现已全部完成,打包部署完工。这里假设部署实例上下文路径为:http://127.0.0.1:7008/webRoot/

五、客户端实现
1、准备工作
(1)相关model,服务端的4个对象都需要加到客户端来
(2)客户端调用的接口,Action接口也要加到客户端来
2、远程调用相关配置
(1)remoting-client.xml 配置远程调用接口和URL,回顾上章3(1)节,/myHessian是在remoting-servlet.xml 中配置的远程访问服务路径,所以这里URL为http://127.0.0.1:7008/webRoot/remoting/myHessian,而接口则只需配Action这个公共接口即可
<?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="hessianTestClient"
        class
="org.springframework.remoting.caucho.HessianProxyFactoryBean">
        
<property name="serviceUrl"
            value
="http://127.0.0.1:7008/webRoot/remoting/myHessian" />
        
<property name="serviceInterface" value="com.govdo.action.Action" />
    
</bean>
</beans>
(2)web.xml中加载remoting-client.xml (如果是在main函数中测试,无需配置web.xml)
3、客户端调用测试类TestHessianTest.java
package com.govdo.test.action;

import java.util.Map;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.govdo.action.Action;
import com.govdo.model.QueryCityInfoIn;
import com.govdo.model.QueryCityInfoOut;
import com.govdo.model.ServiceRequest;
import com.govdo.model.ServiceResponse;

public class TestHessianTest {

    
public static void main(String[] args) {
        ClassPathXmlApplicationContext context 
= new ClassPathXmlApplicationContext("remoting-client.xml");
        
try {
            QueryCityInfoIn in 
= new QueryCityInfoIn();
            in.setCityId(
"Shenzhen");
            in.setCityName(
"深圳");
            Action ac 
= (Action)context.getBean("hessianTestClient");
            ServiceRequest serviceRequest 
= new ServiceRequest();
            serviceRequest.setRequestedServiceID(
"hessianTest");
            serviceRequest.setCurrentRequestObject(in);
            ServiceResponse serviceResponse 
= ac.perform(serviceRequest);
            Map model 
= (Map)serviceResponse.getModel();
     
       if (model != null{
                Map resultList 
= (Map)(model.get(ServiceResponse.SERVICE_RESPONSE_RESULT));
                QueryCityInfoOut out 
= (QueryCityInfoOut)(resultList.get(ServiceResponse.BUSINESS_SUCCESS));
                System.out.println(
"CityId:"+out.getCityId()+";CityName:"+out.getCityName());
            }

        }
 catch (Exception e) {
            
// TODO Auto-generated catch block
            e.printStackTrace();
        }


    }

}
运行结果:CityId:Shenzhen;CityName:深圳(by remoting)
这个(by remoting)就是通过服务端程序加的,请回顾上章4(1)节,至此客户端调用实现结束。

六、小结
对于服务端的这种实现方式,有以下优缺点
1、优点
(1)配置简单扩展性好,服务端只需一次配置,客户端即可调用多个实现不同功能的实例,如文章例中的hessianTest是通过serviceRequest.setRequestedServiceID("hessianTest")去获取,也就是说服务端的其他实现了Action接口的bean都可以通过这个方法远程获取并调用
2、缺点
(1)目前经本人测试,hessian的多个版本(包括最老的最新的)都不支持JDK1.6+weblogic11g的Spring配置,而weblogic11g需要依赖JDK1.6以上版本,weblogic8.1不支持1.4以上版本,所以服务端想用泛型就不可能了,本人对泛型情有独钟,本打算出一个Spring+hessian+ibatis的介绍,看来只能分开讲了。
posted on 2011-07-11 21:55 Ciber 阅读(1283) 评论(1)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: