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 {@Overridepublic 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/beanshttp://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/beanshttp://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
?
轉載于:https://www.cnblogs.com/zhaojiatao/p/8908335.html
總結
以上是生活随笔為你收集整理的hessian学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle 查询表空间路径
- 下一篇: MRTG在Windows平台的安装及使用