欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring HTTP Invoker远程代理详解及实例

程序员文章站 2022-03-12 21:33:15
Spring HTTP Invoker远程代理过程介绍及代码实例...

一、概念

Spring HTTP Invoker一种JAVA远程方法调用框架实现,原理与JDK的RMI基本一致,所以我们先跟其它JAVA远程方法调用实现做下简单比较。

  • RMI:使用JRMP协议(基于TCP/IP),不允许穿透防火墙,使用JAVA序列化方式,使用于任何JAVA应用之间相互调用。

  • Hessian:使用HTTP协议,允许穿透防火墙,使用自己的序列化方式,支持JAVA、C++、.Net等跨语言使用。

  • Burlap: 与Hessian相同,只是Hessian使用二进制传输,而Burlap使用XML格式传输(两个产品均属于caucho公司的开源产品)。

  • Spring HTTP Invoker: 使用HTTP协议,允许穿透防火墙,使用JAVA序列化方式,但仅限于Spring应用之间使用,即调用者与被调用者都必须是使用Spring框架的应用。

既然是通过HTTP请求调用,那么客户端肯定需要一个代理用于帮忙发送HTTP请求,帮忙做对象系列化和反系列化等,Spring框架中的HttpInvokerProxyFactoryBean类处理这些杂事;

而服务器端需要一个HTTP请求处理器,帮忙处理HTTP请求已经对象系列化和反系列化工作,Spring框架中的HttpInvokerServiceExporter类就是干这活的,对于Sun JRE 6 的HTTP Server,Spring还提供了SimpleHttpInvokerServiceExporter类供选择。

二、服务端(服务提供者)

项目都是创建spring mvc项目
具体spring mvc创建流程
可浏览博主之前发布的文章
spring MVC项目的搭建

2.1 创建对外暴露的服务接口及对象

对外暴露的服务接口及对象都是需要打包成jar给客户端调用
所以一般来说,这种接口跟对象都是单独创建成一个项目
服务端跟客户端都直接导入jar进行使用

如果不想打包成jar使用
则客户端及服务端的接口及对象的包名、类名、需实现序列化都一样

person对象类

package com.service;

import java.io.Serializable;

public class Person implements Serializable {

    private static final long serialVersionUID = 6139752933642464599L;
    private String name;
    private String age;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAge() {
        return age;
    }
    public void setAge(String age) {
        this.age = age;
    }
}

IPersonService服务接口类

package com.service;

public interface IPersonService {
    Person findByName(String name);
}

2.2 服务实现类

PersonService实现接口,相关业务处理

这里不进行具体的数据库操作
只返回模拟数据

package com.service;

public class PersonService implements IPersonService {
    @Override
    public Person findByName(String name) {
        Person person = new Person();
        person.setAge("18");
        person.setName(name);
        return person;
    }
}

2.3 服务代理设置

服务端需要实例化HttpInvokerServiceExporter服务注册的一个类;
并且需要设置两个属性

service:服务实现类,也就是接口的实现类,一般都是spring的bean;
serviceInterface:服务类型,也就是服务实现类的一个接口类;

代码如下:

package com.service.util;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
import com.service.IPersonService;

public class RemotingService extends HttpServlet {

    private static final long serialVersionUID = -1017031460828010508L;
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//实例化代理服务
        HttpInvokerServiceExporterserviceExporter = new HttpInvokerServiceExporter();
      	//获取服务的实现bean
        WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
        Object service = wac.getBean("personService");
      	//设置属性
        serviceExporter.setService(service);
        serviceExporter.setServiceInterface(IPersonService.class);
        serviceExporter.afterPropertiesSet();
		
        serviceExporter.handleRequest(req, resp);
    }
}

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">
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>com.service.util.remoting</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/remote/*</url-pattern>
    </servlet-mapping>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/springContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

springContext.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <bean id="personService" class="com.service.PersonService" />  
</beans>

项目结构:
Spring HTTP Invoker远程代理详解及实例

三、客户端(服务消费者)

3.1 导入服务端的jar

<dependency>
	<groupId>com.xiao</groupId>
	<artifactId>springMVC</artifactId>
	<version>0.0.1-SNAPSHOT</version>
</dependency>

这里我服务端名称是springMVC
服务端跟客户端项目都是Spring MVC项目,所以都直接使用maven管理jar包
使用下列命令可导入jar进maven仓库

mvn install:install-file -Dfile=jar绝对路径全称 -DgroupId=项目包名 -DartifactId=项目名称 -Dversion=版本号 -Dpackaging=jar

3.2 客户端配置

因为使用的是spring自带的远程代理,需要项目是spring项目
所以客户端直接就使用默认的一个MVC配置

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">

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>WEB-INF/springContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

springContext.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    
    <!-- 搜索spring -->
    <context:component-scan base-package="com.xiao"></context:component-scan>
    <!-- 视图页面配置 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>
</beans>

3.3 远程代理测试

客户端也需要实现一个代理工厂类HttpInvokerProxyFactoryBean实现代理。
也有两个属性需要设置

serviceInterface:需要消费的服务接口类

serviceUrl:服务提供者的url

这里url可自定义,可在路径后加上调用的接口名
服务端也就能根据接口名实现不同的代理

测试类代码:

package com.xiao.controller;

import org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean;
import org.springframework.stereotype.Controller;
import com.service.IPersonService;
import com.service.Person;

public class controller {

    public static void main(String[] args) {
        String name = "小小";
        Person person = getService(IPersonService.class).findByName(name);
        assert person.getName().equals(name) : name + "与代理返回数据name不匹配";
        System.out.println(person.getName());
    }

    public static <T> T getService(Class<T> clazz) {
        HttpInvokerProxyFactoryBean bean = new HttpInvokerProxyFactoryBean();

        bean.setServiceInterface(clazz);
        String url = "http://192.168.0.161:8081/springMVC/remote";
        bean.setServiceUrl(url);
        bean.afterPropertiesSet();
        Object result = bean.getObject();

        return (T) result;
    }
}

运行后控制台可以输出person的name
测试通过

客户端项目结构
Spring HTTP Invoker远程代理详解及实例

结语

对您有帮助请帮忙点个赞
有疑问可留言评论,博主看到会进行回复
相互学习

本文地址:https://blog.csdn.net/asdluoliu/article/details/112847699