第15章 使用远程服务

一、spring远程调用概览

远程调用指的是客户端应用和服务端之间的会话(RPC)

spring支持多种远程调用技术
1.远程方法调用 RMI
2.Hessian或Burlap
3.HTTP invoker
4.JAX-RPC和JAXWS

二、使用RMI

RMI是在jdk1.1的时候就被引入进来,它为java开发者提供了一种强大的方法来实现java程序间的交互
开发和访问RMI服务很乏味和无聊,因为它涉及到好几个步骤。spring简化了RMI模型,它提供了一个代理工厂bean,能够让我们把RMI服务像本地javaBean那装配到我们的spring应用中。spring还提供了一个远程导出器,能用来简化把Spring管理的bean转换为RMI服务的工作。

1.导出RMI服务(定义RMI服务端)

传统的创建RMI服务的步骤如下:
1.编写一个服务实现类,类中的方法需要抛出RemoteException异常
2.创建一个继承于Remote的服务接口
3.运行RMI编译器,创建客户端stub类和服务端skeleton类
4.启动一个RMI注册表,以便持有这些服务
5.在RMI注册表中注册服务
而spring简化了上面的步骤:
先定义接口

package com.demo.service;

public interface HelloRMIService {
    public int  getAdd(int a, int b);  
}

实现上述接口

package com.demo.service.impl;

import com.demo.service.HelloRMIService;

public class HelloRMIServiceImpl implements HelloRMIService {

    public int getAdd(int a, int b) {
        // TODO Auto-generated method stub
        return a+b;  
    }

}

在spring配置文件中将上述的pojo配置为rmi服务类

<bean id="myRMIServer"  class="org.springframework.remoting.rmi.RmiServiceExporter">  
      <property name="serviceName" value="helloRMI"></property>  
      <property name="service" ref="helloRMIServiceImpl"></property>  
      <property name="serviceInterface" value="com.demo.service.HelloRMIService"></property>  
      <property name="registryPort" value="9999"></property>  
</bean>    

这时候就是配置为rmi服务类了

2.装配RMI服务(编写RMI客户端)

传统的RMI需要使用RMI API的Naming类从RMI注册表中查找服务,但是Spring提供了一个便捷的方式,为了方便,下面利用java-project工程作为RMI客户端作为演示。
先编写服务端相同的接口(实际应用中,一般会打成jar包)

package com.demo.service;

public interface HelloRMIService {
    public int  getAdd(int a, int b);  
}

在spring配置文件配置客户端

 <!-- 客户端 -->  
<bean id="myRMIClient"  class="org.springframework.remoting.rmi.RmiProxyFactoryBean">  
      <property name="serviceInterface" value="com.demo.service.HelloRMIService"></property>  
      <property name="serviceUrl" value="rmi://127.0.0.1:9999/helloRMI"></property>  
</bean>  

再编写客户端类

package com.demo.service;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class RMIClient {
    public static void main(String[] args) {  
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/demo/service/rmiClient.xml");  
        HelloRMIService helloRMIService =  applicationContext.getBean("myRMIClient",HelloRMIService.class);  
        System.out.println(helloRMIService.getAdd(63, 4));  
    }  
}

运行后就可以使用远程服务了
局限:RMI是一种实现远程服务交互的好办法,但是它也是存在某些限制:
1.RMI很难穿越防火墙,这是因为RMI使用任意的端口来交互,这是防火墙不允许的
2.RMI是基于java的,这意味客户端和服务端都必须要用java来进行开发
针对上述的问题,Caucho提供了两种解决方案:Hession和Burlap,下面就来看看这两种方法是如何处理的

三、使用Hession和Burlap发布远程服务

Hessian和Burlap的优势是不同的,Hession的消息是二进制的,可以移植到其他的非java语言中。Burlap的消息是XML格式的,两者的应用场景是不同的

1.使用Hessian和Burlap导出bean的功能(配置服务端)

先看spring中使用Hession:
配置Hession服务端:
先在pom.xml文件中引入相关的jar包:

<!-- https://mvnrepository.com/artifact/com.caucho/hessian -->
        <dependency>
            <groupId>com.caucho</groupId>
            <artifactId>hessian</artifactId>
            <version>4.0.38</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-remoting -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-remoting</artifactId>
            <version>2.0.8</version>
        </dependency>

定义相关的接口

package com.demo.service;

public interface HelloHessianService {
    public int  getAdd(int a, int b);  
}

下面是实现的接口:

package com.demo.service.impl;

import com.demo.service.HelloHessianService;

public class HelloHessianServiceImpl implements HelloHessianService {

    public int getAdd(int a, int b) {
        // TODO Auto-generated method stub
        return a+b;  
    }

}

