(四)远程服务:Hessian 服务实现远程调用

前言

在很久之前, 我们一起领略了 RMI 提供远程服务的过程
https://blog.csdn.net/bestcxx/article/details/79488165
本篇我们继续深入下去,了解 Hessian 提供远程服务的过程

相比 RMI 而言,Hessian 是跨语言的

RMI 是 Java 语言自己提供的远程调用过程解决方法,它要求服务的提供者和调用者都必须是 Java 语言,而由于 Hessian 对外而言类似于一个 http 服务,所以可以跨语言访问。延伸来说,由于 RMI 需要注册端口和一个随机分配的数据通信端口,导致其会遇到防火墙问题,而 Hessian 借助于 http 服务,可以避免这个问题。

Hessian 基于二进制消息通信

和 RMI 一样,Hessian 也是通过二进制消息进行通信的。

序列化的问题

Hessian 的序列化机制不同于 Java 的序列化机制,Hessian 的序列化机制相对而言更加快捷,但是可靠性不如java,因为 Hessian 的序列化机制是私有的,所以造成其序列化信息并没有携带全部的信息,这导致在处理复杂对象的时候有时会出现问题。

Spring 4 结合 Hessian 4

Maven 依赖引入 Hessian 包-服务端和客户端

  <dependency>
	    <groupId>com.caucho</groupId>
	    <artifactId>hessian</artifactId>
	    <version>4.0.38</version>
	</dependency>
服务端的特殊配置
  • 类似于 RMI 服务的发布,Hessian 服务的发布也需要先将本地的服务声明为 Hessian 服务
/**
	 * 注册为远程服务
	 * @return
	 */
	@Bean
	public HessianServiceExporter hessianExportedApiService(){
		HessianServiceExporter exporter=new HessianServiceExporter();
		exporter.setService(getApiService());
		exporter.setServiceInterface(ApiService.class);
		return exporter;
	}	
	/**
	 * 注册为Spring Bean
	 * @return
	 */
	@Bean 
	public ApiService getApiService(){
		return new ApiServiceImpl();
	}
  • 除此之外,还需要设置一个 url 映射,当 web 访问请求符合映射时,将会转由 Hessian 服务来进行处理
/**
	 * 设置URL映射
	 */
	@Bean
	public HandlerMapping hessianMapping(){
		SimpleUrlHandlerMapping shm=new SimpleUrlHandlerMapping();
		Properties properties=new Properties();
		properties.put("/api.service", "hessianExportedApiService");
		shm.setMappings(properties);
		return shm;
	}
  • 最后服务端是一个web工程,所以附带web.xml 的内容
<servlet-mapping>  
    <servlet-name>springservlet</servlet-name>  
    <url-pattern>/</url-pattern> 
    <!--  <url-pattern>*.service</url-pattern>   -->
</servlet-mapping>
客户端的调用

客户端的调用过程相对服务端简单了许多

/**
	 * 为远程服务设置代理
	 * @return
	 */
	@Bean
	public HessianProxyFactoryBean apiService(){
		HessianProxyFactoryBean proxy=new HessianProxyFactoryBean();
		proxy.setServiceUrl("http://localhost:8086/hessian-provider/api.service");
		proxy.setServiceInterface(ApiService.class);
		return proxy;
	}
  • github 完整例子

https://github.com/Bestcxy/RPC/tree/master/hessian
hessian-api 定义接口
hessian-provider 提供服务
hessian-consumer 调用Hessian 服务

  • 调用结果

启动两个web 项目,访问 http://localhost:8085/hessian-consumer/

{"result":"success","name":"服务端:用户输入了姓名=jecket","model":{"userName":"jecket","age":20}}
关于 Hessian 远程服务的测试

当 Hessian 服务启动之后,我们可以通过 Spring 的测试体系对接口进行测试(可以参考 Junit 使用集合),也可以使用 HessianProxyFactory 直接对远程服务进行测试,而且后者会更加简化。这个理由给出 HessianProxyFactory 测试远程接口的方法

package com.bestcxx.stu.rpc.hessian.consumer;

import java.net.MalformedURLException;

import org.junit.Test;

import com.bestcxx.stu.rpc.hessian.api.service.ApiService;
import com.caucho.hessian.client.HessianProxyFactory;
/**
 * 使用 HessianProxyFactory 直接测试远程接口的调用
 * @author Jecket
 *
 */
public class ApiServiceTest {
	
	@Test
	public void testGetName(){
		HessianProxyFactory hessianProxyFactory=new HessianProxyFactory();
		ApiService apiService;
		try {
			apiService=(ApiService) hessianProxyFactory.create(ApiService.class, "http://localhost:8086/hessian-provider/api.service");
			System.out.println(apiService.getName("Jecket"));
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
一个邪门的问题:客户端可以独立写api接口调用服务吗?

标题还不太完整,我再具体阐述一下。
本文的例子中,服务端和客户端都依赖 hessian-api项目,该项目定义了接口和抽象方法,实体等信息。
hessian-provider 提供接口的实现,并发布为 hessian服务,hessian-consumer 通过 hessian-api 中提供的接口和实体来获取 hessian 服务,问,加入hessian-conusmer不依赖 hessian-api,而是在自己的项目中写一套其原本依赖的 接口和实体等,可不可行?
经过实验发现,是可以的,并且这种情况 Model 的序列号不同也不会有影响。
这样做的坏处很明显,就是客户端和服务端的api分离了,加入服务端变更,客户端不知道,但是可以作为一种知识扩充——Java 用包路径+类名+类加载器来唯一限定一个类。

Spring为各种远程访问技术提供集成工具类。Spring远程访问通过使用普通POJOs,能更容易的开发远程访问服务。目前,Spring远程访问的主要技术如下: 1. 远程调用RMI(Remote Method Invocation): 通过使用 RmiProxyFactoryBean 和 RmiServiceExporter,并且,Spring支持两个传统的RMI(使用 java.rmi.Remote接口和java.rmi.RemoteException)和通过RMI调用器实现的暴露远程调用(支持任何Java接口)。 2. Spring的HTTP调用器(Spring’s Http Invoker): Spring提供了一种特殊的允许通过HTTP进行Java串行化的远程调用策略,支持任意Java接口(就像RMI调用器)。相对应的支持类是 HttpInvokerProxyFactoryBean和 HttpInvokerServiceExporter。 3. Hessian: 通过 HessianProxyFactoryBean 和 HessianServiceExporter,可以使用Caucho提供的基于HTTP的轻量级二进制协议来透明地暴露服务。 4. Burlap: Burlap是Caucho的另外一个子项目,可以作为Hessian基于XML的替代方案。Spring提供了诸如 BurlapProxyFactoryBean 和 BurlapServiceExporter 的支持类。 5. JAX RPC: Spring通过JAX-RPC远程Web服务提供支持(J2EE 1.4's web service API)。 6. JAX-WS:Spring通过JAX-WS为远程Web服务提供支持(the successor of JAX-RPC, as introduced in Java EE 5 and Java 6)。 7. JMS:远程访问通过类JmsInvokerServiceExporter和JmsInvokerProxyFactoryBean使用JMS的底层协议实现。 二. 远程访问------RMI 1. RMI远程访问基本流程 1). 服务端定义远程访问接口; 2). 服务端通过RmiServiceExporter暴露服务接口 3). 客户端定义与服务端已暴露的相同接口 4). 客户端通过RmiProxyFactoryBean调用服务接口
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值