hessian原理解析二(服务端分析)

hessian 服务端源码分析

  我们在回头看看 web.xml 中 servlet 配置

  <servlet>

    <servlet-name>HelloHessian</servlet-name>

    <servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class>

    <init-param>

      <param-name>service-class</param-name>

      <param-value>com.hessian.server.HelloHessianImpl</param-value>

    </init-param>

  </servlet>

  服务端HessianServlet 处理hessian 请求 ,HessianServlet 继承HttpServlet, 每个servlet有两个重要的方法 init 和 service

1、void init(ServletConfig config) 初始化远程服务实现类、远程服务接口类以及HessianSkeleton

a、初始化远程服务实现类, home-class 、service-class

 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);

}

 

b 、初始化远程服务接口

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 = _homeImpl.getClass();

}

 

c 、初始化 HessianSkeleton

_homeSkeleton = new HessianSkeleton(_homeImpl, _homeAPI);

// 取服务类的方法

Method []methodList = apiClass.getMethods()

// 遍历 服务类的方法,放入_methodMap

for (int i = 0; i < methodList.length; i++) {

Method method = methodList[i];

Class []param = method.getParameterTypes();

String mangledName = method.getName() + "__" + param.length;

_methodMap.put(method.getName(), methodList[i]);

_methodMap.put(mangledName, methodList[i]);

_methodMap.put(mangleName(method, false), methodList[i]);

}

hessian 支持重载处理,关键点: 比如对于一个方法 public void sayHello(User user), 那么在_methodMap中会存放三个key sayHello sayHello_1, sayHello_User

 

 

2、service(ServletRequest request, ServletResponse response) 重写父类的service 方法

2.1、 检查请求方式是否为POST

if (! req.getMethod().equals("POST")) {

  res.setStatus(500); //  "Hessian Requires POST"

   return;

}

2.2、获取输入输出流、对象的序列化工厂 执行目标目标服务方法

ServletInputStream e = request.getInputStream();

ServletOutputStream os = response.getOutputStream();

SerializerFactory serializerFactory = this.getSerializerFactory();

hessianSkeleton.invoke(is, os, serializerFactory)

 

hessianServlet 处理请求时序图

 

 

HessianSkeleton invoke 方法解析:

  public void invoke(Object service,AbstractHessianInput in,AbstractHessianOutput out){

  //读取方法调用名

  String methodName = in.readMethod();

  int argLength = in.readMethodArgLength();

  Method method = this.getMethod(methodName + "_" + argLength);

   //读取调用方法参数

   Class[] args = method.getParameterTypes();

   Object[] values = new Object[args.length];

      for(int i= 0; i < args.length; ++i) {

     values[i] = in.readObject(args[i]);

   }

  //执行目标方法调用

     result = method.invoke(service, values)

     //结果输出

    out.writeReply(result);

    out.close();

 

      输出格式:

    

      此处为16进制数表示

      72 01 00 53 00 05 74 69 67 65 72 7A

       r            s              t   i   g    e   r   z 

 

posted @ 2017-01-21 15:07  一天一苹果  阅读(598)  评论(0编辑  收藏  举报