接着在web.xml中配置DispatcherServlet.xml

  <servlet>
        <servlet-name>hessian</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>hessian</servlet-name>
        <url-pattern>/hessian.service</url-pattern>
    </servlet-mapping>

新建hessian.servlet.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:task="http://www.springframework.org/schema/task" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd 
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd ">
     <bean id="myService" class="com.demo.service.impl.HelloHessianServiceImpl"/>
    <!-- hessian是基于Http的二进制码传输的轻量级框架 -->
    <bean id="hessianExporter" class="org.springframework.remoting.caucho.HessianServiceExporter">
        <!-- 服务 -->
        <property name="service" ref="myService"/>
        <!--hessian没有类似rmi服务注册表,不需要用服务名注册, -->
        <!-- 绑定服务的路径 -->
        <property name="serviceInterface" value="com.demo.service.HelloHessianService"/>
    </bean>
    <!-- 2.5.6版本相应的jar包在dist/modules/spring-webmvc  -->
    <bean id="hessianMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/hessian.service">hessianExporter</prop>
            </props>
        </property>
    </bean>
    <!-- 因为hessianExporter在SpringMVC里面作为一个controller实现的,所以还需要在web.xml中配置 -->
</beans>

至此,hession服务端就配置好了
下面开始配置Burlap服务端:
先定义接口:

package com.demo.service;

public interface HelloBurlapService {
    public int  getAdd(int a, int b);  
}

实现上面的接口:

package com.demo.service.impl;

import com.demo.service.HelloBurlapService;

public class HelloBurlapServiceImpl implements HelloBurlapService {

    public int getAdd(int a, int b) {
        // TODO Auto-generated method stub
        return a+b;  
    }

}

接着在web.xml中配置DispatcherServlet.xml

 <servlet>
        <servlet-name>burlap</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>burlap</servlet-name>
        <url-pattern>/burlap.service</url-pattern>
    </servlet-mapping>

新建burlap-servlet.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:task="http://www.springframework.org/schema/task" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd 
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd ">
    <!-- 服务 ,需要引入/lib/caucho/hessian.jar -->
    <bean id="myBurlapService" class="com.demo.service.impl.HelloBurlapServiceImpl" />

    <!-- burlap是基于xml传输的轻量级框架 -->
    <bean name="burlapExporter"
        class="org.springframework.remoting.caucho.BurlapServiceExporter">
        <!-- 服务 -->
        <property name="service" ref="myBurlapService" />

        <!-- 绑定服务的路径 -->
        <property name="serviceInterface" value="com.demo.service.HelloBurlapService" />
    </bean>

    <bean id="urlMapping"
        class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/burlap.service">burlapExporter</prop>
            </props>
        </property>
    </bean>
</beans>

至此,burlap服务端就配置好

2.访问Hessian/Burlap服务(编写客户端)

先编写Hessian客户端
定义接口:

package com.demo.service;

public interface HelloHessianService {
    public int  getAdd(int a, int b);  
}

编写spring配置文件

<?xml version="1.0" encoding="UTF-8" standalone="no"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
       xmlns:aop="http://www.springframework.org/schema/aop"  
       xmlns:context="http://www.springframework.org/schema/context"  
       xmlns:jee="http://www.springframework.org/schema/jee"   
       xmlns:tx="http://www.springframework.org/schema/tx"  
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
       xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd     
       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     
       http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd     
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">  

    <!-- 客户端 -->  
   <bean id="myHessionClient" class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
        <!-- 服务URL -->
        <property name="serviceUrl" value="http://localhost:8080/hessian.service"/>
        <!-- 本地接口路径 -->
        <property name="serviceInterface" value="com.demo.service.HelloHessianService"/>
   </bean> 

</beans>  

注意:客户端也需要引入下面的jar包:

<!-- https://mvnrepository.com/artifact/com.caucho/hessian -->
        <dependency>
            <groupId>com.caucho</groupId>
            <artifactId>hessian</artifactId>
            <version>4.0.38</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-remoting -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-remoting</artifactId>
            <version>2.0.8</version>
        </dependency>

接着编写客户端:

package com.demo.service;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class HessionClient {
    public static void main(String[] args) {  
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/demo/service/hessionClient.xml");  
        HelloHessianService helloHessianService =  applicationContext.getBean("myHessionClient",HelloHessianService.class);  
        System.out.println(helloHessianService.getAdd(63, 6666));  
    }  
}

Burlap的客户端的编写也是类似的:
先定义接口

package com.demo.service;

public interface HelloBurlapService {
    public int  getAdd(int a, int b);  
}

然后在spring配置文件配置

