hessian原理解析二(服务端分析)
hessian 服务端源码分析
我们在回头看看 web.xml 中 servlet 配置
<servlet>
<servlet-name>HelloHessian</servlet-name>
<servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class>
<init-param>
<param-name>service-class</param-name>
<param-value>com.hessian.server.HelloHessianImpl</param-value>
</init-param>
</servlet>
服务端HessianServlet 处理hessian 请求 ,HessianServlet 继承HttpServlet, 每个servlet有两个重要的方法 init 和 service
1、void init(ServletConfig config) 初始化远程服务实现类、远程服务接口类以及HessianSkeleton
a、初始化远程服务实现类, home-class 、service-class
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);
}
b 、初始化远程服务接口
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 = _homeImpl.getClass();
}
c 、初始化 HessianSkeleton
_homeSkeleton = new HessianSkeleton(_homeImpl, _homeAPI);
// 取服务类的方法
Method []methodList = apiClass.getMethods()
// 遍历 服务类的方法,放入_methodMap
for (int i = 0; i < methodList.length; i++) {
Method method = methodList[i];
Class []param = method.getParameterTypes();
String mangledName = method.getName() + "__" + param.length;
_methodMap.put(method.getName(), methodList[i]);
_methodMap.put(mangledName, methodList[i]);
_methodMap.put(mangleName(method, false), methodList[i]);
}
hessian 支持重载处理,关键点: 比如对于一个方法 public void sayHello(User user), 那么在_methodMap中会存放三个key sayHello sayHello_1, sayHello_User
2、service(ServletRequest request, ServletResponse response) 重写父类的service 方法
2.1、 检查请求方式是否为POST
if (! req.getMethod().equals("POST")) {
res.setStatus(500); // "Hessian Requires POST"
return;
}
2.2、获取输入输出流、对象的序列化工厂 执行目标目标服务方法
ServletInputStream e = request.getInputStream();
ServletOutputStream os = response.getOutputStream();
SerializerFactory serializerFactory = this.getSerializerFactory();
hessianSkeleton.invoke(is, os, serializerFactory)
hessianServlet 处理请求时序图
HessianSkeleton invoke 方法解析:
public void invoke(Object service,AbstractHessianInput in,AbstractHessianOutput out){
//读取方法调用名
String methodName = in.readMethod();
int argLength = in.readMethodArgLength();
Method method = this.getMethod(methodName + "_" + argLength);
//读取调用方法参数
Class[] args = method.getParameterTypes();
Object[] values = new Object[args.length];
for(int i= 0; i < args.length; ++i) {
values[i] = in.readObject(args[i]);
}
//执行目标方法调用
result = method.invoke(service, values)
//结果输出
out.writeReply(result);
out.close();
输出格式:
此处为16进制数表示
72 01 00 53 00 05 74 69 67 65 72 7A
r s t i g e r z