Hessian源码分析--HessianSkeleton

HessianSkeleton是Hessian的服务端的核心,简单总结来说:HessianSkeleton根据客户端请求的链接,获取到需要执行的接口及实现类,对客户端发送过来的二进制数据进行反序列化,获得需要执行的函数及参数值,然后根据函数和参数值执行具体的函数,接下来对执行的结果进行序列化然后通过连接返回给客户端。

接下来我们按照源码一步一步进行分析,在上一篇博客Hessian源码分析--HessianServlet我们了解到它是调用HessianSkeleton的invoke方法,接下来我们对invoke方法进行分析。

首先获取头类型,这个头类型应该是决定到底是使用那种序列化和反序列函数的,这里对序列化和反序列化不多过多分析。

然后接下来的操作就是调用invoke(_service, in, out)函数了,也没有其他重要的操作了。

public void invoke(InputStream is, OutputStream os,
                     SerializerFactory serializerFactory)
    throws Exception
  {
    HessianInputFactory.HeaderType header = _inputFactory.readHeader(is);

    AbstractHessianInput in;
    AbstractHessianOutput out;

    switch (header) {
    case CALL_1_REPLY_1:
      in = _hessianFactory.createHessianInput(is);
      out = _hessianFactory.createHessianOutput(os);
      break;

    case CALL_1_REPLY_2:
      in = _hessianFactory.createHessianInput(is);
      out = _hessianFactory.createHessian2Output(os);
      break;

    case HESSIAN_2:
      in = _hessianFactory.createHessian2Input(is);
      in.readCall();
      out = _hessianFactory.createHessian2Output(os);
      break;

    default:
      throw new IllegalStateException(header + " is an unknown Hessian call");
    }

    if (serializerFactory != null) {
      in.setSerializerFactory(serializerFactory);
      out.setSerializerFactory(serializerFactory);
    }

    try {
      invoke(_service, in, out);
    } finally {
      in.close();
      out.close();

      if (isDebug)
        os.close();
    }
  }
调用 invoke(_service, in, out)函数实际是调用如下操作,也是没有具体操作

public void invoke(AbstractHessianInput in, AbstractHessianOutput out)
    throws Exception
  {
    invoke(_service, in, out);
  }
接下来调用invoke(_service, in, out)函数是整个服务端的核心了,
首先是获取函数名mehtodName,通过methodName = in.readMethod()反序列化来获得函数名

定义函数对象Method method;

然后根据函数名获得函数对象 method = getMethod(methodName);,这里的函数对象是以函数名为key以对象为value存放到map中去的,这样有利于提高性能

   ServiceContext context = ServiceContext.getContext();

    // backward compatibility for some frameworks that don't read
    // the call type first
    in.skipOptionalCall();

    // Hessian 1.0 backward compatibility
    String header;
    while ((header = in.readHeader()) != null) {
      Object value = in.readObject();

      context.addHeader(header, value);
    }

    String methodName = in.readMethod();
    int argLength = in.readMethodArgLength();

    Method method;

    method = getMethod(methodName + "__" + argLength);

    if (method == null)
      method = getMethod(methodName);
既然都已经拿到函数对象了,当然接下来的操作就是执行客户端要调用的函数了,这也是服务端的关键

method.getParameterTypes获得参数类型

Object []values = new Object[args.length];创建参数对象数组

values[i] = in.readObject(args[i]);反序列化客户端发送过来的参数值

result = method.invoke(service, values); 通过反射调用客户端想要调用的函数,并返回结果。

out.writeReply(result);对结果值进行序列化并发送给客户端,这样整个的RPC的调用过程就结束了。

 <span style="white-space:pre">	</span>Class<?> []args = method.getParameterTypes();

    if (argLength != args.length && argLength >= 0) {
      out.writeFault("NoSuchMethod",
                     escapeMessage("method " + method + " argument length mismatch, received length=" + argLength),
                     null);
      out.close();
      return;
    }

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

    for (int i = 0; i < args.length; i++) {
      // XXX: needs Marshal object
      values[i] = in.readObject(args[i]);
    }

    Object result = null;

    try {
      result = method.invoke(service, values);
    } 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.close();

总结:RPC机制就是客户端发送给服务端想要调用的函数及参数值,服务端通过客户端发送过来的函数和参数值通过反射机制进行函数调用执行,然后将执行结果返回给客户端,这样一个RPC的调用过程结束了。

HessianSkeleton完整源码:

public class HessianSkeleton extends AbstractSkeleton {
  private static final Logger log
    = Logger.getLogger(HessianSkeleton.class.getName());

  private boolean _isDebug;
  
  private HessianInputFactory _inputFactory = new HessianInputFactory();
  private HessianFactory _hessianFactory = new HessianFactory();

  private Object _service;

  /**
   * Create a new hessian skeleton.
   *
   * @param service the underlying service object.
   * @param apiClass the API interface
   */
  public HessianSkeleton(Object service, Class<?> apiClass)
  {
    super(apiClass);

    if (service == null)
      service = this;

    _service = service;

    if (! apiClass.isAssignableFrom(service.getClass()))
      throw new IllegalArgumentException("Service " + service + " must be an instance of " + apiClass.getName());
  }

  /**
   * Create a new hessian skeleton.
   *
   * @param service the underlying service object.
   * @param apiClass the API interface
   */
  public HessianSkeleton(Class<?> apiClass)
  {
    super(apiClass);
  }

  public void setDebug(boolean isDebug)
  {
    _isDebug = isDebug;
  }

  public boolean isDebug()
  {
    return _isDebug;
  }
  
