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
- hessian原理分析(二)
- Hessian 原理分析 (二)
- Hessian原理分析
- Hessian原理分析
- Hessian 原理分析
- Hessian 原理分析
- Hessian原理分析
- Hessian 原理分析
- Hessian 原理分析
- Hessian 原理分析
- Hessian 原理分析
- hessian原理分析
- Hessian 原理分析
- Hessian 原理分析
- Hessian 原理分析
- Hessian 原理分析
- Hessian 原理分析
- Hessian 原理分析
- git创建仓库
- Java8函数式编程之三:函数式接口
- 用R进行文本挖掘与分析--软件分词统计词频
- 【模板】二叉搜索树
- git的传输协议及各自优缺点(本地传输协议,ssh,http,git)
- hessian原理分析(二)
- IO口模拟SPI总线问题
- 求利息与本金的和
- HashMap 数据结构 实现原理
- java基础(集合List-ArrayList、LinkedList、Vector的区别)
- Linux命令行六大技巧
- 三周第三次课 2017.11.01 su命令、sudo命令、限制root远程登录
- 扒新闻
- 适合Python初学者的笔记总结【干货】