hessian原理分析(二)

来源:互联网 发布:淘宝网禁止黄赌毒 编辑:程序博客网 时间:2024/05/24 05:34

上一篇文章写了一个hessian的入门案例,客户端
HessianProxyFactory factory = new HessianProxyFactory();
try {
HelloHessian helloHessian = (HelloHessian) factory.create(HelloHessian.class, "http://localhost:8080/hessian_web/hessian");
helloHessian.sayHello("hi~~~~~~");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

仅仅有三行重要的代码,那么hessianProxyFactory的作用是什么呢?factory.create的内部实现又是怎么样的呢?,调用sayHello方法里面又是怎么实现的呢?带着这些疑问,接下来我们就一步一步来解决这些谜团
1.hessian客户端访问服务端流程:
hessian的主要结构分为客户端和服务端,中间基于http传输。客户端主要做的就是把对远程调用接口序列化为流,并传输给服务端;而服务端主要是接受客户端的请求,将流反序列化并处理,将结果序列化成流再传输给客户端。下面为流程图:
这里写图片描述
2.hessian是什么呢?
hessian是一种远程通讯协议,它传输的标准格式是二进制文件,而后将二进制文件转化为流(通过序列化方式),以二进制方式传输的方式的好处是可以跨语言进行数据交互,传输便捷,快速
3.HessianProxyFactory通过它的create方法来创建代理类,而这里使用了jdk的动态代理,会自动调用invocationHandler中的invoke方法,HessianProxy实现了InvocationHandler接口
4.接下来就在helloHessian.sayHello(“hi~~~~~~”);
打个断点,然后跟进去,就进入到了invoke方法,

public Object invoke(Object proxy, Method method, Object []args)
throws Throwable
{
String mangleName;

synchronized (_mangleMap) {//_mangleMap里面存放的是接口的方法名  mangleName = _mangleMap.get(method);}if (mangleName == null) {  String methodName = method.getName();  Class []params = method.getParameterTypes();  // equals and hashCode are special cased  if (methodName.equals("equals")  && params.length == 1 && params[0].equals(Object.class)) {Object value = args[0];if (value == null || ! Proxy.isProxyClass(value.getClass()))  return Boolean.FALSE;Object proxyHandler = Proxy.getInvocationHandler(value);if (! (proxyHandler instanceof HessianProxy))  return Boolean.FALSE;HessianProxy handler = (HessianProxy) proxyHandler;return new Boolean(_url.equals(handler.getURL()));  }  else if (methodName.equals("hashCode") && params.length == 0)//下边是校验方法是否是固定的那些,如果是,那么就进行特殊处理return new Integer(_url.hashCode());  else if (methodName.equals("getHessianType"))return proxy.getClass().getInterfaces()[0].getName();  else if (methodName.equals("getHessianURL"))return _url.toString();  else if (methodName.equals("toString") && params.length == 0)return "HessianProxy[" + _url + "]";  if (! _factory.isOverloadEnabled())mangleName = method.getName();  else    mangleName = mangleName(method);  synchronized (_mangleMap) {_mangleMap.put(method, mangleName);//将接口名放入map中  }}InputStream is = null;URLConnection conn = null;HttpURLConnection httpConn = null;try {  if (log.isLoggable(Level.FINER))log.finer("Hessian[" + _url + "] calling " + mangleName);  conn = sendRequest(mangleName, args);//将请求发送给hessian服务端  if (conn instanceof HttpURLConnection) {httpConn = (HttpURLConnection) conn;    int code = 500;    try {      code = httpConn.getResponseCode();//获取响应码    } catch (Exception e) {    }    parseResponseHeaders(conn);//解析响应头部信息    if (code != 200) {      StringBuffer sb = new StringBuffer();      int ch;      try {        is = httpConn.getInputStream();        if (is != null) {          while ((ch = is.read()) >= 0)            sb.append((char) ch);          is.close();        }        is = httpConn.getErrorStream();        if (is != null) {          while ((ch = is.read()) >= 0)            sb.append((char) ch);        }      } catch (FileNotFoundException e) {        throw new HessianConnectionException("HessianProxy cannot connect to '" + _url, e);      } catch (IOException e) {    if (is == null)      throw new HessianConnectionException(code + ": " + e, e);    else      throw new HessianConnectionException(code + ": " + sb, e);      }      if (is != null)        is.close();      throw new HessianConnectionException(code + ": " + sb.toString());    }  }  is = conn.getInputStream();  if (log.isLoggable(Level.FINEST)) {PrintWriter dbg = new PrintWriter(new LogWriter(log));HessianDebugInputStream dIs  = new HessianDebugInputStream(is, dbg);dIs.startTop2();is = dIs;  }  AbstractHessianInput in;  int code = is.read();  if (code == 'H') {int major = is.read();int minor = is.read();in = _factory.getHessian2Input(is);return in.readReply(method.getReturnType());  }  else if (code == 'r') {in = _factory.getHessianInput(is);in.startReply();Object value = in.readObject(method.getReturnType());if (value instanceof InputStream) {  value = new ResultInputStream(httpConn, is, in, (InputStream) value);  is = null;  httpConn = null;}else  in.completeReply();return value;  }  elsethrow new HessianProtocolException("'" + (char) code + "' is an unknown code");} catch (HessianProtocolException e) {  throw new HessianRuntimeException(e);} finally {  try {if (is != null)  is.close();  } catch (Exception e) {log.log(Level.FINE, e.toString(), e);  }  try {if (httpConn != null)  httpConn.disconnect();  } catch (Exception e) {log.log(Level.FINE, e.toString(), e);  }}

}
invoke方法中的最重要的几行代码
conn = sendRequest(mangleName, args);//将请求发送给hessian服务端
这行代码主要是建立与服务端的连接并发送请求给服务端,接着我们就跟进去这个方法

URLConnection conn = null;    conn = _factory.openConnection(_url);//打开与hessian服务器的连接    boolean isValid = false;    try {      // Used chunked mode when available, i.e. JDK 1.5.      if (_factory.isChunkedPost() && conn instanceof HttpURLConnection) {    try {      HttpURLConnection httpConn = (HttpURLConnection) conn;//转成HttpURLConnection      httpConn.setChunkedStreamingMode(8 * 1024);    } catch (Throwable e) {    }      }      addRequestHeaders(conn);//填充请求头部信息      OutputStream os = null;      try {    os = conn.getOutputStream();      } catch (Exception e) {    throw new HessianRuntimeException(e);      }      if (log.isLoggable(Level.FINEST)) {    PrintWriter dbg = new PrintWriter(new LogWriter(log));    os = new HessianDebugOutputStream(os, dbg);      }      AbstractHessianOutput out = _factory.getHessianOutput(os);//获得hessian封装好的输出流      out.call(methodName, args);//里面就是将方法与参数进行序列化      out.flush();      isValid = true;      return conn;    } finally {      if (! isValid && conn instanceof HttpURLConnection)    ((HttpURLConnection) conn).disconnect();    }

接着再跟进out.call(method ,args)方法
int length = args != null ? args.length : 0;

startCall(method, length);//发送连接前准备for (int i = 0; i < length; i++)  writeObject(args[i]);//将参数序列化completeCall();//发送后处理

writeObject(args[i])方法就是讲参数进行序列化,再跟进去看看是如何进行序列化的
if (object == null) {
writeNull();
return;
}

Serializer serializer;serializer = _serializerFactory.getSerializer(object.getClass());//获得序列化工厂serializer.writeObject(object, this);这里获取序列化工厂,在通过序列化实例将参数进行序列化,再跟进去
 switch (code) {    case BOOLEAN:      out.writeBoolean(((Boolean) obj).booleanValue());      break;    case BYTE:    case SHORT:    case INTEGER:      out.writeInt(((Number) obj).intValue());      break;    case LONG:      out.writeLong(((Number) obj).longValue());      break;    case FLOAT:    case DOUBLE:      out.writeDouble(((Number) obj).doubleValue());      break;    case CHARACTER:    case CHARACTER_OBJECT:      out.writeString(String.valueOf(obj));      break;    case STRING:      out.writeString((String) obj);      break;    case DATE:      out.writeUTCDate(((Date) obj).getTime());      break;    case BOOLEAN_ARRAY:    {      if (out.addRef(obj))        return;      boolean []data = (boolean []) obj;      boolean hasEnd = out.writeListBegin(data.length, "[boolean");      for (int i = 0; i < data.length; i++)        out.writeBoolean(data[i]);      if (hasEnd)    out.writeListEnd();      break;    }    case BYTE_ARRAY:    {      byte []data = (byte []) obj;      out.writeBytes(data, 0, data.length);      break;    }    case SHORT_ARRAY:    {      if (out.addRef(obj))        return;      short []data = (short []) obj;      boolean hasEnd = out.writeListBegin(data.length, "[short");      for (int i = 0; i < data.length; i++)        out.writeInt(data[i]);      if (hasEnd)    out.writeListEnd();      break;    }    case INTEGER_ARRAY:    {      if (out.addRef(obj))        return;      int []data = (int []) obj;      boolean hasEnd = out.writeListBegin(data.length, "[int");      for (int i = 0; i < data.length; i++)        out.writeInt(data[i]);      if (hasEnd)    out.writeListEnd();      break;    }    case LONG_ARRAY:    {      if (out.addRef(obj))        return;      long []data = (long []) obj;      boolean hasEnd = out.writeListBegin(data.length, "[long");      for (int i = 0; i < data.length; i++)        out.writeLong(data[i]);      if (hasEnd)    out.writeListEnd();      break;    }    case FLOAT_ARRAY:    {      if (out.addRef(obj))        return;      float []data = (float []) obj;      boolean hasEnd = out.writeListBegin(data.length, "[float");      for (int i = 0; i < data.length; i++)        out.writeDouble(data[i]);      if (hasEnd)    out.writeListEnd();      break;    }    case DOUBLE_ARRAY:    {      if (out.addRef(obj))        return;      double []data = (double []) obj;      boolean hasEnd = out.writeListBegin(data.length, "[double");      for (int i = 0; i < data.length; i++)        out.writeDouble(data[i]);      if (hasEnd)    out.writeListEnd();      break;    }    case STRING_ARRAY:    {      if (out.addRef(obj))        return;      String []data = (String []) obj;      boolean hasEnd = out.writeListBegin(data.length, "[string");      for (int i = 0; i < data.length; i++) {        out.writeString(data[i]);      }      if (hasEnd)    out.writeListEnd();      break;    }    case CHARACTER_ARRAY:    {      char []data = (char []) obj;      out.writeString(data, 0, data.length);      break;    }    case OBJECT_ARRAY:    {      if (out.addRef(obj))        return;      Object []data = (Object []) obj;      boolean hasEnd = out.writeListBegin(data.length, "[object");      for (int i = 0; i < data.length; i++) {        out.writeObject(data[i]);      }      if (hasEnd)    out.writeListEnd();      break;    }    case NULL:      out.writeNull();      break;    default:      throw new RuntimeException(code + " " + String.valueOf(obj.getClass()));    }

以上代码片段就是对参数进行序列化,客户端的源码分析就到这里,服务端的今后会继续更新,由于本人目前水平有限,对序列化原理还处于比较模糊的状态,下面给大家推荐一篇讲解序列化的文章:
http://www.cnblogs.com/redcreen/articles/1955307.html