hessian学习笔记
一、hessian是什么
Hessian是一個(gè)輕量級(jí)的remoting onhttp工具,使用簡(jiǎn)單的方法提供了RMI的功能。 相比WebService,Hessian更簡(jiǎn)單、快捷。采用的是二進(jìn)制RPC協(xié)議,因?yàn)椴捎玫氖嵌M(jìn)制協(xié)議,所以它很適合于發(fā)送二進(jìn)制數(shù)據(jù)。——百度百科
?
學(xué)習(xí)hessian,必須知道什么是RPC。
實(shí)現(xiàn)RPC,必須解決如下幾個(gè)問(wèn)題:
1、通訊問(wèn)題。
2、尋址問(wèn)題。
3、序列化與反序列化。
帶著這三個(gè)問(wèn)題我們一起來(lái)探究一下hessian;
?
二、hessian怎么使用
首先,大家去下載源碼,并導(dǎo)入到idea中打開(kāi);
https://github.com/zhaojiatao/learn_hessian
項(xiàng)目結(jié)構(gòu):
--learn_hessian
----api 客戶端和服務(wù)端均共同引用的接口api
----client 客戶端調(diào)用demo,包括本地直接通過(guò)代理對(duì)象調(diào)用以及使用spring集成方式調(diào)用
----webserver 通過(guò)傳統(tǒng)servlet方式提供服務(wù)
----webserver_spring 與spring集成 提供服務(wù)
?
2.1服務(wù)端搭建:
2.1.1傳統(tǒng)serlet方式搭建
在web.xml中配置HessianServlet,
指明服務(wù)地址:/hessian
及其實(shí)現(xiàn)類: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方式集成發(fā)布服務(wù)
首先在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來(lái)處理請(qǐng)求;
<?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客戶端調(diào)用
2.2.1使用傳統(tǒng)方式調(diào)用遠(yuǎn)程服務(wù)
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方式調(diào)用
新建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的使用是很簡(jiǎn)單的。大家自己照著代碼敲一下就可以。
?
三、探究一下hessian的細(xì)節(jié)
回到文章開(kāi)始提出的問(wèn)題,即rpc框架需要解決的問(wèn)題,看看hessian如何解決的。
3.1.通訊問(wèn)題:
我們先看看客戶端在發(fā)起遠(yuǎn)程請(qǐng)求前都經(jīng)歷了什么:
首先,客戶端通過(guò)代理工廠對(duì)象HessianProxyFactory的create方法創(chuàng)建代理對(duì)象;
在create方法里可以看到,該代理對(duì)象在執(zhí)行時(shí)的handler是通過(guò)HessianProxy代理對(duì)象的invoke方法來(lái)執(zhí)行;典型的動(dòng)態(tài)代理;
?
?在invoke方法中:
通過(guò)String methodName = method.getName();得到方法名
通過(guò)sendRequest方法取得和服務(wù)端的連接HessianConnection對(duì)象;
跟蹤sendRequest方法,我們發(fā)現(xiàn):
發(fā)現(xiàn),hessian是使用http協(xié)議進(jìn)行網(wǎng)絡(luò)通信;
?在is = getInputStream(conn);處等待服務(wù)端返回的響應(yīng);
?
?3.2 尋址問(wèn)題
我們跟蹤這里:
我們得出結(jié)論:hessian使用lookup方法來(lái)尋找遠(yuǎn)程服務(wù);
?
3.3序列化與反序列化
我們繼續(xù)看剛剛跟蹤的客戶端調(diào)用時(shí)執(zhí)行的HessianProxy對(duì)象的invoke方法,
進(jìn)入其中的
conn = sendRequest(mangleName, args);
再進(jìn)入
out.call(methodName, args);
再進(jìn)入
writeObject(args[i]);
?進(jìn)入其Hessian2Output實(shí)現(xiàn)中
最終看到了hessian如何進(jìn)行序列化:
serializer.writeObject(object, this);
?
?
至此,我們也可以梳理一下hessian客戶端動(dòng)態(tài)代理的執(zhí)行流程:
?
我們?cè)賮?lái)看看服務(wù)端的執(zhí)行細(xì)節(jié):
通過(guò)后臺(tái)的代碼,可見(jiàn)我們所有的工作都圍繞在HessianServlet在展開(kāi)。該Servlet中有兩個(gè)比較重要的方法:init()、service();
init方法初始化服務(wù)和服務(wù)對(duì)象,主要分為3步:
通過(guò)home-class或者service-class創(chuàng)建服務(wù)端的實(shí)現(xiàn)類實(shí)例;
init方法還會(huì)創(chuàng)建HessianSkeleton對(duì)象,這是Hessian服務(wù)端的核心功能部分。
HessianSkeleton繼承自AbstractSkeleton,其構(gòu)造方法,將會(huì)從實(shí)現(xiàn)類中抽取方法和方法的Method對(duì)象,并且存儲(chǔ)到_methodMap中。
對(duì)于一個(gè)Servlet來(lái)說(shuō)其service方法是對(duì)外提供服務(wù)的方法:
最主要的是調(diào)用HessianSkeleton對(duì)象的invoke方法。注意,Servlet實(shí)例中有兩個(gè)HessianSkeleton變量,分別是:_objectSkeleton和 _homeSkeleton,
invoke方法:
首先從HessianInput對(duì)象中獲取到Method信息,獲取到真正的service對(duì)象。
根據(jù)反射機(jī)制,調(diào)用service對(duì)象的invoke方法,獲取到返回值。
最后調(diào)用HessianOutput對(duì)象將結(jié)果寫回到調(diào)用方。
?
?
?
?
?本文參考:
https://blog.csdn.net/sunwei_pyw/article/details/74002351
https://www.cnblogs.com/happyday56/p/4268249.html
?
轉(zhuǎn)載于:https://www.cnblogs.com/zhaojiatao/p/8908335.html
總結(jié)
以上是生活随笔為你收集整理的hessian学习笔记的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: oracle 查询表空间路径
- 下一篇: MRTG在Windows平台的安装及使用