Hessian源码分析--HessianServlet
Hessian可以通过Servlet来对外暴露服务,HessianServlet继承于HttpServlet,但这仅仅是一个外壳,使用web服务器来提供对外的Http请求,在web.xml中我们会进行如下配置,其实就是一个简单的servlet配置,不过是增加了两个属性的配置home-class和home-api,这两个配置其实就是用来调用真正的接口及实现类的:
<servlet> <servlet-name>hessian-service</servlet-name> <servlet-class> com.caucho.hessian.server.HessianServlet </servlet-class> <init-param> <param-name>home-class</param-name> <param-value> <!-- 服务实现类 --> com.tianjunwei.hessian.server.HelloServiceImpl </param-value> </init-param> <init-param> <param-name>home-api</param-name> <!-- 服务接口 --> <param-value>com.tianjunwei.hessian.server.HelloService</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>hessian-service</servlet-name> <url-pattern>/hessian</url-pattern> </servlet-mapping>
HessianServlet在初始化时会调用init函数来获得home-api和home-class
if (_homeImpl != null) { } else if (getInitParameter("home-class") != null) { String className = getInitParameter("home-class"); Class<?> homeClass = loadClass(className); _homeImpl = homeClass.newInstance(); init(_homeImpl); } else if (getInitParameter("service-class") != null) { String className = getInitParameter("service-class"); Class<?> homeClass = loadClass(className); _homeImpl = homeClass.newInstance(); init(_homeImpl); } else { if (getClass().equals(HessianServlet.class)) throw new ServletException("server must extend HessianServlet"); _homeImpl = this; }
获取home-class和home-api的目的是作为参数去创建HessianSkeleton,它才是服务端的实现中点
_homeSkeleton = new HessianSkeleton(_homeImpl, _homeAPI);
当Servlet调用初始化函数init之后,其最主要的目的就是根据配置信息来初始化HessianSkeleton
当客户端通过http请求到对外暴露的服务端时,接下来要执行的是Servlet的service函数,
service函数的实现还是很简单的,首先判断请求是否是post请求,如果不是则直接返回错误信息
接下来就是一些参数的获取,最终要的是执行invoke(is, os, objectId, serializerFactory)函数
public void service(ServletRequest request, ServletResponse response) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; //Hessian需要调用需要POST请求才可以 if (! req.getMethod().equals("POST")) { res.setStatus(500); // , "Hessian Requires POST"); PrintWriter out = res.getWriter(); res.setContentType("text/html"); out.println("<h1>Hessian Requires POST</h1>"); return; } String serviceId = req.getPathInfo(); String objectId = req.getParameter("id"); if (objectId == null) objectId = req.getParameter("ejbid"); ServiceContext.begin(req, res, serviceId, objectId); try { InputStream is = request.getInputStream(); OutputStream os = response.getOutputStream(); response.setContentType("x-application/hessian"); SerializerFactory serializerFactory = getSerializerFactory(); invoke(is, os, objectId, serializerFactory); } catch (RuntimeException e) { throw e; } catch (ServletException e) { throw e; } catch (Throwable e) { throw new ServletException(e); } finally { ServiceContext.end(); } }
对于invoke(is, os, objectId, serializerFactory)的执行也是很简单的,其实就是在调用初始化的
HessianSkeleton类的invoke函数,这样HessianServlet的任务就完成了。
protected void invoke(InputStream is, OutputStream os, String objectId, SerializerFactory serializerFactory) throws Exception { if (objectId != null) _objectSkeleton.invoke(is, os, serializerFactory); else _homeSkeleton.invoke(is, os, serializerFactory); }
HessianServlet的完整源码如下:
public class HessianServlet extends HttpServlet { private Class<?> _homeAPI; private Object _homeImpl; private Class<?> _objectAPI; private Object _objectImpl; private HessianSkeleton _homeSkeleton; private HessianSkeleton _objectSkeleton; private SerializerFactory _serializerFactory; public HessianServlet() { } public String getServletInfo() { return "Hessian Servlet"; } /** * Sets the home api. */ public void setHomeAPI(Class<?> api) { _homeAPI = api; } /** * Sets the home implementation */ public void setHome(Object home) { _homeImpl = home; } /** * Sets the object api. */ public void setObjectAPI(Class<?> api) { _objectAPI = api; } /** * Sets the object implementation */ public void setObject(Object object) { _objectImpl = object; } /** * Sets the service class. */ public void setService(Object service) { setHome(service); } /** * Sets the api-class. */ public void setAPIClass(Class<?> api) { setHomeAPI(api); } /** * Gets the api-class. */ public Class<?> getAPIClass() { return _homeAPI; } /** * Sets the serializer factory. */ public void setSerializerFactory(SerializerFactory factory) { _serializerFactory = factory; } /** * Gets the serializer factory. */ public SerializerFactory getSerializerFactory() { if (_serializerFactory == null) _serializerFactory = new SerializerFactory(); return _serializerFactory; } /** * Sets the serializer send collection java type. */ public void setSendCollectionType(boolean sendType) { getSerializerFactory().setSendCollectionType(sendType); } /** * Sets the debugging flag. */ public void setDebug(boolean isDebug) { } /** * Sets the debugging log name. */ public void setLogName(String name) { // _log = Logger.getLogger(name); } /** * Initialize the service, including the service object. */ public void init(ServletConfig config) throws ServletException { super.init(config); try { if (_homeImpl != null) { } else if (getInitParameter("home-class") != null) { String className = getInitParameter("home-class"); Class<?> homeClass = loadClass(className); _homeImpl = homeClass.newInstance(); init(_homeImpl); } else if (getInitParameter("service-class") != null) { String className = getInitParameter("service-class"); Class<?> homeClass = loadClass(className); _homeImpl = homeClass.newInstance(); init(_homeImpl); } else { if (getClass().equals(HessianServlet.class)) throw new ServletException("server must extend HessianServlet"); _homeImpl = this; } if (_homeAPI != null) { } else if (getInitParameter("home-api") != null) { String className = getInitParameter("home-api"); _homeAPI = loadClass(className); } else if (getInitParameter("api-class") != null) { String className = getInitParameter("api-class"); _homeAPI = loadClass(className); } else if (_homeImpl != null) { _homeAPI = findRemoteAPI(_homeImpl.getClass()); if (_homeAPI == null) _homeAPI = _homeImpl.getClass(); _homeAPI = _homeImpl.getClass(); } if (_objectImpl != null) { } else if (getInitParameter("object-class") != null) { String className = getInitParameter("object-class"); Class<?> objectClass = loadClass(className); _objectImpl = objectClass.newInstance(); init(_objectImpl); } if (_objectAPI != null) { } else if (getInitParameter("object-api") != null) { String className = getInitParameter("object-api"); _objectAPI = loadClass(className); } else if (_objectImpl != null) _objectAPI = _objectImpl.getClass(); _homeSkeleton = new HessianSkeleton(_homeImpl, _homeAPI); if (_objectAPI != null) _homeSkeleton.setObjectClass(_objectAPI); if (_objectImpl != null) { _objectSkeleton = new HessianSkeleton(_objectImpl, _objectAPI); _objectSkeleton.setHomeClass(_homeAPI); } else _objectSkeleton = _homeSkeleton; if ("true".equals(getInitParameter("debug"))) { } if ("false".equals(getInitParameter("send-collection-type"))) setSendCollectionType(false); } catch (ServletException e) { throw e; } catch (Exception e) { throw new ServletException(e); } } private Class<?> findRemoteAPI(Class<?> implClass) { // hessian/34d0 return null; /* if (implClass == null || implClass.equals(GenericService.class)) return null; Class []interfaces = implClass.getInterfaces(); if (interfaces.length == 1) return interfaces[0]; return findRemoteAPI(implClass.getSuperclass()); */ } private Class<?> loadClass(String className) throws ClassNotFoundException { ClassLoader loader = getContextClassLoader(); if (loader != null) return Class.forName(className, false, loader); else return Class.forName(className); } protected ClassLoader getContextClassLoader() { return Thread.currentThread().getContextClassLoader(); } private void init(Object service) throws ServletException { if (! this.getClass().equals(HessianServlet.class)) { } else if (service instanceof Service) ((Service) service).init(getServletConfig()); else if (service instanceof Servlet) ((Servlet) service).init(getServletConfig()); } /** * Execute a request. The path-info of the request selects the bean. * Once the bean's selected, it will be applied. */ public void service(ServletRequest request, ServletResponse response) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; //Hessian需要调用需要POST请求才可以 if (! req.getMethod().equals("POST")) { res.setStatus(500); // , "Hessian Requires POST"); PrintWriter out = res.getWriter(); res.setContentType("text/html"); out.println("<h1>Hessian Requires POST</h1>"); return; } String serviceId = req.getPathInfo(); String objectId = req.getParameter("id"); if (objectId == null) objectId = req.getParameter("ejbid"); ServiceContext.begin(req, res, serviceId, objectId); try { InputStream is = request.getInputStream(); OutputStream os = response.getOutputStream(); response.setContentType("x-application/hessian"); SerializerFactory serializerFactory = getSerializerFactory(); //其实就是在调用HessianSkeleton的invoke方法 invoke(is, os, objectId, serializerFactory); } catch (RuntimeException e) { throw e; } catch (ServletException e) { throw e; } catch (Throwable e) { throw new ServletException(e); } finally { ServiceContext.end(); } } //实现机制就是调用HessianSkeleton的invoke方法 protected void invoke(InputStream is, OutputStream os, String objectId, SerializerFactory serializerFactory) throws Exception { if (objectId != null) _objectSkeleton.invoke(is, os, serializerFactory); else _homeSkeleton.invoke(is, os, serializerFactory); } protected Hessian2Input createHessian2Input(InputStream is) { return new Hessian2Input(is); } static class LogWriter extends Writer { private Logger _log; private StringBuilder _sb = new StringBuilder(); LogWriter(Logger log) { _log = log; } public void write(char ch) { if (ch == '\n' && _sb.length() > 0) { _log.fine(_sb.toString()); _sb.setLength(0); } else _sb.append((char) ch); } public void write(char []buffer, int offset, int length) { for (int i = 0; i < length; i++) { char ch = buffer[offset + i]; if (ch == '\n' && _sb.length() > 0) { _log.fine(_sb.toString()); _sb.setLength(0); } else _sb.append((char) ch); } } public void flush() { } public void close() { } } }
Hessian源码分析--HessianServlet的更多相关文章
- Hessian源码分析--HessianSkeleton
HessianSkeleton是Hessian的服务端的核心,简单总结来说:HessianSkeleton根据客户端请求的链接,获取到需要执行的接口及实现类,对客户端发送过来的二进制数据进行反序列化, ...
- Hessian源码分析--HessianProxy
在上一篇博客 Hessian源码分析--HessianProxyFactory 中我们了解到,客户端获得的对象其实是HessianProxy生成的目标对象,当调用目标对象的方法时,会调用Hessian ...
- Hessian源码分析--总体架构
Hessian是一个轻量级的remoting onhttp工具,使用简单的方法提供了RMI的功能. 相比WebService,Hessian更简单.快捷.采用的是二进制RPC协议,因为采用的是二进制协 ...
- (转)hessian源码分析(一)------架构
在计费中心的对外交互这块采用了hessian,有必要对hessian的运行机理和源码做一定的解析. 大致翻了翻源码后,发现hessian的主要结构分客户端与服务端,中间基于http传输.客户端主要做的 ...
- Hessian源码分析--HessianProxyFactory
HessianProxyFactory是HessianProxy的工厂类,其通过HessianProxy来生成代理类. 如下面代码: HessianProxyFactory factory = new ...
- SURF算法与源码分析、下
上一篇文章 SURF算法与源码分析.上 中主要分析的是SURF特征点定位的算法原理与相关OpenCV中的源码分析,这篇文章接着上篇文章对已经定位到的SURF特征点进行特征描述.这一步至关重要,这是SU ...
- Dubbo 源码分析 - 服务引用
1. 简介 在上一篇文章中,我详细的分析了服务导出的原理.本篇文章我们趁热打铁,继续分析服务引用的原理.在 Dubbo 中,我们可以通过两种方式引用远程服务.第一种是使用服务直联的方式引用服务,第二种 ...
- 【OpenCV】SIFT原理与源码分析:关键点搜索与定位
<SIFT原理与源码分析>系列文章索引:http://www.cnblogs.com/tianyalu/p/5467813.html 由前一步<DoG尺度空间构造>,我们得到了 ...
- 12.源码分析—如何为SOFARPC写一个序列化?
SOFARPC源码解析系列: 1. 源码分析---SOFARPC可扩展的机制SPI 2. 源码分析---SOFARPC客户端服务引用 3. 源码分析---SOFARPC客户端服务调用 4. 源码分析- ...
随机推荐
- sql的left join 、right join 、inner join之间的区别
sql中left join .right join .inner join之间的区别 left join (左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 : right join (右 ...
- day4 liaoxuefeng---函数式编程
一.概述: 函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数! Python对函数式编程提供部分支持.由于Python允许使用变量,因此,Python不是纯函数式编程 ...
- 第四节基础篇 - SELECT 语句详解
4.1 基本的SELECT语句 select * from T_WEATHER select cityname from t_weather 4.2 数学符号条件(>.<.>=.&l ...
- curl_multi实现并发
普通请求 curl_normal.php <?php $srart_time = microtime(TRUE); $chArr=[]; //创建多个cURL资源 for($i=0; $i< ...
- 算法导轮之B树的学习
最近学习了算法导轮里B树相关的知识,在此写一篇博客作为总结. 1.引言 B树是为磁盘或其他直接存取的辅助存储设备而设计的一种平衡搜索树.B树类似于红黑树,但它与红黑树最大不同之处在于B树的节点可以拥有 ...
- 阿里云部署Node.js项目(CentOS)
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,用来方便地搭建快速的易于扩展的网络应用.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又 ...
- Docker安装tomcat和部署项目
随着微服务的流行,Docker越来越流行,正如它的理念"Build, Ship, and Run Any App, Anywhere"一样,Docker提供的容器隔离技术使得开发人 ...
- WPF 窗口居中 & 变更触发机制
窗口居中 & 变更触发机制 解决: 1.单实例窗口,窗口每次隐藏后再显示时,位置居中显示 2.多屏幕下单实例窗口,当父窗口移动到其它屏幕时,单实例窗口再次弹出时,位置才更新到父窗口屏幕. 3. ...
- linux shell数组
from: http://www.jb51.net/article/34322.htm bash shell只支持一维数组,但参数个数没有限制. 声明一个数组:declare -a array(其实不 ...
- C++ substr
函数文档:http://www.cplusplus.com/reference/string/string/substr/ /* substr(size_t pos = 0,size_t len = ...