日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Hessian 源码简单分析

發布時間:2023/12/1 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Hessian 源码简单分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Hessian 源碼簡單分析

Hessian 是一個rpc框架, 我們需要先寫一個服務端, 然后在客戶端遠程的調用它即可。

?

服務端:

服務端通常和spring 做集成。

首先寫一個接口:

public interface HelloService {
void sayHello(String name);
}

然后一個實現,實現使用@Service("helloService") ? 實現spring bean注冊。

@Service("helloService")
public class HelloServiceImpl implements HelloService {
@Override
public void sayHello(String name) {
System.out.println("Hello " + name + "!");
}
}

spring xml配置中,通過org.springframework.remoting.caucho.HessianServiceExporter 完成服務的暴露: <!-- Name保持與web.xml中的一致,web.xml下文中描述 -->
<bean name="HelloServiceExporter"
class="org.springframework.remoting.caucho.HessianServiceExporter">
<!-- service的ref與HelloServiceImpl中@Service中配置的一致 -->
<property name="service" ref="helloService" />
<!-- 接口的路徑 -->
<property name="serviceInterface"
value="hessian.HelloService" />
</bean> web.xml 的關鍵配置: <servlet>
<!-- servlet-name保持與spring-hessian.xml中一致 -->
<servlet-name>HelloServiceExporter</servlet-name>
<servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServiceExporter</servlet-name>
<url-pattern>/HelloService</url-pattern>
</servlet-mapping> HessianServiceExporter 有兩個關鍵的屬性: serviceInterface 和 service
serviceInterface 是必須是一個接口,也就是服務,值必須是一個接口的全路徑FQN
service 是具體的實現bean,是一個實例的引用

HttpRequestHandlerServlet extends HttpServlet HttpRequestHandlerServlet 的關鍵代碼是: protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
LocaleContextHolder.setLocale(request.getLocale());

try {
this.target.handleRequest(request, response);
} catch (HttpRequestMethodNotSupportedException var8) {
String[] supportedMethods = var8.getSupportedMethods();
if (supportedMethods != null) {
response.setHeader("Allow", StringUtils.arrayToDelimitedString(supportedMethods, ", "));
}

response.sendError(405, var8.getMessage());
} finally {
LocaleContextHolder.resetLocaleContext();
}

}

其實就是調用了 HessianServiceExporter 的handler 方法,HessianServiceExporter 的關鍵代碼是: public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (!"POST".equals(request.getMethod())) {
throw new HttpRequestMethodNotSupportedException(request.getMethod(), new String[]{"POST"}, "HessianServiceExporter only supports POST requests");
} else {
response.setContentType("application/x-hessian");

try {
this.invoke(request.getInputStream(), response.getOutputStream());
} catch (Throwable var4) {
throw new NestedServletException("Hessian skeleton invocation failed", var4);
}
}
}

代碼關系是:

HessianServiceExporter extends HessianExporter implements HttpRequestHandler
HessianExporter extends RemoteExporter implements InitializingBean

HessianExporter has a HessianSkeleton
HessianSkeleton extends AbstractSkeleton

HessianSkeleton 的invoke 方法實現關鍵的request處理

具體來說:

HessianInput extends AbstractHessianInput
HessianOutput extends AbstractHessianOutput

HessianInput 有提供 readHeader、readMethod、readMethodArgLength、readBytes、readInt、readLong、readString/readDouble/readObject、 readCall、 startCall、completeCall、readReply、startReply、completeReply 等方法

HessianOutput 有writeBytes Int long , Double,String, Object, writeReply 等方法

req 獲取 InputStream, res 獲取OutputStream。

HessianInput 從 req 中讀取 方法,參數, 然后method 反射調用 service, 然后通過 HessianOutput 寫回結果

in.completeCall();
out.writeReply(result); // 發送處理結果到 遠程客戶端
out.close();

這樣, 就完成了服務端的編寫,看起來還是比較簡單的。


客戶端:

