天天看點

使用遠端服務RMI和invoker

     如果我們需要擷取目前的天氣狀況,我們可以通過氣象局提供的一個接口并調用方法來擷取,這是因為氣象局釋出了一個遠端服務,我們可以通過接口來調用他的遠端方法,擷取到天氣資訊,一般釋出并使用遠端服務的有RMI ,hessian和brulap ,以及spring的invoker,他們各有優缺點, 這裡隻介紹RMI和spring的invoker

一、使用RMI釋出一個遠端服務

       首先我們需要定義一個接口,這個接口對外公開

package main.java.test.rmi;

import java.util.List;

public interface FruitService {
    List<Fruit> getFruitList();
}
           

 然後還需要一個接口的實作類:

package main.java.test.rmi;

import java.util.ArrayList;
import java.util.List;

public class FruitServiceImpl implements FruitService {
    public List<Fruit> getFruitList() {
        List<Fruit> list = new ArrayList<Fruit>();
        Fruit f1 = new Fruit();
        f1.setName("橙子");
        f1.setColor("黃色");
        Fruit f2 = new Fruit();
        f2.setName("蘋果");
        f2.setColor("紅色");
        list.add(f1);
        list.add(f2);
        return list;
    }
}
           

 這裡用到的實體類是Fruit,實體類必須序列化

package main.java.test.rmi;

import java.io.Serializable;

public class Fruit implements Serializable {
    private String name;
    private String color;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }
}
           

 然後就是配置了, 在spring的配置檔案中配置

<!-- spring內建RMI遠端服務 -->
		<bean id="messageService" class="main.java.test.rmi.MessageProviderImp"></bean>

		<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
		<!-- RMI服務名稱,可自定義服務名稱 -->
		<property name="serviceName" value="MessageService" />
		<!-- 導出實體 -->
		<property name="service" ref="messageService" />
		<!-- 導出接口 -->
		<property name="serviceInterface" value="main.java.test.rmi.MessageProvider" />
		<!-- spring預設使用1099端口 -->
		<property name="registryPort" value="1199" />
		</bean>      

 這樣啟動項目,這個服務就釋出出去了

二、通路RMI遠端服務

     也就是用戶端通路遠端服務的時候,需要在用戶端的spring配置檔案中配置:

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

 這樣在項目中擷取這個bean強轉成接口調用相應的方法就可以了

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);
	}
}
           

 這就是RMI釋出以及調用遠端服務的執行個體

三、釋出spring的invoker遠端服務

    invoker是spring為了解決RMI和hessian的缺陷而出現的一個服務,釋出一個invoker遠端服務的步驟如下,他的接口,實作類以及實體類都是采用上面定義了的接口和接口實作類

   首先,使用invoker就需要使用spring,我們使用的springmvc架構,在這裡需要定義一個接口調用的url,比如我們就定義為/user.service, 這樣用戶端就可以通過這個url來擷取服務,手下那我們需要在web中攔截到這個請求,/*包含/user.service

<servlet>  
     <servlet-name>spring</servlet-name>  
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
       <init-param>  
            <param-name>contextConfigLocation</param-name>  
            <param-value>classpath:main/resource/spring-servlet.xml</param-value>  
        </init-param>  
      <load-on-startup>1</load-on-startup>  
  	</servlet>
 	 <servlet-mapping>  
      <servlet-name>spring</servlet-name>  
      <url-pattern>/*</url-pattern>  
  	</servlet-mapping>  
  	<context-param>  
      <param-name>contextConfigLocation</param-name>  
      <param-value>classpath:main/resource/applicationContext.xml</param-value>  
  </context-param>       

因為這個url請求不同于其他的請求,是以需要為這個請求單獨處理一個bean,在mvc的配置檔案中這樣配置:

<?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:mvc="http://www.springframework.org/schema/mvc"
    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 
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd ">
	<!-- <mvc:resources location="/html/" mapping="/html/**"/> 
	<mvc:resources location="/js/" mapping="/js/**"/> -->
	<mvc:resources location="/" mapping="/**/*.html"/> 
	<mvc:resources location="/" mapping="/**/*.js"/>
	<mvc:resources location="/" mapping="/**/*.jsp"/>
    <context:component-scan
			base-package="main.java">
    </context:component-scan>
    <mvc:annotation-driven/>
    <bean id="userServices" class="main.java.test.rmi.FruitServiceImpl" />  
		 <bean id="userServiceInvoker"  
        class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">  
        <property name="service" ref="userServices" />  
        <property name="serviceInterface" value="main.java.test.rmi.FruitService">  
        </property>  
    </bean> 
    <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">  
        <property name="mappings">    
            <props>    
                  <prop key="/user.service">userServiceInvoker</prop>    
            </props>    
        </property>    
    </bean>
    
</beans>        

  這樣就遠端服務就釋出出去了

四、擷取invoker遠端服務

擷取invoker遠端服務就需要在spring配置檔案中這樣配置:

<bean id="httpService1"  
        class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">  
        <property name="serviceUrl">  
            <value>http://localhost:80/user.service</value>  
        </property>  
        <property name="serviceInterface" value="main.java.test.rmi.FruitService">  
        </property>  
    </bean>      

 配置服務擷取bean,這樣在任意地方通過

FruitService client = (FruitService)BeanUtil.getBeanByName("httpService1");
		System.out.println("invoker     "+client.getFruitList().size());
           

 就可以擷取到服務方法了是不是很簡單

五、優缺點以及問題

   rmi是一種很好的實作與遠端服務互動的非常好的方式,但是他存在某些限制, 首先,他很難穿越防火牆,其次就是rmi是基于java的也就是用戶端和服務端都必須采用java 開發,

  invoker是一個座位兩全其美的遠端調用解決方案二出現的,但是他有一個嚴重的限制,就是他的用戶端呢服務端都必須是spring應用,也隐含的表名了用戶端和服務端必須是基于java的

問題:①invoker配置urlmapping時,必須是在springmvc的配置servlet配置檔案中,而不是在spring的配置檔案。