<?xml version="1.0" encoding="UTF-8" standalone="no"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
       xmlns:aop="http://www.springframework.org/schema/aop"  
       xmlns:context="http://www.springframework.org/schema/context"  
       xmlns:jee="http://www.springframework.org/schema/jee"   
       xmlns:tx="http://www.springframework.org/schema/tx"  
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
       xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd     
       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     
       http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd     
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">  

    <!-- 客户端 -->  
   <bean id="myBurlapClient" class="org.springframework.remoting.caucho.BurlapProxyFactoryBean">
        <!-- 服务URL -->
        <property name="serviceUrl" value="http://localhost:8080/burlap.service"/>
        <!-- 本地接口路径 -->
        <property name="serviceInterface" value="com.demo.service.HelloBurlapService"/>
   </bean> 

</beans>  

接着编写burlap客户端:

package com.demo.service;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BurlapClient {
    public static void main(String[] args) {  
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/demo/service/burlapClient.xml");  
        HelloBurlapService helloBurlapService =  applicationContext.getBean("myBurlapClient",HelloBurlapService.class);  
        System.out.println(helloBurlapService.getAdd(63, 236));  
    }  
}

至此,两种客户端都编写完毕,这时候是可以调用远程的服务了
上面的例子遗憾的是还没有体现出hession和burlap的区别。

Hession和Burlap是基于HTTP开发的,它能解决RMI防火墙的问题,但是如果数据模型非常复杂的话,那么Hession和Burlap是无法胜任的,这时候又有另外一种解决方法,那就是使用Spring的HTTP invoker

四、使用Spring的HttpInvoker

HttpInvoder的配置和Hession还有Burlap是非常的相似的

1.将bean导出为HttpInvoker服务(配置HttpInvoker服务)

定义接口:

package com.demo.service;

public interface HelloInvokerService {
    public int  getAdd(int a, int b);  
}

实现接口

package com.demo.service.impl;

import com.demo.service.HelloInvokerService;

public class HelloInvokerServiceImpl implements HelloInvokerService {

    public int getAdd(int a, int b) {
        // TODO Auto-generated method stub
        return a+b;  
    }

}

在web.xml配置Servlet

  <servlet>
        <servlet-name>invoker</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>3</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>invoker</servlet-name>
        <url-pattern>/invoker.service</url-pattern>
    </servlet-mapping>

编写invoker-servlet.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:task="http://www.springframework.org/schema/task" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd 
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd ">
    <bean id="myInvokerService" class="com.demo.service.impl.HelloInvokerServiceImpl"/>
    <bean id="invokerExporter" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
        <!-- 服务 -->
        <property name="service" ref="myInvokerService"/>
        <!-- 绑定服务的路径 -->
        <property name="serviceInterface" value="com.demo.service.HelloInvokerService"/>
    </bean>
    <!-- 2.5.6版本相应的jar包在dist/modules/spring-webmvc  -->
    <bean id="invokerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/invoker.service">invokerExporter</prop>
            </props>
        </property>
     </bean>
</beans>

至此,HttpInvoker就配置完毕了

2.通过Http访问服务(编写invoker客户端)

定义相同的接口:

package com.demo.service;

public interface HelloInvokerService {
    public int  getAdd(int a, int b);  
}

编写Spring配置文件

<?xml version="1.0" encoding="UTF-8" standalone="no"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
       xmlns:aop="http://www.springframework.org/schema/aop"  
       xmlns:context="http://www.springframework.org/schema/context"  
       xmlns:jee="http://www.springframework.org/schema/jee"   
       xmlns:tx="http://www.springframework.org/schema/tx"  
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
       xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd     
       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     
       http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd     
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">  

    <!-- 客户端 -->  
   <bean id="myInvokerClient" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
        <!-- 服务URL -->
        <property name="serviceUrl" value="http://localhost:8080/invoker.service"/>
        <!-- 本地接口路径 -->
        <property name="serviceInterface" value="com.demo.service.HelloInvokerService"/>
   </bean> 

</beans>  

编写客户端

package com.demo.service;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class InvokerClient {
    public static void main(String[] args) {  
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/demo/service/invokerClient.xml");  
        HelloInvokerService helloInvokerService =  applicationContext.getBean("myInvokerClient",HelloInvokerService.class);  
        System.out.println(helloInvokerService.getAdd(63, 236111));  
    }  
}

至此,HttpInvoker客户端编写完毕

五、发布和使用Web服务

这是关于webservice的知识点,详细看如下的文章(暂时未完成!)

参考文献

  1. Spring整合hessian和burlap及自带的Invoker
  2. Java RMI实现以及Spring封装RMI实现小结
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值