spring之HttpInvoker

简介:   一、HttpInvoker是常用的Java同构系统之间方法调用实现方案,是众多Spring项目中的一个子项目。顾名思义,它通过HTTP通信即可实现两个Java系统之间的远程方法调用,使得系统之间的通信如同调用本地方法一般。

  一、HttpInvoker是常用的Java同构系统之间方法调用实现方案,是众多Spring项目中的一个子项目。顾名思义,它通过HTTP通信即可实现两个Java系统之间的远程方法调用,使得系统之间的通信如同调用本地方法一般。

  二、他有点类似于Java的服务远程调用RMI,但是两个基于的协议不一样。RMI是直接服务器直接的调用,需要防火墙单独放开端口。而HttpInvoker是基于http协议进行远程方法调用的。需要容器支持。

  三、RMI的实现过程参考:https://www.cnblogs.com/ll409546297/p/8948185.html

  四、我这里中间件使用的是jetty来嵌入启动的,可以参考jetty的启动方式:https://www.cnblogs.com/ll409546297/p/9338837.html

  五、HttpInvoker实现例子:

  1、服务端:

  1)提供远程调用的借口和实现类

package com.pinnet.remote;

public interface IRemoteService {

    String show();
}
package com.pinnet.remote.impl;

import com.pinnet.remote.IRemoteService;

public class RemoteServiecImpl implements IRemoteService {

    public String show() {
        System.out.println("show");
        return "show";
    }
}

  2)服务端bean的配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="remoteService" class="com.pinnet.remote.impl.RemoteServiecImpl"/>
    <bean name="/remoteService" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
        <property name="service" ref="remoteService"/>
        <property name="serviceInterface" value="com.pinnet.remote.IRemoteService"/>
    </bean>
</beans>

  3)有人会问相对于RMI怎么没有注册端口,因为这里是基于http协议,所以,是使用web服务的容器接口

  2、客户端:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="remoteService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
        <property name="serviceUrl" value="http://localhost:8090/remoteService"/>
        <property name="serviceInterface" value="com.pinnet.remote.IRemoteService"/>
    </bean>
</beans>

  端口:是服务端的容器端口,接口是公用的

  3、测试:

public static void main(String[] args) {
        ApplicationContext client = new ClassPathXmlApplicationContext("spring-httpinvoker-client.xml");
        IRemoteService remoteService = (IRemoteService) client.getBean("remoteService");
        String show = remoteService.show();
        System.out.println(show);
    }

  服务端:

  

  客户端:

  

  六、HttpInvoker源码分析(来至:https://charpty.com

  1、服务端

  1)服务端主入口由HttpInvokerServiceExporter实现,它的工作大致流程如下

   

  2)HttpInvokerServiceExporter实现了HttpRequestHandler,这使得其拥有处理HTTP请求的能力,按照Spring MVC的架构,它将被注册到HandlerMappingBeanNameMapping中,这设计到Spring MVC如何处理请求,可以关注我的相关文章。服务端的重要任务就是读取并解析RemoteInvocation,再返回RemoteInvocationResult,剩下的都只是标准IO流的读写。

  2、客户端
  1)客户端的实现也很好理解,主入口为 HttpInvokerProxyFactoryBean, 和Spring用到的众多设计相同,该类的结构使用了模板设计方法,该类提供实现了几个模板方法,整体逻辑由父类 HttpInvokerClientInterceptor的实现,主要流程如下
  

  2)我们最关心的是当我们调用接口的方法时,HttpInvoker是如何做到调用到远方系统的方法的,其实HttpInvokerProxyFactoryBean最后返回的是一个代理类(Cglib Proxy或者Jdk Proxy),我们调用接口的任何方法时,都会先执行HttpInvokerClientInterceptorinvoke()方法。

public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        if (AopUtils.isToStringMethod(methodInvocation.getMethod())) {
            return "HTTP invoker proxy for service URL [" + this.getServiceUrl() + "]";
        } else {
            RemoteInvocation invocation = this.createRemoteInvocation(methodInvocation);
            RemoteInvocationResult result = null;

            try {
                result = this.executeRequest(invocation, methodInvocation);
            } catch (Throwable var5) {
                throw this.convertHttpInvokerAccessException(var5);
            }

            try {
                return this.recreateRemoteInvocationResult(result);
            } catch (Throwable var6) {
                if (result.hasInvocationTargetException()) {
                    throw var6;
                } else {
                    throw new RemoteInvocationFailureException("Invocation of method [" + methodInvocation.getMethod() + "] failed in HTTP invoker remote service at [" + this.getServiceUrl() + "]", var6);
                }
            }
        }
    }

  六、本博客后面源码部分,部分来至https://charpty.com

 

 

相关文章
|
Java Spring 应用服务中间件
|
22天前
|
Java 测试技术 数据库
Spring Boot中的项目属性配置
本节课主要讲解了 Spring Boot 中如何在业务代码中读取相关配置,包括单一配置和多个配置项,在微服务中,这种情况非常常见,往往会有很多其他微服务需要调用,所以封装一个配置类来接收这些配置是个很好的处理方式。除此之外,例如数据库相关的连接参数等等,也可以放到一个配置类中,其他遇到类似的场景,都可以这么处理。最后介绍了开发环境和生产环境配置的快速切换方式,省去了项目部署时,诸多配置信息的修改。
|
1月前
|
Java 应用服务中间件 开发者
Java面试题:解释Spring Boot的优势及其自动配置原理
Java面试题:解释Spring Boot的优势及其自动配置原理
87 0
|
19天前
|
XML Java 数据库连接
Spring Boot集成MyBatis
主要系统的讲解了 Spring Boot 集成 MyBatis 的过程,分为基于 xml 形式和基于注解的形式来讲解,通过实际配置手把手讲解了 Spring Boot 中 MyBatis 的使用方式,并针对注解方式,讲解了常见的问题已经解决方式,有很强的实战意义。在实际项目中,建议根据实际情况来确定使用哪种方式,一般 xml 和注解都在用。
|
22天前
|
Java Spring 容器
Spring Boot 启动源码解析结合Spring Bean生命周期分析
Spring Boot 启动源码解析结合Spring Bean生命周期分析
60 11
|
1月前
|
Java 开发者 Spring
深入理解Spring Boot中的自动配置原理
深入理解Spring Boot中的自动配置原理
|
2月前
|
前端开发 Java 微服务
Spring Boot与微前端架构的集成开发
Spring Boot与微前端架构的集成开发
|
2月前
|
Java
springboot自定义拦截器,校验token
springboot自定义拦截器,校验token
109 6
|
2月前
|
Java 数据库连接 数据库
Spring Boot 集成 MyBatis-Plus 总结
Spring Boot 集成 MyBatis-Plus 总结
|
2月前
|
运维 Java 关系型数据库
Spring运维之boot项目bean属性的绑定读取与校验
Spring运维之boot项目bean属性的绑定读取与校验
36 2