Hessian学习(二)源码分析HessianServlet



说明

在上篇博文Hessian学习(一)中,初步了解了Hessian,并使用Hessian搭建了一个简单的项目,了解了Hessian如何使用,本文主要学习记录Hessian的实现原理

正文

在使用Hessian时,最重要的就是服务端web.xml中的配置

<servlet>
    <servlet-name>HessianServlet</servlet-name>
    <servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class>
    <init-param>
        <param-name>service-class</param-name>
        <param-value>com.basic.server.impl.HelloImpl</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>HessianServlet</servlet-name>
    <url-pattern>/hessian</url-pattern>
  </servlet-mapping>
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在web.xml中配置了一个Servlet,通过这个Servlet来处理请求,可见Hessian的使用都是围绕着com.caucho.hessian.server.HessianServlet这类来展开

当服务器初始化Servlet时调用Servlet的init()方法,调用service()方法实现服务
通过阅读源码了解Hessian的运行原理

HessianServlet

HessianServlet继承了HttpServlet,在这可以看出Hessian是基于HTTP协议的

public class HessianServlet extends HttpServlet {
 
 
  • 1

重要参数

private Class<?> _homeAPI;   // 服务类的接口
  private Object _homeImpl;  // 服务类的实例

  private Class<?> _objectAPI;  // 不清楚 此参数的意义
  private Object _objectImpl;

  private HessianSkeleton _homeSkeleton; // hsesian服务的代理类,服务端功能的核心
  private HessianSkeleton _objectSkeleton;

  private SerializerFactory _serializerFactory;
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

init(config)方法

初始化时,读取配置文件信息,初始化servlet

在init方法中通过service-class或home-class来获取服务类的实例,通过home-api或api-class来获取服务接口的class对象
当把参数名称换为object-class、object-api时程序无法运行
当把web.xml文件中的service-class替换成object-class时,客户端测试会报错

com.caucho.hessian.client.HessianConnectionException: 500: java.io.IOException: Server returned HTTP response code: 500 for URL:
 
 
  • 1
 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"); // 获取配置文件中名为home-class参数的值

        Class<?> homeClass = loadClass(className); //获得class对象

        _homeImpl = homeClass.newInstance(); //创建实例对象

        init(_homeImpl);
      }
      else if (getInitParameter("service-class") != null) { //获取配置文件中名为service-class参数的值

        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"); //得到配置文件中名为home-api的参数值

        _homeAPI = loadClass(className); // 获取class对象
      }
      else if (getInitParameter("api-class") != null) {
        String className = getInitParameter("api-class"); //得到配置文件中名为api-class的参数值

        _homeAPI = loadClass(className);
      }
      else if (_homeImpl != null) {//当没有配置那两个参数时,会使用服务类实例对象获取class对象
        _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);
    }
  }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100

service(request,response)方法

当客户端请求时,使用service方法来处理请求,在此方法中主要是调用invoke()来处理请求

public void service(ServletRequest request, ServletResponse response)
    throws IOException, ServletException
  {
    HttpServletRequest req = (HttpServletRequest) request; // 强转为HttpServelt 的request和response
    HttpServletResponse res = (HttpServletResponse) response;

    if (! req.getMethod().equals("POST")) {  // 当请求的方法不是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(); // 从http的请求url中获取服务id 
    String objectId = req.getParameter("id"); // 获取参数id
    if (objectId == null)
      objectId = req.getParameter("ejbid");

    ServiceContext.begin(req, res, serviceId, objectId); // 初始化service的上下文

    try {
      InputStream is = request.getInputStream();
      OutputStream os = response.getOutputStream();

      response.setContentType("x-application/hessian");

      SerializerFactory serializerFactory = getSerializerFactory();// 得到序列化的factory

      invoke(is, os, objectId, serializerFactory);// 调用invoke方法处理请求
    } catch (RuntimeException e) {
      throw e;
    } catch (ServletException e) {
      throw e;
    } catch (Throwable e) {
      throw new ServletException(e);
    } finally {
      ServiceContext.end();
    }
  }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

invoke(is, os, objectId, serializerFactory)方法

这里根据objectId是否为null,调用不同对象的invoke方法 ,都是调用的HessianSkeleton的invoke方法 invoke方法中涉及到了hessian的序列化

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);
  }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

在HessianSkeleton的invoke方法中,最终的执行还是调用method的invoke方法

    try {
      result = method.invoke(service, values); // 调用method的invoke方法
    } catch (Exception e) {
      Throwable e1 = e;
      if (e1 instanceof InvocationTargetException)
        e1 = ((InvocationTargetException) e).getTargetException();

      log.log(Level.FINE, this + " " + e1.toString(), e1);

      out.writeFault("ServiceException", 
                     escapeMessage(e1.getMessage()), 
                     e1);
      out.close();
      return;
    }

    // The complete call needs to be after the invoke to handle a
    // trailing InputStream
    in.completeCall();

    out.writeReply(result); // 使用out对象的方法将结果返回给客户端

    out.close();
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

参考博文:https://blog.csdn.net/qq924862077/article/details/52799330

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值