一、简介
Hessian基于http协议的rpc远程调用协议的实现,采用二进制格式传输的服务框架,比soap web service更轻量、更简单高效。
二、源码分析
Hession通过ThreadLocal保证服务层对象上下文信息线程安全,具体如下代码所示
1. ServiceContext.java类,将服务层对象需要用得到的属性注入到上下文中,采用了多例设计,源码如下
public class ServiceContext {@b@ private static final ThreadLocal<ServiceContext> _localContext@b@ = new ThreadLocal<ServiceContext>();@b@@b@ private ServletRequest _request;@b@ private ServletResponse _response;@b@ private String _serviceName;@b@ private String _objectId;@b@ private int _count;@b@ private HashMap _headers = new HashMap();@b@@b@ private ServiceContext(){}@b@ @b@ /**@b@ * Sets the request object prior to calling the service's method.@b@ *@b@ * @param request the calling servlet request@b@ * @param serviceId the service identifier@b@ * @param objectId the object identifier@b@ */@b@ public static void begin(ServletRequest request,@b@ ServletResponse response,@b@ String serviceName,@b@ String objectId)@b@ throws ServletException@b@ {@b@ ServiceContext context = (ServiceContext) _localContext.get();@b@@b@ if (context == null) {@b@ context = new ServiceContext();@b@ _localContext.set(context);@b@ }@b@@b@ context._request = request;@b@ context._response = response;@b@ context._serviceName = serviceName;@b@ context._objectId = objectId;@b@ context._count++;@b@ }@b@@b@ public static ServiceContext getContext()@b@ {@b@ return (ServiceContext) _localContext.get();@b@ }@b@ @b@ public void addHeader(String header, Object value)@b@ {@b@ _headers.put(header, value);@b@ }@b@ @b@ public Object getHeader(String header)@b@ {@b@ return _headers.get(header);@b@ }@b@@b@...@b@@b@ /**@b@ * Cleanup at the end of a request.@b@ */@b@ public static void end()@b@ {@b@ ServiceContext context = (ServiceContext) _localContext.get();@b@@b@ if (context != null && --context._count == 0) {@b@ context._request = null;@b@ context._response = null;@b@@b@ context._headers.clear();@b@ @b@ _localContext.set(null);@b@ }@b@ }@b@@b@...@b@}
2. 在控制调用HessianServlet中,注入使用,过程如下HessianServlet.java类代码片段
...@b@ @b@ ServiceContext.begin(req, res, serviceId, objectId);//初始化当前调用线程上下文对象@b@@b@ try {@b@ @b@ InputStream is = request.getInputStream();@b@ OutputStream os = response.getOutputStream();@b@ response.setContentType("x-application/hessian");@b@ SerializerFactory serializerFactory = getSerializerFactory();@b@@b@ invoke(is, os, objectId, serializerFactory); //使用上下文对象信息@b@ } catch (RuntimeException e) {@b@ throw e;@b@ } catch (ServletException e) {@b@ throw e;@b@ } catch (Throwable e) {@b@ throw new ServletException(e);@b@ } finally {@b@ ServiceContext.end(); //释放线程内存@b@ }@b@ ...
3. 主服务必须继承父类HessianServlet,在web.xml配置注册servlet子服务类(搜索服务SearchService),如下
<servlet>@b@ <servlet-name>SearchService</servlet-name>@b@ <display-name>SearchRpcService</display-name>@b@ <servlet-class>@b@ com.xwood.search.service.impl.SearchServiceImpl@b@ </servlet-class>@b@ <init-param>@b@ <param-name>home-api</param-name>@b@ <param-value>@b@ com.xwood.search.service.ISearchService@b@ </param-value>@b@ </init-param>@b@ <init-param>@b@ <param-name>home-class</param-name>@b@ <param-value>@b@ com.xwood.search.service.impl.SearchServiceImpl@b@ </param-value>@b@ </init-param>@b@ </servlet>@b@ <servlet-mapping>@b@ <servlet-name>SearchService</servlet-name>@b@ <url-pattern>/search</url-pattern>@b@ </servlet-mapping>
其中必须配置初始化home-api、home-class分别对应服务的接口、实现类(实现类必须继承com.caucho.hessian.server.HessianServlet),这两个配置分别对应HessianServlet源码的初始化方法init中进行类加载,如下所示
package com.caucho.hessian.server;@b@...@b@public class HessianServlet extends GenericServlet@b@{@b@ ...@b@ @b@ public void init(ServletConfig config)@b@ throws ServletException@b@ {@b@ super.init(config);@b@ try@b@ {@b@ String className;@b@ Class homeClass;@b@ if (this._homeImpl != null) break label125:@b@@b@ if (getInitParameter("home-class") != null) {@b@ className = getInitParameter("home-class");@b@ homeClass = loadClass(className);@b@ this._homeImpl = homeClass.newInstance();@b@ init(this._homeImpl);@b@ }else if (getInitParameter("service-class") != null) {@b@ className = getInitParameter("service-class");@b@ homeClass = loadClass(className);@b@ this._homeImpl = homeClass.newInstance();@b@ init(this._homeImpl);@b@ }else {@b@ if (getClass().equals(HessianServlet.class))@b@ throw new ServletException("server must extend HessianServlet");@b@ this._homeImpl = this;@b@ }@b@ if (this._homeAPI != null) label125: break label231:@b@ if (getInitParameter("home-api") != null) {@b@ className = getInitParameter("home-api");@b@ this._homeAPI = loadClass(className);@b@ }else if (getInitParameter("api-class") != null) {@b@ className = getInitParameter("api-class");@b@@b@ this._homeAPI = loadClass(className);@b@ }else if (this._homeImpl != null) {@b@ this._homeAPI = findRemoteAPI(this._homeImpl.getClass());@b@ if (this._homeAPI == null)@b@ this._homeAPI = this._homeImpl.getClass();@b@ }@b@ if (this._objectImpl != null) label231: break label279:@b@@b@ if (getInitParameter("object-class") != null) {@b@ className = getInitParameter("object-class");@b@ Class objectClass = loadClass(className);@b@ this._objectImpl = objectClass.newInstance();@b@ init(this._objectImpl);@b@ }@b@@b@ if (this._objectAPI != null) label279: break label335:@b@ if (getInitParameter("object-api") != null) {@b@ className = getInitParameter("object-api");@b@ this._objectAPI = loadClass(className);@b@ }else if (this._objectImpl != null) {@b@ this._objectAPI = this._objectImpl.getClass();@b@ }@b@ label335: this._homeSkeleton = new HessianSkeleton(this._homeImpl, this._homeAPI);@b@ if (this._objectAPI != null)@b@ this._homeSkeleton.setObjectClass(this._objectAPI);@b@ if (this._objectImpl != null) {@b@ this._objectSkeleton = new HessianSkeleton(this._objectImpl, this._objectAPI);@b@ this._objectSkeleton.setHomeClass(this._homeAPI);@b@ }else {@b@ this._objectSkeleton = this._homeSkeleton;@b@ }@b@ if ("true".equals(getInitParameter("debug")))@b@ this._isDebug = true;@b@@b@ if ("false".equals(getInitParameter("send-collection-type")))@b@ setSendCollectionType(false);@b@ } catch (ServletException e) {@b@ throw e;@b@ } catch (Exception e) {@b@ throw new ServletException(e);@b@ }@b@ }@b@...@b@ }@b@}
三、相关下载
hessian-4.0.7.jar,点击下载,如需要下载其他更多版本
<dependency>@b@ <groupId>hessian</groupId>@b@ <artifactId>hessian</artifactId>@b@ <version>3.0.20</version>@b@</dependency>
spring-2.0.8.jar(org.springframework.remoting.caucho.HessianProxyFactoryBean),点击下载,源码下载,源码视图链接
git源码分享,点击浏览
hessian简单项目实例(包含依赖包&完整源码),点击下载