参考up:孙哥
孙哥主页
为什么要学习这个比较老的RPC框架
-
纯粹的RPC,只解决了RPC的四个核心问题
- 网络通信
- 协议
- 序列化
- 代理
-
Java写的
-
Hessian RPC落伍了,但是他的序列化方式 Dubbo还在使用
Dubbo用的Hessian,阿里定制(Hessain Lite) Dubbo默认启动
Hessian RPC 概念
- Resin 服务器的伴生产品
- 基于Java编程语言设计的RPC框架,只支持Java编程语言使用(服务调用者和提供者都得是Java开发)
- 序列化协议(二进制)
HessianRPC设计思想
:::info
服务调用者: 客户端 SlefService
HessianProxyFactory 做服务代理
工具 参数
- 接口 OrederService--->JDK Proxy.newProxyInstance(ClassLoader,OderService,InvovationHndler)
- url
服务的接口 做成公共模块 :::
HessianRPC 的开发
准备依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<!--编译时使用-->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.32</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.9</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
<dependency>
<groupId>com.caucho</groupId>
<artifactId>hessian</artifactId>
<version>4.0.38</version>
</dependency>
</dependencies>
开发步骤
服务端(RPC远端功能提供者)
- 开发服务 :::info
- 开发Service
- DAO----Mybaits
注意 一定要定义Service的接口,自定义的类型要实现序列化接口 :::
public interface UserService {
boolean login(String name,String password);
void register(String name,String password);
}
@Slf4j
public class UserServiceImpl implements UserService {
@Override
public boolean login(String name, String password) {
log.debug("login,{},{}",name,password);
return false;
}
@Override
public void register(String name, String password) {
log.debug("name:{},password:{}",name,password);
}
}
- 发布服务 :::info
- web.xml进行配置 :::
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>userServiceRPC</servlet-name>
<servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class>
<init-param>
<param-name>home-api</param-name>
<param-value>com.huy.service.UserService</param-value>
</init-param>
<init-param>
<param-name>home-class</param-name>
<param-value>com.huy.service.UserServiceImpl</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>userServiceRPC</servlet-name>
<url-pattern>/userServiceRPC</url-pattern>
</servlet-mapping>
</web-app>
客户端(远端服务的调用者)
:::info
HessianProxyFactory
参数: 远端服务的接口 url
:::
@Slf4j
public class HessianRPCClient {
public static void main(String[] args) throws MalformedURLException {
HessianProxyFactory hessianProxyFactory=new HessianProxyFactory();
String URL="http://localhost:8080/rpc-hessian/userServiceRPC";
UserService userService = (UserService) hessianProxyFactory.create(UserService.class, URL);
boolean userServiceRet = userService.login("xiaohei", "123456");
log.debug("userServiceRet value is{}",userServiceRet);
}
}
HessianRPC核心源码分析
:::info HessoanRPC client 创建代理的方式 JDK Proxy.newProxyInstance() :::
public Object create(Class<?> api, URL url, ClassLoader loader) {
if (api == null) {
throw new NullPointerException("api must not be null for HessianProxyFactory.create()");
} else {
InvocationHandler handler = null;
handler = new HessianProxy(url, this, api);
return Proxy.newProxyInstance(loader, new Class[]{api, HessianRemoteObject.class}, handler);
}
}
:::info 代理中: 1. 通过网络Http请求,链接远端RPC服务 2. 通过流数据写出 HessianProxy#invoke()
- 通过URLConnection 进行网络链接
- 解析协议 传递数据
:::
HessianRPC 序列化
:::info Hessian 的RPC 已经过时了 但Hessian序列化方式还在使用(Dubbo) :::
- 开发
public class TestHessianSerializable {
public static void main(String[] args) throws IOException {
//Hessian序列化的目的 就是为了传输数据 基本类型 对象 Serializable 接口
/* OutputStream outputStream=new FileOutputStream("test");
Hessian2Output out=new Hessian2Output(outputStream);
out.writeObject(new User("suns","1234"));
out.flush();
outputStream.close();*/
//Hessian反序列化
InputStream inputStream=new FileInputStream("test");
Hessian2Input in=new Hessian2Input(inputStream);
User user = (User) in.readObject(User.class);
System.out.println(user);
}
}