Java后台框架--Spring与远程方法调用

org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter 实现远程服务调用

(1)httpinvoker方式 服务器客户端都是spring时推荐这种方式

服务端 必须要实现 bean实体类  service接口类  serviceImpl服务实现类

客户端只需拷贝 bean 实体类  service接口类(注意 ,客户端 bean,service类要和服务端bean,service类包路径相同,比如都是

com.hlzt.csm.model.DataPlatFormCountBean,不然会报找不到类,而且 bean要序列化  public class DataPlatFormCount implements Serializable;
如果服务端有 序列化的private static final long serialVersionUID = 1L号,客户端也必须有,如果服务端没有此id,客户端也不要有此id,不然会出错。service类的包路径也要相同,最好服务端写好后直接把实体类和service服务接口类打包,拷贝到客户端,以免造成两端不同。


服务器端要在spring-mvc配置文件 spring-mvc-servlet.xml中加入以下(注意是在spring-mvc的配置文件中,不是spring的配置文件)

[html]  view plain  copy
  1. <beans xmlns="http://www.springframework.org/schema/beans"  
  2.     xmlns:context="http://www.springframework.org/schema/context"  
  3.     xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="  
  5.         http://www.springframework.org/schema/beans       
  6.         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  7.         http://www.springframework.org/schema/context   
  8.         http://www.springframework.org/schema/context/spring-context-3.0.xsd  
  9.         http://www.springframework.org/schema/mvc  
  10.         http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">  
  11.      
  12.     <!-- 启用spring mvc 注解 -->  
  13.     <mvc:annotation-driven />  
  14.    <!-- 设置使用注解的类扫描的包 -->  
  15.     <context:component-scan base-package="com.hlzt.csm" />  
  16.       
  17.      
  18.       
  19.      <!--不被spring mvc过滤器 DispatcherServlet,前提文件不能放在WEB-INF下,引用必须使用jstl的c标签-->  
  20.       <mvc:default-servlet-handler/>  
  21.     
  22.   <!--指定自定义  <mvc:default-servlet-handler default-servlet-name="StaticServlet"/> -->  
  23.       
  24.      <!-- 指定静态文件的路径映射  可以访问 WEB-INF下 访问直接src=static1/js/1.js-->  
  25.   <!-- <mvc:resources mapping="/static1/**" location="/WEB-INF/static/"/>  -->  
  26.        
  27.      <!-- 对转向页面的路径解析。prefix:前缀, suffix:后缀 -->  
  28. <!--     <bean  
  29.         class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
  30.         <property name="prefix">  
  31.             <value>/</value>  
  32.         </property>  
  33.         <property name="suffix">  
  34.             <value>.jsp</value>  
  35.         </property>  
  36.     </bean> -->  
  37.       
  38. <!-- 下面是需要加入的-->  
  39. <!-- 下面是需要加入的 ,id要和SimpleUrlHandlerMapping中的 prop的key相同,name要和rop key对应的value相同,否则会导致找不到请求的地址-->  
  40.     <bean id="csmDataCountService"  name="/CsmDataCountSer.shtm" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">  
  41.         <property name="service" ref="csmDataCountSerImpl"></property>  
  42.         <property name="serviceInterface" value="com.hlzt.csm.service.CsmDataCountSer">  
  43.         </property>  
  44.     </bean>  
  45.     <!-- 远程服务的URL ,key值表示客户端请求的地址-->  
  46.     <bean  
  47.         class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">  
  48.          <property name="mappings">  
  49.             <props>  
  50.                   <prop key="/CsmDataCountSer.shtm">csmDataCountService</prop>  
  51.             </props>  
  52.         </property>  
  53.     </bean>  
  54.   
  55.   
  56. </beans>  

服务端 web.xml的配置




客户端配置


客户端 spring的xml文件配置


[html]  view plain  copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3.     xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"  
  4.     xmlns:p="http://www.springframework.org/schema/p"  
  5.     xsi:schemaLocation="  
  6.         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd  
  7.         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd  
  8.         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"  
  9.         default-lazy-init="true">  
  10.   
  11.  <bean id="csmDataCountSer"  name="csmDataCountSer" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">    
  12.      <property name="serviceUrl">    
  13.            <value>http://localhost:80/chat/CsmDataCountSer.shtm</value>    
  14.        </property>    
  15.        <property name="serviceInterface">    
  16.             <value>com.hlzt.csm.service.CsmDataCountSer</value>    
  17.         </property>    
  18.    </bean>  
  19.      
  20. </beans>  

注意的是 id="csmDataCountSer" 本人测试结果是 此实例不能在java中通过 rource 或Autowired自动注入,而要通过手工载入方式获得

ApplicationContext context =new ClassPathXmlApplicationContext("/spring/spring-remote.xml");
CsmDataCountSer csmDataCountSer=(CsmDataCountSer)context.getBean("csmDataCountSer");

(2)spring RMI方式

首先看下实例程序目录结构:

Spring中发布RMI服务(ZLv_RMIServerWithSpring):

(1) 定义接口MessageProvider及接口中供调用的方法(MessageProvider.java):

?
1
2
3
4
5
package  org.thera.rmi.service;
 
public  interface  MessageProvider {
     public  String queryForMessage(String name);
}

(2) 实现MessageProvider接口(MessageProviderImpl.java):

?
1
2
3
4
5
6
7
8
9
10
package  org.thera.rmi.service;
 
public  class  MessageProviderImpl  implements  MessageProvider {
 
     @Override
     public  String queryForMessage(String name) {
         return  "Hello, "  + name;
     }
 
}

做好了上述准备,下面我们就可以通过Spring中集成RMI,方便的发布RMI服务端

(3) Spring配置文件作如下配置(context.xml):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<? xml  version = "1.0"  encoding = "UTF-8" ?>
< beans  xmlns = "http://www.springframework.org/schema/beans"
     xmlns:p = "http://www.springframework.org/schema/p"  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">
 
     <!-- 注入要发布的RMI服务类 -->
     < bean  id = "messageService"  class = "org.thera.rmi.service.MessageProviderImpl" ></ bean >
 
     < bean  class = "org.springframework.remoting.rmi.RmiServiceExporter" >
         <!-- RMI服务名称,可自定义服务名称 -->
         < property  name = "serviceName"  value = "MessageService"  />
         <!-- 导出实体 -->
         < property  name = "service"  ref = "messageService"  />
         <!-- 导出接口 -->
         < property  name = "serviceInterface"  value = "org.thera.rmi.service.MessageProvider"  />
         <!-- spring默认使用1099端口 -->
         < property  name = "registryPort"  value = "1199"  />
     </ bean >
 
</ beans >

(4) 加载Spring容器,发布RMI服务(Main.java):

?
1
2
3
4
5
6
7
8
9
10
11
package  org.thera.rmi.service.main;
 
import  org.springframework.context.ApplicationContext;
import  org.springframework.context.support.FileSystemXmlApplicationContext;
 
public  class  Main {
     public  static  void  main(String[] args) {
         ApplicationContext ctx =  new  FileSystemXmlApplicationContext( "conf/context.xml" );
         System.out.println( "已成功发布RMI服务类" );
     }
}

    到这里,RMI的服务端已经发布成功,运行结果如下截图:

Spring中客户端调用RMI服务(ZLv_RMIClientWithSpring):

(1) 移植服务端服务接口文件MessageProvider.java;

(2) Spring配置文件做如下配置:

?
1
2
3
4
5
6
7
8
9
10
11
12
<? xml  version = "1.0"  encoding = "UTF-8" ?>
< beans  xmlns = "http://www.springframework.org/schema/beans"
     xmlns:p = "http://www.springframework.org/schema/p"  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 = "messageService"  class = "org.springframework.remoting.rmi.RmiProxyFactoryBean" >
         < property  name = "serviceUrl"  value = "rmi://192.168.1.100:1199/MessageService"  />
         < property  name = "serviceInterface"  value = "org.thera.rmi.service.MessageProvider"  />
     </ bean >
 
</ beans >

(3) 加载Spring容器,调用RMI服务端(Main.java):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package  org.thera.rmi.service.main;
 
import  org.springframework.context.ApplicationContext;
import  org.springframework.context.support.FileSystemXmlApplicationContext;
import  org.thera.rmi.service.MessageProvider;
 
public  class  Main {
     public  static  void  main(String[] args) {
         ApplicationContext ctx =  new  FileSystemXmlApplicationContext( "conf/context.xml" );
         System.out.println( "加载Spring容器,并初始化RMI客户端" );
         MessageProvider client = (MessageProvider)ctx.getBean( "messageService" );
         String temp = client.queryForMessage( "LvSantorini" );
         
         System.out.println( "返回结果: "  + temp);
     }
}

运行Main.java,结果如下图:


四种方式总结

1. Spring Remote Service Overview

RPC调用类似于调用本地对象的方法,都是同步的操作,调用代码将被阻塞,直到被调用过程完成为止。

本地调用就是execute process在同一个应用的两个代码块中交换。RPC就是execute process从一个应用通过网络传递给另外一个应用。

Spring RemoteService支持这几种模式:RMI, Hessian, Burlap, HTTP invokerJAX-RPC

Server端,Spring可以通过相应的RemoteExporter将一个Bean的发布成一个remote service

2. RMI in Spring

RMI缺点RMI在有防火墙的环境下运行会有困难,而且RMI要求客户端和服务器端都必须用Java编写。

3.  HessianBurlap

HessionBurlap都是Caucho Technology的框架,基于HTTP的轻量级remote service

Hessian使用binary消息来建立客户端和服务器端之间的交流,因为基于binary所以对通迅带宽的占用小。所以不依赖于语言可以被Java之外的语言所用。

Burlap是基于XML的技术,消息可读性比较好,而且Burlap相比其他基于XML的技术比如SOAP来说,Burlap的消息结构比较简单,不需要WSDL之类的东西额外定义。

使用Hessian(客户端代码)

RMI类似,Spring使用HessianProxyFactoryBean来创建一个指向Hessian服务的proxy

由此可见,当使用Spring时,可以很简单的在各种Spring所支持的remote技术之间切换,而仅仅需要更改很少的配置。

输出Hessian服务

  • 使用HessianServiceExporter

POJOpublic方法公开成Hessian服务。HessianServiceExporter是一个Spring MVC controller,接收Hessian的请求然后翻译成对POJO的方法调用。

输出Burlap服务

Burlap服务的输出几乎和Hessian是一样的,不同的地方就是使用org.springframework.remoting.caucho.BurlapServiceExporter。也需要为它配置URL handlerDispatcherServlet

4. HTTP invoker

RMI使用Java标准的序列化机制,但是很难穿过防火墙;Hessian/Burlap能穿越防火墙但是使用自己私有的一套系列化机制。

因此HTTP invoker应运而生,使用HTTP协议能通过防火墙,并且使用Java序列化机制。

使用HTTP invoker

RMIHessian等相同,HTTP invoker也是通过HttpInvokerProxyFactoryBean

输出HTTP invoker服务

Hessian相同,不同的地方就是使用org.springframework.remoting.httpinvoder.HttpInvokerServiceExporter。也需要为它配置URL handlerDispatcherServlet

HTTP invoder的限制就是客户端和服务器端必须使用Spring

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值