`
DiaoCow
  • 浏览: 244332 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Hessian源码学习(一)服务端

阅读更多
【服务端】
HessianServlet 是一个非常普通的Servlet 它直接继承 GenericServlet

我们看其中两个核心方法:init与service方法(参考源码版本3.0.13)

init(ServletConfig config)


该方法覆写父类的init(ServletConfig config)方法(按照servlet规范推荐,覆写init()方法更好)

在初始化中,它做了哪些事情呢?

第一步.初始化远程服务类(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);
}
else {
	if (getClass().equals(HessianServlet.class))
	  throw new ServletException("server must extend HessianServlet");

	_homeImpl = this;
      }

其中home-class或者service-class就是在web.xml配置的提供远程服务的类(两者取一个作为配置即可);

它首先通过getInitParameter方法获取类名,然后调用loadClass获取对应的Class,最后newInstance创建实例;

若用户未配置,使用当前Servlet作为默认实现类(不能为HessianServlet);

我们接着往下看:init(_homeImpl) 又做了些什么呢?
private void init(Object service)
    throws ServletException
{
	if (service instanceof Service)
	  ((Service) service).init(getServletConfig());
	else if (service instanceof Servlet)
	  ((Servlet) service).init(getServletConfig());
}

根据当前服务类(impl)继承的接口(可以是标准的servlet接口也可以是Hessian中定义的Service接口)做相应的初始化(相当于spring的init标签属性);

第二步.初始化远程服务类接口(基本上Hessian也是通过这接口知道自己对外暴露了哪些服务)
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();
  }
}

其中home-api或是api-class定义了对外暴露的服务接口(服务的使用方需要依赖这个接口jar包);

若在配置文件中未指定接口,首先尝试从当前服务类查找(findRemoteAPI);

findRemoteAPI是一个递归方法:在类继承路径上递归查找只继承一个接口的类
private Class findRemoteAPI(Class implClass)
  {
    if (implClass == null || implClass.equals(GenericService.class))
      return null;
    
    Class []interfaces = implClass.getInterfaces();

    if (interfaces.length == 1)
      return interfaces[0];

    return findRemoteAPI(implClass.getSuperclass());
  }

若查找失败,则使用当前服务类作为interface Class(这句话说得很奇怪,还是看代码比较明了)

第三步.初始化 HessianSkeleton 类(相当于HessianExecutor)
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();

获取服务接口中(_homeAPI)所有public方法,这也是为什么hessian说:每一个public方法都是一个远程服务。

接着遍历所有方法,放入_methodMap中,这里有个关键点,如何支持重载?

Hessian是这样处理的,比如对于一个方法: public void sayHello(String str),那么在_methodMap中会存放三个key(这三个key对应着同一个value,也就是sayHello方法)
sayHello
sayHello_1     (参数个数)
sayHello_string    (参数类型)


所以只要client传递方法说明支持调用重载方法,那么他就会调用到正确的重载方法,不然结果是不确定的。

service(ServletRequest request, ServletResponse response)


这个方法重写了父类(GenericServlet)的service方法

第一步.检查请求方式是否是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;
}

第二步.初始化Hessian输入流/输出流
InputStream is = request.getInputStream();
OutputStream os = response.getOutputStream();

HessianInput in = new HessianInput(is);
HessianOutput out = new HessianOutput();
out.setSerializerFactory(getSerializerFactory()); // 关于这里的序列化工厂,后面的文章会详述
out.init(os);

第三步.调用服务(这就是RPC中的C哈 ^_^)
_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]);

// 真正的执行服务方法
result = method.invoke(_service, values);


//最后把执行写回输出流,输出起始标志:'r' 1 0
out.startReply();
// 序列化结果(远程调用结果)
out.writeObject(result);
// 输出结束标志'z'
out.completeReply();

HessianServlet总结
通过上面的源码分析,我们了解到:

1.Hessian如何响应一个远程调用;

2.在web.xml中的各项配置都是什么意思,以及Hessian相应的默认处理规则;

3.Hessian如何支持方法重载;

在下一篇文章中,我们将会分析客户端如何调用Hessian服务!欢迎朋友们提出宝贵意见!
0
0
分享到:
评论
2 楼 DiaoCow 2011-11-28  
evanzzy 写道
支持继续发布Hessian分析类文章。另外lz是否可讲解hessian相关原理和设计思路?谢谢。

很感谢你的支持,我自己也是出于好奇和以及学习的目的来看hessian源码的,本身并没有什么使用经验。
原理的话我想一步步分析源码就可以得出,至于设计思路这个问题我还回答不上来,希望能和你共同探讨,另外后面也打算分析几个类以及hessian如何实现序列化与反序列化。
1 楼 evanzzy 2011-11-28  
支持继续发布Hessian分析类文章。另外lz是否可讲解hessian相关原理和设计思路?谢谢。

相关推荐

    Hessian 学习 例子 实例

    至于标签"源码",学习Hessian时查看源码有助于理解其内部工作原理,比如数据如何被编码和解码。你可以通过阅读开源的Hessian库,如Caucho Hessian的Java实现,来了解其底层细节。 至于"工具",有一些工具可以帮助...

    Hessian学习笔记

    10. **源码阅读**:对于深入理解Hessian的工作原理,阅读源码是一个很好的学习途径。通过查看源码,可以理解数据如何被序列化和反序列化,以及如何处理远程调用的细节。 综上所述,学习Hessian需要掌握二进制序列化...

    Hessian

    在博客链接《iteye博客:550771》中,作者可能详细讨论了Hessian的使用方法、优缺点以及实战案例,可以作为学习Hessian的参考资料。 **六、Hessian的使用场景** 1. **微服务通信**:在微服务架构中,Hessian可以...

    hessian php与java通讯demo源码

    总之,这个"PHP与Java通信Demo源码"是一个很好的学习资源,帮助开发者理解如何在PHP和Java之间使用Hessian协议进行通信。通过分析和实践这些示例代码,你可以更好地掌握Hessian的工作原理和使用方式,为你的跨语言...

    hessian-4.0.51-src

    《深入解析Hessian 4.0.51源码》 Hessian,作为一个高效轻量级的二进制Web服务协议,广泛应用于分布式系统中,它允许开发者...对于想深入理解分布式通信机制的开发者来说,研究Hessian源码无疑是一次宝贵的学习机会。

    Hessian(Spring集成的)的应用与研究

    2. Hessian的安全策略:学习如何在Hessian服务上实现认证和授权,防止未授权访问。 3. 性能优化:通过调整Hessian配置,如连接池大小、超时时间等,来提升服务性能。 4. 异常处理:研究如何处理Hessian通信过程中的...

    Spring中集成Hessian的问题

    在Spring框架中集成Hessian是为了实现远程方法调用(Remote Method Invocation, RMI),这是一种轻量级的序列化协议,可以高效地传输Java...通过深入学习和实践,我们可以更好地利用Hessian来构建高性能的分布式系统。

    Hessian源代码

    2. **示例代码**:这些示例可以帮助我们理解如何在实际项目中使用Hessian,包括创建服务端、客户端,以及调用远程服务的方法。 3. **测试用例**:源代码可能包含单元测试和集成测试,通过这些测试,我们可以验证...

    spring整合hessian进行远程通讯

    标题中的“spring整合hessian进行远程通讯”是指在Spring框架中使用Hessian库来实现远程过程调用(RPC)。...在实际开发中,我们需要结合源码学习,了解其实现原理,并注意安全性和性能优化,确保系统的稳定运行。

    Java Hessian小试(转)

    Java Hessian小试(转) Java Hessian是一种二进制的RPC(远程过程调用)协议,由Caucho...在压缩包子文件"**Hessian**"中,可能包含了一些示例代码或者Hessian的实现细节,对于学习和研究Hessian的源码有一定的帮助。

    hessian-4.0.7jar文件与源代码.rar

    这个jar文件可以被Java应用程序引入,以便在客户端和服务端之间进行Hessian协议的通信。它包括了序列化和反序列化机制,以及对HTTP和HTTPS的支持,使得远程方法调用变得简单且高效。 `hessian-4.0.7-src.jar`则是...

    Hessian 入门介绍

    **Hessian入门介绍** 在IT领域,Hessian是一种二进制Web服务协议,它由Caucho Technology开发,主要用于提供...通过学习和实践`HessianDemo`,开发者能够掌握Hessian的基本用法,从而在实际项目中有效地利用这一工具。

    自己写了个Hessian

    通过阅读这个博客,我们可以学习到如何在实际项目中应用Hessian协议,以及如何优化自定义实现。 标签 "源码" 和 "工具" 提醒我们,这个项目不仅涉及理论知识,还包含了实际的代码实现,可能是一个工具或者库,可以...

    flex-hessian-java实例.rar

    Flex是Adobe开发的一种开放源码的富互联网应用(RIA)开发框架,用于创建交互性强、用户体验良好的Web应用程序。Hessian是一种二进制Web服务协议,它提供了轻量级、高效的远程方法调用(RPC)机制,尤其适合于Java和...

    Flex + Hessian 学习笔记(二)

    2. **Hessian服务端集成**:在服务器端,开发者需要配置Hessian服务,这通常涉及到创建Java服务接口和实现。Hessian库将这些Java对象暴露为二进制HTTP服务,使得Flex客户端可以调用。 3. **Hessian客户端API**:在...

    hessian-4.0.7.jar + src

    3. 掌握如何通过Hessian源码调试和优化性能。 4. 熟悉Hessian与其他通信协议(如HTTP、SOAP)的对比,以便根据项目需求选择最佳方案。 总结,Hessian 4.0.7是一个强大的工具,尤其适合需要高效远程调用的Java开发者...

    hession例子,源码,最新的jar包,还有web例子与spring结合的例子

    3. **源码分析**: 深入理解Hessian源码对于优化和定制Hessian服务非常重要。源码可能包含了Hessian序列化和反序列化的实现细节,以及处理异常和错误的方式。通过阅读源码,你可以了解到Hessian如何处理不同类型的...

    Hessian 发布WebServices

    在实际开发中,使用Eclipse或MyEclipse这样的IDE可以帮助开发者方便地管理Hessian服务,通过配置`.classpath`和`.project`文件来导入所需的库,如Hessian的客户端和服务端API。`src`目录下的源代码可能包含了使用...

Global site tag (gtag.js) - Google Analytics