hessian原理服务端源码分析(三)
2017-11-02 13:49
316 查看
上一篇文章分析了hessian客户端的源码,其实服务端的源码分析与客户端的差不多,只是服务端是先接收客户端的请求,将请求参数进行反序列化,再处理,将结果序列化转换成流返回给客户端,由于有了客户端源码分析,其他的就不多说了,直接上代码
1.为了能够跟进hessian服务端的源码,首先我们需要将导入hessian的jar包替换成源码,下面是我导入hessian源码的目录结构:
![](https://img-blog.csdn.net/20171102112049290?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHVpeW9uZ196aG91/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
2.根据我们在hessian web中的web.xml配置的hessian servlet可知,接收客户端的请求是从HessianServlet中的service方法开始的,那么我们就在这个方法里面打个断点
调试的快捷方式:
F5进入方法 F6往下执行 F8到达下一个断点
下面是service方法中的代码
我就把里面重要的几行代码单拿出来
if (major >= 2)//用来设置成hessian自己封装的输出流
out = new Hessian2Output(os);
else
out = new HessianOutput(os);
}
in = new HessianInput(is);//获取hessian自己封装的输入流
SerializerFactory serializerFactory = getSerializerFactory();//获得序列化工厂将得到的流反序列化
in.setSerializerFactory(serializerFactory);
out.setSerializerFactory(serializerFactory);
然后
if (objectId != null)
_objectSkeleton.invoke(in, out);//处理请求
else
_homeSkeleton.invoke(in, out);//处理请求
处理请求就交给了HessianSkeleton类,调用其中的invoke方法
继续跟进invoke方法
3.invoke方法代码:
再跟进readObject(Class cl)方法,看看里面是如何将得到的流反序列化的
_serializerFactory.getDeserializer(cl).readObject(this);获取反序列化工厂,并进行反序列化,再跟进这个方法看看
这部分代码就是将得到的流进行反序列化,而后再进行处理,将结果序列化返回到客户端,源码就分析到这里,由于本人水平有限,如果以上解析有误的地方,请留言
1.为了能够跟进hessian服务端的源码,首先我们需要将导入hessian的jar包替换成源码,下面是我导入hessian源码的目录结构:
2.根据我们在hessian web中的web.xml配置的hessian servlet可知,接收客户端的请求是从HessianServlet中的service方法开始的,那么我们就在这个方法里面打个断点
调试的快捷方式:
F5进入方法 F6往下执行 F8到达下一个断点
下面是service方法中的代码
HttpServletRequest req = (HttpServletRequest) request;//转换成httpServletRequest HttpServletResponse res = (HttpServletResponse) response; if (! req.getMethod().equals("POST")) {//判断请求方法是不是post方法 res.setStatus(500, "Hessian Requires POST"); PrintWriter out = res.getWriter(); res.setContentType("text/html"); out.println("<h1>Hessian Requires POST</h1>"); return; } String serviceId = req.getPathInfo(); String objectId = req.getParameter("id"); if (objectId == null) objectId = req.getParameter("ejbid"); ServiceContext.begin(req, serviceId, objectId); try { InputStream is = request.getInputStream(); OutputStream os = response.getOutputStream(); response.setContentType("application/x-hessian");//设置请求类型 if (_log.isLoggable(Level.FINEST) || _isDebug && _log.isLoggable(Level.FINE)) { PrintWriter dbg = new PrintWriter(new LogWriter(_log)); HessianDebugInputStream dIs = new HessianDebugInputStream(is, dbg); dIs.startTop2(); is = dIs; HessianDebugOutputStream dOs = new HessianDebugOutputStream(os, dbg); dOs.startTop2(); os = dOs; } int code = is.read(); int major; int minor; AbstractHessianInput in; AbstractHessianOutput out; if (code == 'H') { major = is.read(); minor = is.read(); if (major != 0x02 || minor != 0x00) throw new IOException("Version " + major + "." + minor + " is not understood"); in = createHessian2Input(is); out = new Hessian2Output(os); in.readCall(); } else if (code == 'c') { major = is.read(); minor = is.read(); in = new HessianInput(is);//获取hessian自己封装的输入流 if (major >= 2) out = new Hessian2Output(os); else out = new HessianOutput(os); } else { // XXX: deflate throw new IOException("expected 'H' (Hessian 2.0) or 'c' (Hessian 1.0) in hessian input at " + code); } SerializerFactory serializerFactory = getSerializerFactory();//获得序列化工厂将得到的流反序列化 in.setSerializerFactory(serializerFactory); out.setSerializerFactory(serializerFactory); if (objectId != null) _objectSkeleton.invoke(in, out);//处理请求 else _homeSkeleton.invoke(in, out);//处理请求 out.close(); } catch (RuntimeException e) { throw e; } catch (ServletException e) { throw e; } catch (Throwable e) { throw new ServletException(e); } finally { ServiceContext.end(); }
我就把里面重要的几行代码单拿出来
if (major >= 2)//用来设置成hessian自己封装的输出流
out = new Hessian2Output(os);
else
out = new HessianOutput(os);
}
in = new HessianInput(is);//获取hessian自己封装的输入流
SerializerFactory serializerFactory = getSerializerFactory();//获得序列化工厂将得到的流反序列化
in.setSerializerFactory(serializerFactory);
out.setSerializerFactory(serializerFactory);
然后
if (objectId != null)
_objectSkeleton.invoke(in, out);//处理请求
else
_homeSkeleton.invoke(in, out);//处理请求
处理请求就交给了HessianSkeleton类,调用其中的invoke方法
继续跟进invoke方法
3.invoke方法代码:
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); if (method == null) { out.writeFault("NoSuchMethodException", "The service has no method named: " + in.getMethod(), null); out.close(); return; } 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; } Class []args = method.getParameterTypes(); if (argLength != args.length && argLength >= 0) { out.writeFault("NoSuchMethod", "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++) { values[i] = in.readObject(args[i]);//将参数反序列化 } Object result = null; try { result = method.invoke(service, values);//处理并返回结果 } catch (Throwable e) { if (e instanceof InvocationTargetException) e = ((InvocationTargetException) e).getTargetException(); log.log(Level.FINE, this + " " + e.toString(), e); out.writeFault("ServiceException", e.getMessage(), e); out.close(); return; } // The complete call needs to be after the invoke to handle a // trailing InputStream in.completeCall();//将结果序列化之前的准备 out.writeReply(result);//将结果序列化并返回给客户端 out.close();//关闭资源 }
再跟进readObject(Class cl)方法,看看里面是如何将得到的流反序列化的
if (cl == null || cl == Object.class) return readObject(); int tag = read(); switch (tag) { case 'N': return null; case 'M': { String type = readType(); // hessian/3386 if ("".equals(type)) { Deserializer reader; reader = _serializerFactory.getDeserializer(cl); return reader.readMap(this); } else { Deserializer reader; reader = _serializerFactory.getObjectDeserializer(type); return reader.readMap(this); } } case 'V': { String type = readType(); int length = readLength(); Deserializer reader; reader = _serializerFactory.getObjectDeserializer(type); if (cl != reader.getType() && cl.isAssignableFrom(reader.getType())) return reader.readList(this, length); reader = _serializerFactory.getDeserializer(cl); Object v = reader.readList(this, length); return v; } case 'R': { int ref = parseInt(); return _refs.get(ref); } case 'r': { String type = readType(); String url = readString(); return resolveRemote(type, url); } } _peek = tag; // hessian/332i vs hessian/3406 //return readObject(); Object value = _serializerFactory.getDeserializer(cl).readObject(this); return value;
_serializerFactory.getDeserializer(cl).readObject(this);获取反序列化工厂,并进行反序列化,再跟进这个方法看看
public Object readObject(AbstractHessianInput in) throws IOException { switch (_code) { case NULL: // hessian/3490 in.readObject(); return null; case BOOLEAN: return Boolean.valueOf(in.readBoolean()); case BYTE: return Byte.valueOf((byte) in.readInt()); case SHORT: return Short.valueOf((short) in.readInt()); case INTEGER: return Integer.valueOf(in.readInt()); case LONG: return Long.valueOf(in.readLong()); case FLOAT: return Float.valueOf((float) in.readDouble()); case DOUBLE: return Double.valueOf(in.readDouble()); case STRING: return in.readString(); case OBJECT: return in.readObject(); case CHARACTER: { String s = in.readString(); if (s == null || s.equals("")) return Character.valueOf((char) 0); else return Character.valueOf(s.charAt(0)); } case CHARACTER_OBJECT: { String s = in.readString(); if (s == null || s.equals("")) return null; else return Character.valueOf(s.charAt(0)); } case DATE: return new Date(in.readUTCDate()); case NUMBER: return in.readObject(); case BYTE_ARRAY: return in.readBytes(); case CHARACTER_ARRAY: { String s = in.readString(); if (s == null) return null; else { int len = s.length(); char []chars = new char[len]; s.getChars(0, len, chars, 0); return chars; } } case BOOLEAN_ARRAY: case SHORT_ARRAY: case INTEGER_ARRAY: case LONG_ARRAY: case FLOAT_ARRAY: case DOUBLE_ARRAY: case STRING_ARRAY: { int code = in.readListStart(); switch (code) { case 'N': return null; case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: int length = code - 0x10; in.readInt(); return readLengthList(in, length); default: String type = in.readType(); length = in.readLength(); return readList(in, length); } } default: throw new UnsupportedOperationException(); } }
这部分代码就是将得到的流进行反序列化,而后再进行处理,将结果序列化返回到客户端,源码就分析到这里,由于本人水平有限,如果以上解析有误的地方,请留言
相关文章推荐
- Hessian源码分析--HessianProxy
- zookeeper源码分析之四服务端(单机)处理请求流程
- Struts2工作流程图、原理和源码分析---perfect
- OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波
- mahout实现的模糊K-Means聚类算法原理和源码分析
- 【OpenCV】SIFT原理与源码分析
- 插入排序:2路插入排序原理分析及源码演示
- [netty源码分析]--服务端启动的工作流程分析
- 【TeamTalk】源码分析之服务端描述
- Android AsyncTask运作原理和源码分析
- uC/OS II原理分析及源码阅读(一)
- Hessian源码分析之设计模式篇(八)
- 深入理解Spark 2.1 Core (二):DAG调度器的原理与源码分析
- [原创]Android Studio的Instant Run(即时安装)原理分析和源码浅析
- Picasso源码原理分析
- MVCC原理探究及MySQL源码实现分析
- ConcurrentHashMap实现原理及源码分析
- Mybatis Interceptor 拦截器原理 源码分析
- MySQL源码分析及核心内幕之4 -- 源码服务端main函数开始及启动流程
- Fresco 源码分析(三) Fresco服务端处理(4) Producer处理体系的总结