hessian学习笔记
一、hessian是什么
Hessian是一个轻量级的remoting onhttp工具,使用简单的方法提供了RMI的功能。 相比WebService,Hessian更简单、快捷。采用的是二进制RPC协议,因为采用的是二进制协议,所以它很适合于发送二进制数据。——百度百科
学习hessian,必须知道什么是RPC。
实现RPC,必须解决如下几个问题:
1、通讯问题。
2、寻址问题。
3、序列化与反序列化。
带着这三个问题我们一起来探究一下hessian;
二、hessian怎么使用
首先,大家去下载源码,并导入到idea中打开;
https://github.com/zhaojiatao/learn_hessian
项目结构:
--learn_hessian
----api 客户端和服务端均共同引用的接口api
----client 客户端调用demo,包括本地直接通过代理对象调用以及使用spring集成方式调用
----webserver 通过传统servlet方式提供服务
----webserver_spring 与spring集成 提供服务
2.1服务端搭建:
2.1.1传统serlet方式搭建
在web.xml中配置HessianServlet,
指明服务地址:/hessian
及其实现类:com.zjt.learn.hessian.api.impl.GetUserInfoImpl
<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.zjt.learn.hessian.api.impl.GetUserInfoImpl</param-value>
</init-param>
</servlet> <servlet-mapping>
<servlet-name>HessianServlet</servlet-name>
<url-pattern>/hessian</url-pattern>
</servlet-mapping>
package com.zjt.learn.hessian.api.impl; import com.zjt.learn.hessian.api.GetUserInfo;
import com.zjt.learn.hessian.dto.User;
import org.apache.commons.lang3.StringUtils; /**
* Created by zhaojiatao@souche.com on 2018/4/17
*/
public class GetUserInfoImpl implements GetUserInfo {
@Override
public String getuserinfo(String id) { if(StringUtils.isNotBlank(id)){
User user=new User();
user.setId("1");
user.setName("zhaojiatao");
user.setAddress("hangzhou");
user.setAge(18);
user.setGender(1);
return user.toString();
} return null;
}
}
2.1.2使用spring方式集成发布服务
首先在web.xml中配置springmvc:
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet> <servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/remote/*</url-pattern>
</servlet-mapping>
配置applicationContext.xml:
使用HessianServiceExporter来处理请求;
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd"
default-lazy-init="true"> <bean id = "getuserService" class="com.zjt.learn.hessian.api.impl.GetUserInfoImpl"/> <bean name="/getuserHessianService" class="org.springframework.remoting.caucho.HessianServiceExporter">
<property name="service" ref="getuserService"/>
<property name="serviceInterface" value="com.zjt.learn.hessian.api.GetUserInfo"/>
</bean>
</beans>
2.2客户端调用
2.2.1使用传统方式调用远程服务
package test; import com.caucho.hessian.client.HessianProxyFactory;
import com.zjt.learn.hessian.api.GetUserInfo; /**
* Created by zhaojiatao@souche.com on 2018/4/17
*/
public class BasicClient { public static void main(String[] args) {
try {
String url = "http://localhost:8080/hessian";
HessianProxyFactory factory = new HessianProxyFactory();
factory.setOverloadEnabled(true);
GetUserInfo getUserInfo = (GetUserInfo) factory.create(GetUserInfo.class, url);
System.out.println(getUserInfo.getuserinfo("1"));
System.out.println("over");
}catch (Exception e){
e.printStackTrace();
}
} }
2.2.2使用spring方式调用
新建spring.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd"
default-lazy-init="true"> <bean id="getuserService" class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
<property name="serviceUrl" value="http://localhost:8080/remote/getuserHessianService"/>
<property name="serviceInterface" value="com.zjt.learn.hessian.api.GetUserInfo"/>
</bean>
</beans>
package test; import com.zjt.learn.hessian.api.GetUserInfo;
import org.springframework.context.support.ClassPathXmlApplicationContext; /**
* Created by zhaojiatao@souche.com on 2018/4/18
*/
public class BasicSpringClient { public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"classpath:spring.xml"});
GetUserInfo getUserInfo = (GetUserInfo)context.getBean("getuserService");
System.out.println(getUserInfo.getuserinfo("1"));
} }
hessian的使用是很简单的。大家自己照着代码敲一下就可以。
三、探究一下hessian的细节
回到文章开始提出的问题,即rpc框架需要解决的问题,看看hessian如何解决的。
3.1.通讯问题:
我们先看看客户端在发起远程请求前都经历了什么:
首先,客户端通过代理工厂对象HessianProxyFactory的create方法创建代理对象;
在create方法里可以看到,该代理对象在执行时的handler是通过HessianProxy代理对象的invoke方法来执行;典型的动态代理;
在invoke方法中:
通过String methodName = method.getName();得到方法名
通过sendRequest方法取得和服务端的连接HessianConnection对象;
跟踪sendRequest方法,我们发现:
发现,hessian是使用http协议进行网络通信;
在is = getInputStream(conn);处等待服务端返回的响应;
3.2 寻址问题
我们跟踪这里:
我们得出结论:hessian使用lookup方法来寻找远程服务;
3.3序列化与反序列化
我们继续看刚刚跟踪的客户端调用时执行的HessianProxy对象的invoke方法,
进入其中的
conn = sendRequest(mangleName, args);
再进入
out.call(methodName, args);
再进入
writeObject(args[i]);
进入其Hessian2Output实现中
最终看到了hessian如何进行序列化:
serializer.writeObject(object, this);
至此,我们也可以梳理一下hessian客户端动态代理的执行流程:
我们再来看看服务端的执行细节:
通过后台的代码,可见我们所有的工作都围绕在HessianServlet在展开。该Servlet中有两个比较重要的方法:init()、service();
init方法初始化服务和服务对象,主要分为3步:
通过home-class或者service-class创建服务端的实现类实例;
init方法还会创建HessianSkeleton对象,这是Hessian服务端的核心功能部分。
HessianSkeleton继承自AbstractSkeleton,其构造方法,将会从实现类中抽取方法和方法的Method对象,并且存储到_methodMap中。
对于一个Servlet来说其service方法是对外提供服务的方法:
最主要的是调用HessianSkeleton对象的invoke方法。注意,Servlet实例中有两个HessianSkeleton变量,分别是:_objectSkeleton和 _homeSkeleton,
invoke方法:
首先从HessianInput对象中获取到Method信息,获取到真正的service对象。
根据反射机制,调用service对象的invoke方法,获取到返回值。
最后调用HessianOutput对象将结果写回到调用方。
本文参考:
https://blog.csdn.net/sunwei_pyw/article/details/74002351
https://www.cnblogs.com/happyday56/p/4268249.html
hessian学习笔记的更多相关文章
- 轻量级远程调用框架-Hessian学习笔记-Demo实现
Hessian是一个轻量级的remoting onhttp工具,使用简单的方法提供了RMI的功能. 相比WebService,Hessian更简单.快捷.采用的是二进制RPC协议,因为采用的是二进制协 ...
- WebService另一种轻量级实现—Hessian 学习笔记
最近和同事聊天,得知他们在使用一种叫做Hessian的WebService实现方式实现远 程方法调用,是轻量级的,不依赖JavaEE容器,同时也是二进制数据格式传输,效率比SOAP的XML方式要高.感 ...
- spring学习笔记(一) Spring概述
博主Spring学习笔记整理大部分内容来自Spring实战(第四版)这本书. 强烈建议新手购入或者需要电子书的留言. 在学习Spring之前,我们要了解这么几个问题:什么是Spring?Spring ...
- R语言与机器学习学习笔记
人工神经网络(ANN),简称神经网络,是一种模仿生物神经网络的结构和功能的数学模型或计算模型.神经网络由大量的人工神经元联结进行计算.大多数情况下人工神经网络能在外界信息的基础上改变内部结构,是一种自 ...
- Dubbo -- 系统学习 笔记 -- 示例 -- 多协议
Dubbo -- 系统学习 笔记 -- 目录 示例 想完整的运行起来,请参见:快速启动,这里只列出各种场景的配置方式 多协议 可以自行扩展协议,参见:协议扩展 (1) 不同服务不同协议 比如:不同服务 ...
- Dubbo -- 系统学习 笔记 -- 配置参考手册
Dubbo -- 系统学习 笔记 -- 目录 配置参考手册 <dubbo:service/> <dubbo:reference/> <dubbo:protocol/> ...
- Dubbo -- 系统学习 笔记 -- 依赖
Dubbo -- 系统学习 笔记 -- 目录 依赖 必需依赖 缺省依赖 可选依赖 依赖 必需依赖 JDK1.5+ 理论上Dubbo可以只依赖JDK,不依赖于任何三方库运行,只需配置使用JDK相关实现策 ...
- Dubbo -- 系统学习 笔记 -- 入门
Dubbo -- 系统学习 笔记 -- 目录 入门 背景 需求 架构 用法 入门 背景 随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行, ...
- TensorFlow学习笔记6-数值计算基础
TensorFlow学习笔记6-数值计算 本笔记内容为"数值计算的基础知识".内容主要参考<Deep Learning>中文版. \(X\)表示训练集的矩阵,其大小为m ...
随机推荐
- 自己组装一台1U服务器
视频资料链接 自己组装一台1U服务器 执行思路: 1.评估访问了,根据需求确定服务器要求 2.根据要求选择硬件:冗余.稳定等 3.搜索主流服务器参数进行对比,及对比价格 4.咨询IDC机房价格 DIY ...
- ThinkCMF后台地址加密忘记了无法打开后台怎么办?
ThinkCMF后台地址加密忘记了无法打开后台怎么办?笔者为了网站安全把ThinkCMF后台的安全模式打开后忘了保存加密地址,导致无法登陆后台,找了些网上的资料,不太靠谱,只好从代码入手,找到/app ...
- 对比Node.js和Python 帮你确定理想编程解决方案!
世上没有最好的编程语言.有些编程语言比其他编程语言用于更具体的事情.比如,你可能需要移动应用程序,网络应用程序或更专业化的系统,则可能会有特定的语言.但是我们暂时假设你需要的是一个相对来说比较简单的网 ...
- SQL基础教程(第2版)第3章 聚合与排序:3-1 对表进行聚合查询
3-1 对表进行聚合查询 ● 使用聚合函数对表中的列进行计算合计值或者平均值等的汇总操作.● 通常,聚合函数会对NULL以外的对象进行汇总.但是只有COUNT函数例外,使用COUNT(*)可以查出包含 ...
- Java 知识点(一)
博主对 Java知识点的整理基于 c语言,整理内容为 Java的重点及与 c语言的差异点或编程通要知识点.水平有限,欢迎指正.(参考书籍<Java 核心技术 卷Ⅰ>) Java 的类名:名 ...
- 【Gson】网页上String获取的Json数据转化为对象
1.网络上获取的String Json格式转化为对象获取数据: 需要的包:Gson Maven依赖: <!-- https://mvnrepository.com/artifact/com.go ...
- 【WPF学习】第三十七章 触发器
WPF中有个主题,就是以声明方式扩展代码的功能.当使用样式.资源或数据绑定时,将发现即使不使用代码,也能完成不少工作. 触发器是另一个实现这种功能的例子.使用触发器,可自动完成简单的样式改变,而这通常 ...
- 87.QuerySet API使用详解:create方法
create:创建一条数据,并且保存到数据库中,这个方法相当于先用指定的模型创建一个一个对象,然后再调用这个对象的save方法,示例代码如下: from django.db import connec ...
- [浅学]POST、GET、PUT、DELETE 请求
HTTP定义了与服务器交互的不同的方法,最基本的是POST.GET.PUT.DELETE,与其比不可少的URL的全称是资源描述符,我们可以这样理解: url描述了一个网络上资源,而post.get.p ...
- ruoyi LogUtils
package com.ruoyi.framework.util; import java.io.PrintWriter; import java.io.StringWriter; import ja ...