zoukankan      html  css  js  c++  java
  • Hessian总结

    一、简介:

    Hessian是一个基于Binary-RPC 实现的远程通讯library,基于 Http 协议进行传输。通过其自定义的串行化机制将请求信息进行序列化,产生二进制流。响应端根据 Hessian 提供的 API 来接收请求,根据其私有的串行化机制来将请求信息进行反序列化,传递给使用者时已是相应的请求信息对象了。处理完毕后直接返回,hessian 将结果对象进行序列化,传输至调用端。

    一次完整的调用如下图所示:

     

    二、Demo:

    1. 服务端:

    l  首先建立web工程,引入Hessian的jar包;

    l  接着定义接口:

    public interface HelloService {

           public String sayHello(String name);

    }

    l  然后实现接口:

    public class HelloServiceImpl extends HessianServlet implements HelloService {

           @Override

           public String sayHello(String name) {

                  return "Hello :"+name;

           }

    }

    2.客户端:

    public static void main(String[] args) throws MalformedURLException {

          

           String url="http://localhost:8080/myserver/hello";

        HessianProxyFactory hessianProxyFactory = new HessianProxyFactory();

        // 创建接口代理程序

        HelloService proxy = (HelloService) hessianProxyFactory.create(HelloService.class, url);

        String result = proxy.sayHello("test");

        System.out.println(result);

          

    }

    三、客户端流程分析:

     

    1、客户端首先通过HessianProxyFactory创建HessianProxy对象,也就是使用动态代理调用服务的方法的代理对象;

    2、在HessianProxy对象中缓存Method和MethodName的hash表,invoke方法中首先根据Method在hash表查找对应的MethodName,如果找到则直接使用缓存,如果未找到则根据Method读出MethodName,并缓存到hash表中;

    3、HessianProxy.invoke方法中主要调用sendRequest调用远程对象,首先通过addRequestHeaders添加Http协议头信息,获取远程服务器的HessianConnection对象,然后通过AbstractHessianOutput.Call将调用方法和参数序列化为二进制,最后通过HessianConnection. sendRequest将调用信息发送到远端服务器;

    4、AbstractHessianOutput.Call序列化调用信息时,startCall在二进制流里面写入起始标记“c”、版本信息以及长度等信息,然后调用Serializer对象将调用方法和参数进行序列化,最后通过写入结束标记“z”完成二进制流的序列化;

    四、服务器端流程分析:

     

    1、HessianSkeleton是hessian server端的核心类,从输入流中返序列化出客户端调用的方法和参数,对服务端服务进行调用,然后把处理结果返回给客户端;

    2、HessianSkeleton.invoke首先调用AbstractHessianInput.readObject读出调用方法名和参数信息,并根据这个信息从service中查找到对应的Method对象;

    String methodName = in.readMethod();

    int argLength = in.readMethodArgLength();

    Method method;

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

    if (method == null)

      method = getMethod(methodName);

    其中getMethod是从一个_methodMap的hash表中查找Method对象,而_methodMap表在服务类对象的构造函数中就已经完成了Method对象和方法名的映射:

    protected AbstractSkeleton(Class apiClass)

    {

      _apiClass = apiClass;

      Method []methodList = apiClass.getMethods();

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

        Method method = methodList[i];

        if (_methodMap.get(method.getName()) == null)

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

      }

    }

    3、接下来读取参数值是调用的AbstractHessianInput.readObject读取的,而这个读取又是调用的Deserializer对象的readObject读取的,其读取方法(反序列化)与客户端的序列化格式是一一对应的;

    4、将调用方法名和参数值都反序列化出来后,接下来就通过动态代理调用Service服务的对应方法,将其返回值使用writeReply进行序列化后返回给调用客户端:

    public void writeReply(Object o) throws IOException

    {

      startReply();

      writeObject(o);

      completeReply();

    }

    其中的startReply和completeReply分别在二进制流里面写入起始标记和结束标记,writeObject将返回值序列化到二进制流里面;

  • 相关阅读:
    wpf button的mouse(leftbutton)down/up,click事件不响应解决办法
    多线程引发OutOfMemoryException
    WINDBUG常用命令
    有关OEP脱壳
    reversing.kr easykeygen 之wp
    reversing.kr easy crack 之write up
    pwnable.kr leg之write up
    pwnable input2 之 write up
    pwnable.kr random 之 write up
    pwnable.kr 之 passcode write up
  • 原文地址:https://www.cnblogs.com/laoxia/p/8620776.html
Copyright © 2011-2022 走看看