Hessian遠端呼叫框架進階教程(一) Hessian介紹JAVA使用Hessian進行程式設計例項
Hessian介紹
Dubbo提供了RPC服務、服務治理,而Spring Cloud則涵蓋了微服務的方方面面,服務治理只是其中的一個方面,關於二者的比較,可以參看程式猿DD的一篇部落格–微服務架構的基礎框架選擇:Spring Cloud還是Dubbo?。儘管國內大部分互初創聯網公司幾乎是用Zookeeper+Dubbo搭建的架構,而Spring Cloud商用成熟產品少之又少,但是筆者個人覺得未來短時間之內Spring Cloud必火,各位不要錯過了。轉入正題,我們已經有了Dubbo、Spring Cloud為什麼還要了解Hessian呢?因為
- Hessian很簡單,理解其使用和機制之後,有助於你理解其他微服務框架(這是重點,本教程理解的越深越細,對學習微服務框架幫助越大這也是我們所期望的)
- Hessian是基於 Http 協議進行傳輸的,初中級程式猿都很熟悉的通訊協議
- Hessian是一種RPC框架,就是遠端方法呼叫,一個服務中某個類可以呼叫其他服務的某個類的某個方法
那麼接下來就好理解了,Hessian是一個使用Http協議進行遠端方法呼叫的框架。
使用Http協議,必須有一個Web服務(Hessian服務端或者叫提供者–dubbo的叫法);
應用端亦即消費端通過方法呼叫的形式獲得代理物件,呼叫服務端的介面實現方法;
應用端和服務端都需要持有公共服務的介面資訊;
使用hessian需要引入依賴:
<!-- 引入hessian依賴 -->
<dependency >
<groupId>com.caucho</groupId>
<artifactId>hessian</artifactId>
<version>4.0.38</version>
</dependency>
我們以一個簡單的例子入門:獲取一個使用者的資訊。
- 公共服務介面類:中間工程jar包middleProject,僅僅包含hello方法和一個重新設定使用者年齡的方法。
- 服務端:構建成一個web服務,只有一個介面實現類需要依賴middleProject,需要配置成hessian服務。
- 客戶端:同樣依賴middleProject,使用hessian代理工廠例項化公共介面服務類,然後呼叫該例項的方法。
公共介面服務(打包成jar,讓服務端、client端都需要依賴)
該介面定義了兩個簡單方法:
- helloWorld方法,返回一個簡單字串
- getMyInfo方法,傳入一個複雜物件,並重新設定其age屬性,再將新的user物件返回給client端。
HelloService.java
package org.byron4j.hessian.service;
import org.byron4j.hessian.entity.User;
/**
* @author Byron.Y.Y
* @optDate 2016年12月6日
* This class is for ...
*/
public interface HelloService {
public String helloWorld(String message);
public User getMyInfo(User user);
}
使用者類是一個簡單的POJO,需要實現Serializable介面以序列化
User.java
package org.byron4j.hessian.entity;
import java.io.Serializable;
import java.util.Map;
/**
* @author Byron.Y.Y
* @optDate 2016年12月6日
* This class is for ...
*/
public class User implements Serializable{
/**
*
*/
private static final long serialVersionUID = -1352128884522619903L;
private String userName;
private int age;
private Map<String, Object> detailData;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Map<String, Object> getDetailData() {
return detailData;
}
public void setDetailData(Map<String, Object> detailData) {
this.detailData = detailData;
}
}
公共服務需要打包成jar包,hessian服務端、client端都需要依賴該jar;或者使用maven構建的話將公共服務需要打包成jardeploy到私服中,hessian服務端、client端都通過maven座標引入依賴(本系列文章採取的方式)。
Hessian服務端
服務端必須暴露服務,我們將其發構建成一個web服務,在web.xml中配置指定hessian服務的介面以及具體的實現服務、servlet;該工程只有一個實現HelloService介面的類HelloServiceImpl並且繼承自HessianServlet。
HelloServiceImpl.java
package org.byron4j.hessian.service.impl;
import org.byron4j.hessian.entity.User;
import org.byron4j.hessian.service.HelloService;
import com.caucho.hessian.server.HessianServlet;
/**
* @author Byron.Y.Y
* @optDate 2016年12月6日
*
*/
public class HelloServiceImpl extends HessianServlet implements HelloService{
/**
*
*/
private static final long serialVersionUID = -3537274030227675984L;
@Override
public String helloWorld(String message) {
return "Hello, " + message;
}
@Override
public User getMyInfo(User user) {
if(null == user){ return new User(); }
user.setAge(99);
return user;
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>hessian-showcase</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>hessian-service</servlet-name>
<servlet-class>
com.caucho.hessian.server.HessianServlet
</servlet-class>
<init-param>
<param-name>home-class</param-name>
<param-value>
<!-- 服務實現類 -->
org.byron4j.hessian.service.impl.HelloServiceImpl
</param-value>
</init-param>
<init-param>
<param-name>home-api</param-name>
<!-- 服務介面 -->
<param-value>
org.byron4j.hessian.service.HelloService
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hessian-service</servlet-name>
<url-pattern>/hessian</url-pattern>
</servlet-mapping>
</web-app>
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.byron4j</groupId>
<artifactId>hessian</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>hessian</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- 引入hessian依賴 -->
<dependency>
<groupId>com.caucho</groupId>
<artifactId>hessian</artifactId>
<version>4.0.38</version>
</dependency>
<!-- 引入介面服務定義(公共服務介面jar包) -->
<dependency>
<groupId>org.byron4j</groupId>
<artifactId>hessianMiddleJar</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- 引入servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>3.0-alpha-1</version>
</dependency>
</dependencies>
<build>
<finalName>hessionDemo</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Hessian Client端
client端同樣需要依賴公共服務jar,該專案只有一個單元測試類HessianClient。使用HessianProxyFactory建立介面服務
HessianProxyFactory factory = new HessianProxyFactory();
HelloService helloService = (HelloService) factory.create(HelloService.class, url);
helloService.helloWorld("kitty!")
HessianClient.java
package org.byron4j.hessionClient;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.byron4j.hessian.entity.User;
import org.byron4j.hessian.service.HelloService;
import org.junit.Test;
import com.caucho.hessian.client.HessianProxyFactory;
/**
* Hello world!
*
*/
public class HessianClient
{
static ExecutorService es = Executors.newFixedThreadPool(10);
/**
* 測試hessian服務是否可用,並要求在2秒內獲得響應
* @throws MalformedURLException
*/
@Test//(timeout = 2000)
public void testService4Success() throws MalformedURLException {
String url = "http://localhost:8080/hessionDemo/hessian";
System.out.println("請求的服務端地址:" + url);
HessianProxyFactory factory = new HessianProxyFactory();
HelloService helloService = (HelloService) factory.create(HelloService.class, url);
System.out.println("服務端返回結果為:" + helloService.helloWorld("kitty!"));
HashMap<String, Object> detailData = new HashMap<String, Object>();
detailData.put("isMarried", "N");
detailData.put("gender", "F");
User user = new User();
user.setAge(18);
user.setUserName("OYY");
user.setDetailData(detailData);
int time = 100000;
long startTime = System.currentTimeMillis();
for(int i = 0; i< time; i++){
es.execute(new Runnable() {
@Override
public void run() {
helloService.getMyInfo(user);
}
});
}
System.out.println(time + "次呼叫耗時:" + (System.currentTimeMillis() - startTime));
System.out.println("+--獲得複雜物件:" );
System.out.println(" +--新年齡:" + helloService.getMyInfo(user).getAge());
System.out.println(" +--隱私資訊:" + helloService.getMyInfo(user).getDetailData());
}
}
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.byron4j</groupId>
<artifactId>hessionClient</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>hessionClient</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- 引入hessian依賴 -->
<dependency>
<groupId>com.caucho</groupId>
<artifactId>hessian</artifactId>
<version>4.0.38</version>
</dependency>
<!-- 引入介面服務定義(公共服務介面jar包) -->
<dependency>
<groupId>org.byron4j</groupId>
<artifactId>hessianMiddleJar</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>hessionClientDemo</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
例項執行結果
執行client單元測試結果如下,本例項還增加了一個執行緒例項用於測試單執行緒高訪問量、多執行緒多訪問量使用hessian RMI呼叫的時間。
請求的服務端地址:http://localhost:8080/hessionDemo/hessian
服務端返回結果為:Hello, kitty!
100000次呼叫耗時:33
+--獲得複雜物件:
+--新年齡:99
+--隱私資訊:{isMarried=N, gender=F}