【Spring集成】-Spring配置HttpInvoker

一:前言

上一篇我们写了Spring如何配置RMI,但是RMI很难穿透防火墙,这一篇就让我们看看Spirng如何解决的?

Spring开发团队意识到RMI服务和基于HTTP的服务(例如Hessian和Burlap)之间的空白。一方面,RMI使用Java标准的对象序列化机制,但是很难穿透防火墙。另一方面,Hessian和Burlap能很好的穿透防火墙,但是使用私有的对象序列化机制。

就这样,Spring的Http invoker应运而生了。HttpInvoker是一个新的远程调用模型,作为Spring框架的一部分,能够执行基于Http的远程调用,并使用Java的序列化机制。使用基于HttpInvoker的服务和使用基于Hessian/Burlap的服务非常相似。

二:spring如何配置HttpInvoker

【Spring集成】-Spring配置HttpInvoker_第1张图片

                项目整体结构,和上一篇一样

第一步:配置实体类,接口和接口实现类,和上一篇文章一模一样,这里就不再赘述了,请参考上一篇文章

第二步:配置HttpInvokerServiceExpoter,将接口实现类JinNangServiceImpl导出为服务

package chapter15.spittr.config;

import java.util.Properties;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;

import chapter15.spittr.service.JinNangServiceImpl;
import chapter15.spittr.service.interfaces.JinNangService;

@Configuration
@ComponentScan
public class RootConfig {	
	@Bean
	  public JinNangService jinNangService(){
		  return new JinNangServiceImpl();
	  }
	
	  @Bean
	  public HandlerMapping httpInvokerMapping(){
		  SimpleUrlHandlerMapping mapping=new SimpleUrlHandlerMapping();
		  Properties mappings=new Properties();
		  mappings.setProperty("/jinNang.service", "httpInvokerExporterJinNangService");
		  mapping.setMappings(mappings);
		  return mapping;
	  }
	  
	  @Bean
	  public HttpInvokerServiceExporter httpInvokerExporterJinNangService(JinNangService jinNangService){
		  HttpInvokerServiceExporter rmiServiceExporter=new HttpInvokerServiceExporter();
		  rmiServiceExporter.setService(jinNangService);
		  rmiServiceExporter.setServiceInterface(JinNangService.class);
		  return rmiServiceExporter;
	  }
}

是否有点似曾相识,我们很难找出这个bean的定义和上一篇所声明的bean有什么不同,唯一的区别就是类名:HttpInvokerServiceExporter。否则的话,这个导出器和其他远程服务的导出器没有任何区别。

如下图所示,HttpInvokerServiceExporter的工作方式是:HttpInvokerServiceExporter也是一个Spring的MVC控制器,他通过DispatcherServlet接受来自客户端的请求,并将这些请求转换成实现服务的Pojo的方法调用。

【Spring集成】-Spring配置HttpInvoker_第2张图片

因为HttpInvokerServiceExpoter是一个Spring MVC控制器,我们需要建立一个URL处理器,映射HTTP URL到对应的服务上,就像Hessian和Burlap导出器所作的一样:

	  @Bean
	  public HandlerMapping httpInvokerMapping(){
		  SimpleUrlHandlerMapping mapping=new SimpleUrlHandlerMapping();
		  Properties mappings=new Properties();
		  mappings.setProperty("/jinNang.service", "httpInvokerExporterJinNangService");
		  mapping.setMappings(mappings);
		  return mapping;
	  }

这样我们需要确保匹配了DispacherServlet,这样才能处理对“*.service”扩展的请求。

我们可以通过扩展

AbstractDispatcherServletInitializer或者 Abstract-AnnotationConfigDispatcherServletInitializer 的方式来配置DispatcherServlet,那么在重载getServletMappings()的时候,我们需要包含该映射:

package common;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import chapter15.spittr.config.RootConfig;
public class SpitterWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
  
  @Override
  protected Class[] getRootConfigClasses() {
    return new Class[] { RootConfig.class };
  }

  @Override
  protected Class[] getServletConfigClasses() {
    return null;
  }

  @Override
  protected String[] getServletMappings() {
    return new String[] { "/" ,"*.service"};
  }

}

到此我们已经创建好了服务器端。

三:配置客户端

使用Spring的HttpInvokerProxyFactoryBean,只需要在客户端的spring配置增加如下的@bean方法:

package chapter15.spittr.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean;

import chapter15.spittr.service.interfaces.JinNangService;

@Configuration
@ComponentScan(basePackages={"chapter15.spittr"})
public class RootConfig {
	@Bean
	  public HttpInvokerProxyFactoryBeanjinNangService(){
		  HttpInvokerProxyFactoryBeanrmiProxy=new HttpInvokerProxyFactoryBean();
		  rmiProxy.setServiceUrl("rmi://localhost/JinNangService");
	          rmiProxy.setServiceInterface(JinNangService.class);
		  return rmiProxy;
	  }

}

服务的URL是通过HttpInvokerProxyFactoryBean的serviceUrl属性设置的,在这里,服务名被设置为JinNangService,并且生命服务实在本地机器上的;同时,服务提供的接口由serviceInterface属性来指定。

现在我们已经把服务声明为Spring管理的bean,我们可以把它作为依赖装配进另一个bean中,就像任意非远程的bean那样。例如,我们可以使用JinNangService来获得一条锦囊妙计:

package chapter15.spittr.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import chapter15.spittr.config.RootConfig;
import chapter15.spittr.domain.JinNang;
import chapter15.spittr.service.interfaces.JinNangService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=RootConfig.class)
public class JaxwsTest {

	@Autowired
	JinNangService jinNangService;
	
	@Test
	public void getJinNang(){
		JinNang jinnang=jinNangService.getJinNang();
		System.out.println("获得的计策是:让"+jinnang.getPeople()+"实施"+jinnang.getJice());
	}
	
}

客户端就会得到如下输出:

        获得的计策是:让黄盖实施苦肉计

至此,服务端客户端代码已经全部写完了,怎么样,很简单吧!

总结:

   Spring的HttpInvoker是作为两全齐美的远程调用解决方案而出现的,把Http的简单行和Java内置的对象序列化机制融合在一起,这使得HttpInvoker服务成为一个引人注目的替代RMI或者Hessian/Burlap的可选方案。

要记住HttpInvoker有一个重大的限制:他只是Spring框架所提供的远程调用解决方案。这意味着客户端和服务端都必须是Spring应用。并且,至少目前而言,也隐含表明客户端和服务端都必须是基于Java的。另外,因为使用了java的序列化机制,客户端和服务端必须使用相同版本的类(与RMI类似)。

以上全是作者纯手打,欢迎提出改进意见,谢谢!



你可能感兴趣的:(spring)