说明
在上篇博文Hessian学习(一)中,初步了解了Hessian,并使用Hessian搭建了一个简单的项目,了解了Hessian如何使用,本文主要学习记录Hessian的实现原理
正文
在使用Hessian时,最重要的就是服务端web.xml中的配置
<servlet>
<servlet-name>HessianServlet</servlet-name>
<servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class>
<init-param>
<param-name>service-class</param-name>
<param-value>com.basic.server.impl.HelloImpl</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>HessianServlet</servlet-name>
<url-pattern>/hessian</url-pattern>
</servlet-mapping>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
在web.xml中配置了一个Servlet,通过这个Servlet来处理请求,可见Hessian的使用都是围绕着com.caucho.hessian.server.HessianServlet这类来展开
当服务器初始化Servlet时调用Servlet的init()方法,调用service()方法实现服务
通过阅读源码了解Hessian的运行原理
HessianServlet
HessianServlet继承了HttpServlet,在这可以看出Hessian是基于HTTP协议的
public class HessianServlet extends HttpServlet {
- 1
重要参数
private Class<?> _homeAPI; // 服务类的接口
private Object _homeImpl; // 服务类的实例
private Class<?> _objectAPI; // 不清楚 此参数的意义
private Object _objectImpl;
private HessianSkeleton _homeSkeleton; // hsesian服务的代理类,服务端功能的核心
private HessianSkeleton _objectSkeleton;
private SerializerFactory _serializerFactory;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
init(config)方法
初始化时,读取配置文件信息,初始化servlet
在init方法中通过service-class或home-class来获取服务类的实例,通过home-api或api-class来获取服务接口的class对象
当把参数名称换为object-class、object-api时程序无法运行
当把web.xml文件中的service-class替换成object-class时,客户端测试会报错
com.caucho.hessian.client.HessianConnectionException: 500: java.io.IOException: Server returned HTTP response code: 500 for URL:
- 1
public void init(ServletConfig config)
throws ServletException
{
super.init(config);
try {
if (_homeImpl != null) {
}
else if (getInitParameter("home-class") != null) {
String className = getInitParameter("home-class"); // 获取配置文件中名为home-class参数的值
Class<?> homeClass = loadClass(className); //获得class对象
_homeImpl = homeClass.newInstance(); //创建实例对象
init(_homeImpl);
}
else if (getInitParameter("service-class") != null) { //获取配置文件中名为service-class参数的值
String className = getInitParameter("service-class");
Class<?> homeClass = loadClass(className);
_homeImpl = homeClass.newInstance();
init(_homeImpl);
}
else {
if (getClass().equals(HessianServlet.class))
throw new ServletException("server must extend HessianServlet");
_homeImpl = this;
}
if (_homeAPI != null) {
}
else if (getInitParameter("home-api") != null) {
String className = getInitParameter("home-api"); //得到配置文件中名为home-api的参数值
_homeAPI = loadClass(className); // 获取class对象
}
else if (getInitParameter("api-class") != null) {
String className = getInitParameter("api-class"); //得到配置文件中名为api-class的参数值
_homeAPI = loadClass(className);
}
else if (_homeImpl != null) {//当没有配置那两个参数时,会使用服务类实例对象获取class对象
_homeAPI = findRemoteAPI(_homeImpl.getClass()); // 该方法在源码中已经被注释
if (_homeAPI == null)
_homeAPI = _homeImpl.getClass();
_homeAPI = _homeImpl.getClass();
}
if (_objectImpl != null) {
}
else if (getInitParameter("object-class") != null) {
String className = getInitParameter("object-class");
Class<?> objectClass = loadClass(className);
_objectImpl = objectClass.newInstance();
init(_objectImpl);
}
if (_objectAPI != null) {
}
else if (getInitParameter("object-api") != null) {
String className = getInitParameter("object-api");
_objectAPI = loadClass(className);
}
else if (_objectImpl != null)
_objectAPI = _objectImpl.getClass();
_homeSkeleton = new HessianSkeleton(_homeImpl, _homeAPI);
if (_objectAPI != null)
_homeSkeleton.setObjectClass(_objectAPI);
if (_objectImpl != null) {
_objectSkeleton = new HessianSkeleton(_objectImpl, _objectAPI);
_objectSkeleton.setHomeClass(_homeAPI);
}
else
_objectSkeleton = _homeSkeleton;
if ("true".equals(getInitParameter("debug"))) {
}
if ("false".equals(getInitParameter("send-collection-type")))
setSendCollectionType(false);
} catch (ServletException e) {
throw e;
} catch (Exception e) {
throw new ServletException(e);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
service(request,response)方法
当客户端请求时,使用service方法来处理请求,在此方法中主要是调用invoke()来处理请求
public void service(ServletRequest request, ServletResponse response)
throws IOException, ServletException
{
HttpServletRequest req = (HttpServletRequest) request; // 强转为HttpServelt 的request和response
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(); // 从http的请求url中获取服务id
String objectId = req.getParameter("id"); // 获取参数id
if (objectId == null)
objectId = req.getParameter("ejbid");
ServiceContext.begin(req, res, serviceId, objectId); // 初始化service的上下文
try {
InputStream is = request.getInputStream();
OutputStream os = response.getOutputStream();
response.setContentType("x-application/hessian");
SerializerFactory serializerFactory = getSerializerFactory();// 得到序列化的factory
invoke(is, os, objectId, serializerFactory);// 调用invoke方法处理请求
} catch (RuntimeException e) {
throw e;
} catch (ServletException e) {
throw e;
} catch (Throwable e) {
throw new ServletException(e);
} finally {
ServiceContext.end();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
invoke(is, os, objectId, serializerFactory)方法
这里根据objectId是否为null,调用不同对象的invoke方法 ,都是调用的HessianSkeleton的invoke方法 invoke方法中涉及到了hessian的序列化
protected void invoke(InputStream is, OutputStream os,
String objectId,
SerializerFactory serializerFactory)
throws Exception
{
if (objectId != null)
_objectSkeleton.invoke(is, os, serializerFactory);
else
_homeSkeleton.invoke(is, os, serializerFactory);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
在HessianSkeleton的invoke方法中,最终的执行还是调用method的invoke方法
try {
result = method.invoke(service, values); // 调用method的invoke方法
} catch (Exception e) {
Throwable e1 = e;
if (e1 instanceof InvocationTargetException)
e1 = ((InvocationTargetException) e).getTargetException();
log.log(Level.FINE, this + " " + e1.toString(), e1);
out.writeFault("ServiceException",
escapeMessage(e1.getMessage()),
e1);
out.close();
return;
}
// The complete call needs to be after the invoke to handle a
// trailing InputStream
in.completeCall();
out.writeReply(result); // 使用out对象的方法将结果返回给客户端
out.close();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
参考博文:https://blog.csdn.net/qq924862077/article/details/52799330