Hessian源码学习(一)
【服务端】
HessianServlet 是一个非常普通的Servlet 它直接继承 GenericServlet
我们重点看其中的两个方法:
1.init(ServletConfig config)
这个方法覆写父类的init(ServletConfig config)方法 (我觉得这里覆写init()方法更好)
在初始化中,它做了哪些事情呢?
a.初始化远程服务类(Impl)
if (_homeImpl != null) {}else if (getInitParameter("home-class") != null) {String className = getInitParameter("home-class");Class homeClass = loadClass(className);_homeImpl = homeClass.newInstance();init(_homeImpl);}else if (getInitParameter("service-class") != null) {String className = getInitParameter("service-class");Class homeClass = loadClass(className);_homeImpl = homeClass.newInstance();init(_homeImpl);}其中home-class或者service-class就是在web.xml配置的提供远程服务的类
它首先通过getInitParameter方法获取类名,然后调用loadClass获取对应的Class,最后newInstance创建实例
init(_homeImpl) 又做了些什么呢?
我们知道提供远程服务的类是继承HessianServlet的 所以它也是一个Servlet 我们同样需要初始化它(以下是初始化代码)
private void init(Object service) throws ServletException{if (service instanceof Service) ((Service) service).init(getServletConfig());else if (service instanceof Servlet) ((Servlet) service).init(getServletConfig());}b.初始化远程服务类(Interface)
if (_homeAPI != null) { } else if (getInitParameter("home-api") != null) {String className = getInitParameter("home-api");_homeAPI = loadClass(className); } else if (getInitParameter("api-class") != null) {String className = getInitParameter("api-class");_homeAPI = loadClass(className); } else if (_homeImpl != null) {_homeAPI = findRemoteAPI(_homeImpl.getClass());if (_homeAPI == null) _homeAPI = _homeImpl.getClass();}这段代码和上面逻辑基本一样,这里不再赘述。
c.初始化 HessianSkeleton 类
public HessianSkeleton(Object service, Class apiClass){super(apiClass);_service = service;if (! apiClass.isAssignableFrom(service.getClass())) throw new IllegalArgumentException("Service " + service + " must be an instance of " + apiClass.getName());}重点在于super(apiClass):AbstractSkeleton的初始化
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]); Class []param = method.getParameterTypes(); String mangledName = method.getName() + "__" + param.length; _methodMap.put(mangledName, methodList[i]); _methodMap.put(mangleName(method, false), methodList[i]);}}Method []methodList = apiClass.getMethods();
获取服务类的所有public方法,这也是为什么hessian说每一个public方法都是一个远程服务。
接着遍历所有方法,放入_methodMap中,这里有个关键点,如何支持重载?
hessian是这样处理的,比如对于一个方法: public void sayHello(String str),那么在_methodMap中会存放三个key
sayHello
sayHello_1 (参数个数)
sayHello_string (参数类型)
所以只要client传递方法说明支持调用重载方法,那么他就会调用到正确的重载方法,不然结果是不确定的。
2.service(ServletRequest request, ServletResponse response)
这个方法重写了父类的service方法
a.检查请求方式是否是post
if (! req.getMethod().equals("POST")) {res.setStatus(500, "Hessian Requires POST");PrintWriter out = res.getWriter();res.setContentType("text/html");out.println("<h1>Hessian Requires POST</h1>");return;}b.初始化Hessian输入流以及序列化工厂并设置到Hessian输入流
Hessian2Input in = new Hessian2Input(is);SerializerFactory serializerFactory = getSerializerFactory();in.setSerializerFactory(serializerFactory);
c.读取第一个字节判断是否标准的hessian流
int code = in.read();if (code != 'c') {throw new IOException("expected 'c' in hessian input at " + code);}d.生成hessian输出流并设置序列化工厂到输出流
out = new HessianOutput(os);out.setSerializerFactory(serializerFactory);
e.调用服务
_homeSkeleton.invoke(in, out);
我们具体看下HessianSkeleton.invoke方法:
//反序列化输入流获取调用的服务方法String methodName = in.readMethod();Method method = getMethod(methodName);//反序列输入流获取方法参数Class []args = method.getParameterTypes();Object []values = new Object[args.length];for (int i = 0; i < args.length; i++) values[i] = in.readObject(args[i]);// 真正的执行服务方法(java 反射)result = method.invoke(_service, values);//最后把执行写回输出流,输出起始标志:'r' 1 0out.startReply();// 序列化结果out.writeObject(result);// 输出结束标志'z'out.completeReply();1 楼 evanzzy 2011-11-28 支持继续发布Hessian分析类文章。另外lz是否可讲解hessian相关原理和设计思路?谢谢。 2 楼 DiaoCow 2011-11-28 evanzzy 写道支持继续发布Hessian分析类文章。另外lz是否可讲解hessian相关原理和设计思路?谢谢。
很感谢你的支持,我自己也是出于好奇和以及学习的目的来看hessian源码的,本身并没有什么使用经验。
原理的话我想一步步分析源码就可以得出,至于设计思路这个问题我还回答不上来,希望能和你共同探讨,另外后面也打算分析几个类以及hessian如何实现序列化与反序列化。