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的更多相关文章

  1. Hessian源码分析--HessianSkeleton

    HessianSkeleton是Hessian的服务端的核心,简单总结来说:HessianSkeleton根据客户端请求的链接,获取到需要执行的接口及实现类,对客户端发送过来的二进制数据进行反序列化, ...

  2. Hessian源码分析--HessianProxy

    在上一篇博客 Hessian源码分析--HessianProxyFactory 中我们了解到,客户端获得的对象其实是HessianProxy生成的目标对象,当调用目标对象的方法时,会调用Hessian ...

  3. Hessian源码分析--总体架构

    Hessian是一个轻量级的remoting onhttp工具,使用简单的方法提供了RMI的功能. 相比WebService,Hessian更简单.快捷.采用的是二进制RPC协议,因为采用的是二进制协 ...

  4. (转)hessian源码分析(一)------架构

    在计费中心的对外交互这块采用了hessian,有必要对hessian的运行机理和源码做一定的解析. 大致翻了翻源码后,发现hessian的主要结构分客户端与服务端,中间基于http传输.客户端主要做的 ...

  5. Hessian源码分析--HessianProxyFactory

    HessianProxyFactory是HessianProxy的工厂类,其通过HessianProxy来生成代理类. 如下面代码: HessianProxyFactory factory = new ...

  6. SURF算法与源码分析、下

    上一篇文章 SURF算法与源码分析.上 中主要分析的是SURF特征点定位的算法原理与相关OpenCV中的源码分析,这篇文章接着上篇文章对已经定位到的SURF特征点进行特征描述.这一步至关重要,这是SU ...

  7. Dubbo 源码分析 - 服务引用

    1. 简介 在上一篇文章中,我详细的分析了服务导出的原理.本篇文章我们趁热打铁,继续分析服务引用的原理.在 Dubbo 中,我们可以通过两种方式引用远程服务.第一种是使用服务直联的方式引用服务,第二种 ...

  8. 【OpenCV】SIFT原理与源码分析:关键点搜索与定位

    <SIFT原理与源码分析>系列文章索引:http://www.cnblogs.com/tianyalu/p/5467813.html 由前一步<DoG尺度空间构造>,我们得到了 ...

  9. 12.源码分析—如何为SOFARPC写一个序列化?

    SOFARPC源码解析系列: 1. 源码分析---SOFARPC可扩展的机制SPI 2. 源码分析---SOFARPC客户端服务引用 3. 源码分析---SOFARPC客户端服务调用 4. 源码分析- ...

随机推荐

  1. C语言第二次作业 ,

    一:修改错题 1输出带框文字:在屏幕上输出以下3行信息. 将源代码输入编译器 运行程序发现错误 错误信息1: 错误原因:将stido.h拼写错误 改正方法:将stido.h改为stdio.h 错误信息 ...

  2. Gradle--初识

    1.Eclipse从svn导入Gradle项目 1.检出项目的时候不要选新项目,选"做为工作空间中的项目检出",然后点Finish. 2.将项目转为Gradle项目,右键导入的项目 ...

  3. 分布式锁的几种使用方式(redis、zookeeper、数据库)

    Q:一个业务服务器,一个数据库,操作:查询用户当前余额,扣除当前余额的3%作为手续费 synchronized lock db lock Q:两个业务服务器,一个数据库,操作:查询用户当前余额,扣除当 ...

  4. 使用webpack-dev-server设置反向代理解决前端跨域问题

    webpack-dev-server是一个小型的Node.js Express服务器,它使用webpack-dev-middleware来服务于webpack的包,除此自外,它还有一个通过Sock.j ...

  5. 使用 OpenCV 与 Face++ 人脸识别

    今天看到一篇文章<使用 OpenCV 与 Face++ 实现人脸解锁>,感觉挺好玩,就照着作者的讲解,写了一下.详细内容还请看原作者文章. # *^_^* coding:utf-8 *^_ ...

  6. Linux下使用MD5加密BASE64加密

    这里以字符串123456为例子,它的md5密文值为:e10adc3949ba59abbe56e057f20f883e 这里以1.txt为需要被加密的文件. 一. 用oppnssl md5 加密字符串和 ...

  7. 用python爬了自己的微信,原来好友都是这样的!

    偶然了解到Python里的itchat包,它已经完成了wechat的个人账号API接口,使爬取个人微信信息更加方便.鉴于自己很早之前就想知道诸如自己微信好友性别比例都来自哪个城市之类的问题,于是乎玩心 ...

  8. lglob-lua 静态检查脚本

    ./lglob ~/ngx/lualib/mvc/*.lua 2>&1 | grep ' set '

  9. Unity发布至IOS的流程(踩坑记录)

    这篇文章主要用于记录本人亲身经历过的Unity发布到IOS平台所遇到的所有坑(其实也就是一些自己并不明白的强制设定),以便于后续再有类似需求时少走些弯路. 我的环境: Unity 5.2.2 个人版( ...

  10. Android简易实战教程--第三十话《撕衣美女》

    此篇邪恶一些,给单身屌丝发点"福利",通过图片的绘制,给美女脱掉衣服. 原理:图片覆盖图片,通过画笔对顶端的图片做一些特效处理,即手指触摸的地方,设置为透明.即可显示最底部的美女图 ...