  public void setHessianFactory(HessianFactory factory)
  {
    _hessianFactory = factory;
  }

  /**
   * Invoke the object with the request from the input stream.
   *
   * @param in the Hessian input stream
   * @param out the Hessian output stream
   */
  public void invoke(InputStream is, OutputStream os)
    throws Exception
  {
    invoke(is, os, null);
  }

  /**
   * Invoke the object with the request from the input stream.
   *
   * @param in the Hessian input stream
   * @param out the Hessian output stream
   */
  public void invoke(InputStream is, OutputStream os,
                     SerializerFactory serializerFactory)
    throws Exception
  {
    boolean isDebug = false;

    if (isDebugInvoke()) {
      isDebug = true;

      PrintWriter dbg = createDebugPrintWriter();
      HessianDebugInputStream dIs = new HessianDebugInputStream(is, dbg);
      dIs.startTop2();
      is = dIs;
      HessianDebugOutputStream dOs = new HessianDebugOutputStream(os, dbg);
      dOs.startTop2();
      os = dOs;
    }

    HessianInputFactory.HeaderType header = _inputFactory.readHeader(is);

    AbstractHessianInput in;
    AbstractHessianOutput out;
	//通过头部信息来选择序列化和反序列化方式
    switch (header) {
    case CALL_1_REPLY_1:
      in = _hessianFactory.createHessianInput(is);
      out = _hessianFactory.createHessianOutput(os);
      break;

    case CALL_1_REPLY_2:
      in = _hessianFactory.createHessianInput(is);
      out = _hessianFactory.createHessian2Output(os);
      break;

    case HESSIAN_2:
      in = _hessianFactory.createHessian2Input(is);
      in.readCall();
      out = _hessianFactory.createHessian2Output(os);
      break;

    default:
      throw new IllegalStateException(header + " is an unknown Hessian call");
    }

    if (serializerFactory != null) {
      in.setSerializerFactory(serializerFactory);
      out.setSerializerFactory(serializerFactory);
    }

    try {
      invoke(_service, in, out);
    } finally {
      in.close();
      out.close();

      if (isDebug)
        os.close();
    }
  }

  /**
   * Invoke the object with the request from the input stream.
   *
   * @param in the Hessian input stream
   * @param out the Hessian output stream
   */
  public void invoke(AbstractHessianInput in, AbstractHessianOutput out)
    throws Exception
  {
    invoke(_service, in, out);
  }

  /**
   * Invoke the object with the request from the input stream.
   *
   * @param in the Hessian input stream
   * @param out the Hessian output stream
   */
  public void invoke(Object service,
                     AbstractHessianInput in,
                     AbstractHessianOutput out)
    throws Exception
  {
    ServiceContext context = ServiceContext.getContext();

    // backward compatibility for some frameworks that don't read
    // the call type first
    in.skipOptionalCall();

    // Hessian 1.0 backward compatibility
    String header;
    while ((header = in.readHeader()) != null) {
      Object value = in.readObject();

      context.addHeader(header, value);
    }
	//反序列化获得客户端发送过来的函数名
    String methodName = in.readMethod();
    int argLength = in.readMethodArgLength();

    Method method;
	//从map中获取Method对象
    method = getMethod(methodName + "__" + argLength);

    if (method == null)
      method = getMethod(methodName);

    if (method != null) {
    }
    else if ("_hessian_getAttribute".equals(methodName)) {
      String attrName = in.readString();
      in.completeCall();

      String value = null;

      if ("java.api.class".equals(attrName))
        value = getAPIClassName();
      else if ("java.home.class".equals(attrName))
        value = getHomeClassName();
      else if ("java.object.class".equals(attrName))
        value = getObjectClassName();

      out.writeReply(value);
      out.close();
      return;
    }
    else if (method == null) {
      out.writeFault("NoSuchMethodException",
                     escapeMessage("The service has no method named: " + in.getMethod()),
                     null);
      out.close();
      return;
    }
	//获得参数值类型
    Class<?> []args = method.getParameterTypes();

    if (argLength != args.length && argLength >= 0) {
      out.writeFault("NoSuchMethod",
                     escapeMessage("method " + method + " argument length mismatch, received length=" + argLength),
                     null);
      out.close();
      return;
    }

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

    for (int i = 0; i < args.length; i++) {
      // XXX: needs Marshal object
	  //函数的参数值
      values[i] = in.readObject(args[i]);
    }

    Object result = null;

    try {
	   //反射执行客户端想要执行的函数
      result = method.invoke(service, values);
    } 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.close();
  }
  //以下是和日志相关的,不会影响主流程
  private String escapeMessage(String msg)
  {
    if (msg == null)
      return null;
    
    StringBuilder sb = new StringBuilder();
    
    int length = msg.length();
    for (int i = 0; i < length; i++) {
      char ch = msg.charAt(i);
      
      switch (ch) {
      case '<':
        sb.append("<");
        break;
      case '>':
        sb.append(">");
        break;
      case 0x0:
        sb.append("�");
        break;
      case '&':
        sb.append("&");
        break;
      default:
        sb.append(ch);
        break;
      }
    }
    
    return sb.toString();
  }

  protected boolean isDebugInvoke()
  {
    return (log.isLoggable(Level.FINEST)
            || isDebug() && log.isLoggable(Level.FINE));
  }
  
  
  /**
   * Creates the PrintWriter for debug output. The default is to
   * write to java.util.Logging.
   */
  protected PrintWriter createDebugPrintWriter()
    throws IOException
  {
    return new PrintWriter(new LogWriter(log));
  }

  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()
    {
    }
  }
}





  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值