HttpInvoker 的独到之处
在之前的几篇文章中,已经介绍了 RMI 和 Hessian,那么HttpInvoker 有什么独到之处呢?“HttpInvoker 是一个新的远程调用模型,作为 Spring 框架的一部分,能够执行基于 HTTP 的远程调用(让防火墙不为难),并使用 Java 的序列化机制(让开发者乐观其变)”(《Spring 实战(第4版)》)。
模板化的配置
在之前的几篇文章中,已经可以看到 RPC 的实现过程总是有着极为相似的模式,服务端提供服务,并且将服务声明为对应的协议服务,客户端则将声明远程服务的具体地址,从而达到远程服务的本地化。当然,Spring 帮助我们简化了那些配置。
HttpInvoker 由 Spring 提供
本文使用 Spring 4 ,具体的 Maven 依赖如下
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
服务端配置
- 先将本地的服务声明为 HttpInvoker 服务
/**
* 将本地服务声明为远程服务
* @return
*/
@Bean
public HttpInvokerServiceExporter httpInvokerExportedApiService(){
HttpInvokerServiceExporter exporter=new HttpInvokerServiceExporter();
exporter.setService(getApiService());
exporter.setServiceInterface(ApiService.class);
return exporter;
}
/**
* 注册为Spring Bean
* @return
*/
@Bean
public ApiService getApiService(){
return new ApiServiceImpl();
}
- 除此之外,还需要设置一个 url 映射,当 web 访问请求符合映射时,将会转由 HttpInvoker 服务来进行处理
/**
* 设置URL映射
*/
@Bean
public HandlerMapping hessianMapping(){
SimpleUrlHandlerMapping shm=new SimpleUrlHandlerMapping();
Properties properties=new Properties();
properties.put("/api.service", "httpInvokerExportedApiService");
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 HttpInvokerProxyFactoryBean apiService(){
HttpInvokerProxyFactoryBean proxy=new HttpInvokerProxyFactoryBean();
proxy.setServiceUrl("http://localhost:8086/httpinvoker-provider/api.service");
proxy.setServiceInterface(ApiService.class);
return proxy;
}
客户端使用 main 方法调用
需要手动初始化参数,然后获取远程代理
public static void main(String[] args) {
HttpInvokerProxyFactoryBean proxy=new HttpInvokerProxyFactoryBean();
proxy.setServiceUrl("http://localhost:8086/httpinvoker-provider/api.service");
proxy.setServiceInterface(ApiService.class);
//手动初始化参数
proxy.afterPropertiesSet();
ApiService apiService=(ApiService)proxy.getObject();
//调用
}
github 完整例子
https://github.com/Bestcxy/RPC/tree/master/httpinvoker-master
httpinvoker-api 定义接口
httpinvoker-provider 提供服务
httpinvoker-consumer 调用 httpInvoker 服务
#####客户端调用结果
启动两个web 项目,访问 http://localhost:8085/httpinvoker-consumer/
{"result":"success","name":"服务端:用户输入了姓名=jecket","model":{"userName":"jecket","age":20}}