Hessian源码分析--HessianServlet
Hessian可以通过Servlet来对外暴露服务,HessianServlet继承于HttpServlet,但这仅仅是一个外壳,使用web服务器来提供对外的Http请求,在web.xml中我们会进行如下配置,其实就是一个简单的servlet配置,不过是增加了两个属性的配置home-class和home-api,这两个配置其实就是用来调用真正的接口及实现类的:
<servlet>
<servlet-name>hessian-service</servlet-name>
<servlet-class>
com.caucho.hessian.server.HessianServlet
</servlet-class>
<init-param>
<param-name>home-class</param-name>
<param-value>
<!-- 服务实现类 -->
com.tianjunwei.hessian.server.HelloServiceImpl
</param-value>
</init-param>
<init-param>
<param-name>home-api</param-name>
<!-- 服务接口 -->
<param-value>com.tianjunwei.hessian.server.HelloService</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>hessian-service</servlet-name>
<url-pattern>/hessian</url-pattern>
</servlet-mapping>
HessianServlet在初始化时会调用init函数来获得home-api和home-class
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);
}
else {
if (getClass().equals(HessianServlet.class))
throw new ServletException("server must extend HessianServlet");
_homeImpl = this;
}
获取home-class和home-api的目的是作为参数去创建HessianSkeleton,它才是服务端的实现中点
_homeSkeleton = new HessianSkeleton(_homeImpl, _homeAPI);
当Servlet调用初始化函数init之后,其最主要的目的就是根据配置信息来初始化HessianSkeleton
当客户端通过http请求到对外暴露的服务端时,接下来要执行的是Servlet的service函数,
service函数的实现还是很简单的,首先判断请求是否是post请求,如果不是则直接返回错误信息
接下来就是一些参数的获取,最终要的是执行invoke(is, os, objectId, serializerFactory)函数
public void service(ServletRequest request, ServletResponse response)
throws IOException, ServletException
{
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
//Hessian需要调用需要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;
}
String serviceId = req.getPathInfo();
String objectId = req.getParameter("id");
if (objectId == null)
objectId = req.getParameter("ejbid");
ServiceContext.begin(req, res, serviceId, objectId);
try {
InputStream is = request.getInputStream();
OutputStream os = response.getOutputStream();
response.setContentType("x-application/hessian");
SerializerFactory serializerFactory = getSerializerFactory();
invoke(is, os, objectId, serializerFactory);
} catch (RuntimeException e) {
throw e;
} catch (ServletException e) {
throw e;
} catch (Throwable e) {
throw new ServletException(e);
} finally {
ServiceContext.end();
}
}
对于invoke(is, os, objectId, serializerFactory)的执行也是很简单的,其实就是在调用初始化的
HessianSkeleton类的invoke函数,这样HessianServlet的任务就完成了。
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);
}
HessianServlet的完整源码如下:
public class HessianServlet extends HttpServlet {
private Class<?> _homeAPI;
private Object _homeImpl;
private Class<?> _objectAPI;
private Object _objectImpl;
private HessianSkeleton _homeSkeleton;
private HessianSkeleton _objectSkeleton;
private SerializerFactory _serializerFactory;
public HessianServlet()
{
}
public String getServletInfo()
{
return "Hessian Servlet";
}
/**
* Sets the home api.
*/
public void setHomeAPI(Class<?> api)
{
_homeAPI = api;
}
/**
* Sets the home implementation
*/
public void setHome(Object home)
{
_homeImpl = home;
}
/**
* Sets the object api.
*/
public void setObjectAPI(Class<?> api)
{
_objectAPI = api;
}
/**
* Sets the object implementation
*/
public void setObject(Object object)
{
_objectImpl = object;
}
/**
* Sets the service class.
*/
public void setService(Object service)
{
setHome(service);
}
/**
* Sets the api-class.
*/
public void setAPIClass(Class<?> api)
{
setHomeAPI(api);
}
/**
* Gets the api-class.
*/
public Class<?> getAPIClass()
{
return _homeAPI;
}
/**
* Sets the serializer factory.
*/
public void setSerializerFactory(SerializerFactory factory)
{
_serializerFactory = factory;
}
/**
* Gets the serializer factory.
*/
public SerializerFactory getSerializerFactory()
{
if (_serializerFactory == null)
_serializerFactory = new SerializerFactory();
return _serializerFactory;
}
/**
* Sets the serializer send collection java type.
*/
public void setSendCollectionType(boolean sendType)
{
getSerializerFactory().setSendCollectionType(sendType);
}
/**
* Sets the debugging flag.
*/
public void setDebug(boolean isDebug)
{
}
/**
* Sets the debugging log name.
*/
public void setLogName(String name)
{
// _log = Logger.getLogger(name);
}
/**
* Initialize the service, including the service object.
*/
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");
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);
}
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");
_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();
_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);
}
}
private Class<?> findRemoteAPI(Class<?> implClass)
{
// hessian/34d0
return null;
/*
if (implClass == null || implClass.equals(GenericService.class))
return null;
Class []interfaces = implClass.getInterfaces();
if (interfaces.length == 1)
return interfaces[0];
return findRemoteAPI(implClass.getSuperclass());
*/
}
private Class<?> loadClass(String className)
throws ClassNotFoundException
{
ClassLoader loader = getContextClassLoader();
if (loader != null)
return Class.forName(className, false, loader);
else
return Class.forName(className);
}
protected ClassLoader getContextClassLoader()
{
return Thread.currentThread().getContextClassLoader();
}
private void init(Object service)
throws ServletException
{
if (! this.getClass().equals(HessianServlet.class)) {
}
else if (service instanceof Service)
((Service) service).init(getServletConfig());
else if (service instanceof Servlet)
((Servlet) service).init(getServletConfig());
}
/**
* Execute a request. The path-info of the request selects the bean.
* Once the bean's selected, it will be applied.
*/
public void service(ServletRequest request, ServletResponse response)
throws IOException, ServletException
{
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
//Hessian需要调用需要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;
}
String serviceId = req.getPathInfo();
String objectId = req.getParameter("id");
if (objectId == null)
objectId = req.getParameter("ejbid");
ServiceContext.begin(req, res, serviceId, objectId);
try {
InputStream is = request.getInputStream();
OutputStream os = response.getOutputStream();
response.setContentType("x-application/hessian");
SerializerFactory serializerFactory = getSerializerFactory();
//其实就是在调用HessianSkeleton的invoke方法
invoke(is, os, objectId, serializerFactory);
} catch (RuntimeException e) {
throw e;
} catch (ServletException e) {
throw e;
} catch (Throwable e) {
throw new ServletException(e);
} finally {
ServiceContext.end();
}
}
//实现机制就是调用HessianSkeleton的invoke方法
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);
}
protected Hessian2Input createHessian2Input(InputStream is)
{
return new Hessian2Input(is);
}
static class LogWriter extends Writer {
private Logger _log;
private StringBuilder _sb = new StringBuilder();
LogWriter(Logger log)
{
_log = log;
}
public void write(char ch)
{
if (ch == '\n' && _sb.length() > 0) {
_log.fine(_sb.toString());
_sb.setLength(0);
}
else
_sb.append((char) ch);
}
public void write(char []buffer, int offset, int length)
{
for (int i = 0; i < length; i++) {
char ch = buffer[offset + i];
if (ch == '\n' && _sb.length() > 0) {
_log.fine(_sb.toString());
_sb.setLength(0);
}
else
_sb.append((char) ch);
}
}
public void flush()
{
}
public void close()
{
}
}
}
Hessian源码分析--HessianServlet的更多相关文章
- Hessian源码分析--HessianSkeleton
HessianSkeleton是Hessian的服务端的核心,简单总结来说:HessianSkeleton根据客户端请求的链接,获取到需要执行的接口及实现类,对客户端发送过来的二进制数据进行反序列化, ...
- Hessian源码分析--HessianProxy
在上一篇博客 Hessian源码分析--HessianProxyFactory 中我们了解到,客户端获得的对象其实是HessianProxy生成的目标对象,当调用目标对象的方法时,会调用Hessian ...
- Hessian源码分析--总体架构
Hessian是一个轻量级的remoting onhttp工具,使用简单的方法提供了RMI的功能. 相比WebService,Hessian更简单.快捷.采用的是二进制RPC协议,因为采用的是二进制协 ...
- (转)hessian源码分析(一)------架构
在计费中心的对外交互这块采用了hessian,有必要对hessian的运行机理和源码做一定的解析. 大致翻了翻源码后,发现hessian的主要结构分客户端与服务端,中间基于http传输.客户端主要做的 ...
- Hessian源码分析--HessianProxyFactory
HessianProxyFactory是HessianProxy的工厂类,其通过HessianProxy来生成代理类. 如下面代码: HessianProxyFactory factory = new ...
- SURF算法与源码分析、下
上一篇文章 SURF算法与源码分析.上 中主要分析的是SURF特征点定位的算法原理与相关OpenCV中的源码分析,这篇文章接着上篇文章对已经定位到的SURF特征点进行特征描述.这一步至关重要,这是SU ...
- Dubbo 源码分析 - 服务引用
1. 简介 在上一篇文章中,我详细的分析了服务导出的原理.本篇文章我们趁热打铁,继续分析服务引用的原理.在 Dubbo 中,我们可以通过两种方式引用远程服务.第一种是使用服务直联的方式引用服务,第二种 ...
- 【OpenCV】SIFT原理与源码分析:关键点搜索与定位
<SIFT原理与源码分析>系列文章索引:http://www.cnblogs.com/tianyalu/p/5467813.html 由前一步<DoG尺度空间构造>,我们得到了 ...
- 12.源码分析—如何为SOFARPC写一个序列化?
SOFARPC源码解析系列: 1. 源码分析---SOFARPC可扩展的机制SPI 2. 源码分析---SOFARPC客户端服务引用 3. 源码分析---SOFARPC客户端服务调用 4. 源码分析- ...
随机推荐
- Java实现word文档在线预览,读取office文件
想要实现word或者其他office文件的在线预览,大部分都是用的两种方式,一种是使用openoffice转换之后再通过其他插件预览,还有一种方式就是通过POI读取内容然后预览. 一.使用openof ...
- spring AOP的两种配置方式
连接点(JoinPoint) ,就是spring允许你是通知(Advice)的地方,那可就真多了,基本每个方法的前.后(两者都有也行),或抛出异常是时都可以是连接点,spring只支持方法连接点.其他 ...
- jquery easyui combobox 从指定位置开始模糊查询
$("#bzr").combobox({ url: "ClassSave.aspx?opt=bzr&bzr=<%=arrbj[2]%>", ...
- 四柱加强版汉诺塔HanoiTower----是甜蜜还是烦恼
我想很多人第一次学习递归的时候,老师或者书本上可能会举汉诺塔的例子. 但是今天,我们讨论的重点不是简单的汉诺塔算法,而是三柱汉诺塔的延伸.先来看看经典的三柱汉诺塔. 一.三柱汉诺塔(Hanoi_Thr ...
- css修改浏览器默认的滚动条样式
//滚动条样式 ::-webkit-scrollbar { width: 10px; } /* 垂直滚动条的滑动块 */ ::-webkit-scrollbar-thumb:vertical { bo ...
- springboot解决跨域问题(Cors)
1.对于前后端分离的项目来说,如果前端项目与后端项目部署在两个不同的域下,那么势必会引起跨域问题的出现. 针对跨域问题,我们可能第一个想到的解决方案就是jsonp,并且以前处理跨域问题我基本也是这么处 ...
- 代码之间-论文修改助手v1.0版本发布
论文查重,是每个毕业生都要面临的一个令人头疼的问题,如果写论文不认真,很可能导致查重红一大片. 之前有帮助一些朋友修改论文降低重复率,做了一些工作后发现,国内的查重机构,如知网.维普等,大多数是基于关 ...
- Appium--入门demo
Appium环境搭建已经在在博客中写出 http://www.cnblogs.com/feimaoyuzhubaobao/p/5057832.html 那么本篇博客主要介绍java版本的appiu ...
- Request JSON
https://developer.android.com/training/volley/request.html Request JSON Volley provides the followin ...
- 【伯乐在线】这些 Git 技能够你用一年了
原文出处: Pyper 欢迎分享原创到伯乐头条 用git有一年了,下面是我这一年来的git使用总结,覆盖了日常使用中绝大多数的场景.嗯,至少是够用一年了,整理出来分享给大家,不明白的地方可以回复交 ...