因為Hessian服務端暴露的服務實際上是一個基于http實現通信的。 故我們需要通過http 調用?Hessian。

客戶端可以是一個web應用,也可以是一個簡單的main:

方式1,通過HessianProxyFactory: public static void main(String[] args) {
try {
String url = "http://localhost:8080/HelloService";
HessianProxyFactory factory = new HessianProxyFactory();
HelloService helloService = (HelloService) factory.create(
HelloService.class, url);
helloService.sayHello("張三");
} catch (Exception e) {
e.printStackTrace();
}
}
稍微查看一下源碼,我們就會發現:

HessianProxy implements InvocationHandler, Serializable 可見 hessian 是使用jdk 動態代理實現的, 故我們需要一個接口

HessianURLConnection extends AbstractHessianConnection implements HessianConnection

HessianURLConnection 有一個 java.net.URLConnection ?, 可見Hessian 的通信主要就是通過http, 具體是 URLConnection實現的。

HessianProxy has a HessianProxyFactory
HessianProxyFactory has a HessianConnectionFactory
HessianProxyFactory 用來獲取conn: conn = this._factory.getConnectionFactory().open(this._url);
HessianProxy relate to HessianConnection

?

?具體來說是這樣的:

create 返回的是一個代理, return Proxy.newProxyInstance(loader, new Class[]{api, HessianRemoteObject.class}, handler);

HessianProxy 的invoke 是關鍵:


sendRequest 方法
os = conn.getOutputStream(); 通過conn 返回OutputStream

OutputStream os 強制轉換為?AbstractHessianOutput, 然后

out.call(methodName, args); // 發送數據到 遠程服務端
out.flush();
conn.sendRequest(); // 返回一個statusMessage?
is = httpConn.getInputStream(); // 通過conn獲取InputStream,


conn = this.sendRequest(mangleName, args);
is = conn.getInputStream(); // 通過sendRequest發送完數據后, 就可以通過conn 獲取遠程的返回的數據了。

InputStream的is 轉換為 AbstractHessianInput 后, 然后就可以 readObject
value = in.readObject(method.getReturnType()); // readObject 最終返回了 遠程調用的結果。 至此,單次 rpc 結束

?

?

方式2,通過HessianProxyFactoryBean: public static void main(String[] args) {
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring-servlet.xml");
HelloService ser = (HelloService) classPathXmlApplicationContext.getBean("testHessianService");
ser.sayHello("lk AA");
}

其實也就是把前面的HessianProxyFactory 集成到了spring,封裝成了bean

HessianProxy implements InvocationHandler, Serializable 可見 hessian 是使用jdk 動態代理實現的, 故我們需要一個接口

HessianURLConnection extends AbstractHessianConnection implements HessianConnection

HessianProxyFactoryBean extends HessianClientInterceptor implements FactoryBean<Object>

HessianClientInterceptor extends UrlBasedRemoteAccessor implements MethodInterceptor

HessianClientInterceptor has a HessianProxyFactory

HessianClientInterceptor 定義hessianProxy:有一個屬性: private Class serviceInterface;
serviceInterface 定義serviceInterface:有一個屬性: private Class serviceInterface;
UrlBasedRemoteAccessor 定義serviceUrl:有一個屬性: private String serviceUrl;

hessianProxy 是通過proxyFactory(也就是HessianProxyFactory)創建, 可見, HessianProxyFactoryBean 還是通過HessianProxyFactory來完成的主要工作的。

簡單說,其實就是 spring 通過反射的調用proxyFactory 的遠程方法。

?

當然,實際使用的時候, 我們不會使用?ClassPathXmlApplicationContext, 它僅僅是在測試環境中使用。

posted on 2017-08-15 13:10 CanntBelieve 閱讀(...) 評論(...) 編輯 收藏

轉載于:https://www.cnblogs.com/FlyAway2013/p/7364576.html

總結

以上是生活随笔為你收集整理的Hessian 源码简单分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。