`

Spring HTTP invoker RPC

 
阅读更多

Spring HTTP invoker是spring框架中的一个远程调用模型,执行基于HTTP的远程调用(意味着可以通过防火墙),并使用java的序列化机制在网络间传递对象。客户端可以很轻松的像调用本地对象一样调用远程服务器上的对象,这有点类似于webservice,但又不同于webservice,区别如下:

webservice

HTTP invoker

跨平台,跨语言

只支持java语言

支持SOAP,提供wsdl

不支持

结构庞大,依赖特定的webservice实现,如xfire等

结构简单,只依赖于spring框架本身

项目中使用哪种远程调用机制取决于项目本身的要求。

HTTP invoker 服务模式

HTTP invoker 服务模式

 

说明:

1.       服务器端:通过HTTP invoker服务将服务接口的某个实现类提供为远程服务

2.       客户端:通过HTTP invoker代理向服务器端发送请求,远程调用服务接口的方法

3.       服务器端与客户端通信的数据需要序列化

配置服务器端和客户端的步骤

配置服务器端

1.       添加springJAR文件

建议使用spring2+.jar版本

2.       创建服务接口

3.       创建服务接口的具体实现类

4.       公开服务

配置客户端

1.  添加springJAR文件

建议使用spring2+.jar版本

2.       创建服务接口

3.       访问服务

实例讲解

服务器端

1.服务接口:UcService.java

它提供两项服务,查询用户信息和记录日志,如下:

public interface UcService {

           public UserInfo getUserInfobyName(String userName);

           public int recordLog(String username, String point, String operate, String desc);

}

说明:举这个列子是因为其比较有代表性,它将展示普通数据类型(int,long等)和复杂数据类型(DTO等)的远程调用方式。UserInfo是一个普通的DTO,代码如下:

public class UserInfo implements Serializable {

    private static final long serialVersionUID = -6970967506712260305L;

    /**用户名*/

    private String userName;

    /**电子邮箱*/

    private String email;

    /**注册日期*/

    private Date registDate;

 

    public String getUserName() {

        return userName;

    }

    public void setUserName(String userName) {

        this.userName = userName;

    }

    public String getEmail() {

        return email;

    }

    public void setEmail(String email) {

        this.email = email;

    }

     public Date getRegistDate() {

        return registDate;

    }

    public void setRegistDate(Date registDate) {

        this.registDate = registDate;

    }

}

注意:因为是在网络间传输对象,所以需要将UserInfo实现Serializable接口,并指定一个serialVersionUID(任意值即可,同时客户端也要有这个类,否则在客户端接收对象时会因为serialVersionUID不匹配而出现异常)

回到UcService.java,它提供了两个服务(在这里一个方法代表一个服务功能),我们需要具体的实现类来实现真正的服务

2.实现类是UCServiceImpl.java

public class UCServiceImpl implements UcService {

    private static Logger pointrecordlog = Logger.getLogger("pointrecordlog");

    private static Logger logger = Logger.getLogger(UCServiceImpl.class);

    private UcFacade ucFacade;

    public void setUcFacade(UcFacade ucFacade) {

        this.ucFacade = ucFacade;

    }

    public UserInfo getUserInfobyName(String userName) {

        UserInfo user = null;

        try {

            user = ucFacade.getUserInfoDetail(userName);

            logger.debug("get userinfo success by  username:" + userName);

        } catch (Throwable t) {

            logger.error("get userinfo fail by  username:" + userName, t);

        }

        return user;

    }

    public int recordLog(String username, String point, String operate, String desc) {

        int result = 0;

        try {

            pointrecordlog.info(username + " - " + point + " - " + operate + " - " + desc);

        } catch (Throwable t) {

            result = -1;

            logger.error(t);

        }

        return result;

    }

}

说明:ucFacade是通过spring注入的一个数据查询类,因为它与http invoker没有直接关系,所以不进行介绍。

3.公开服务UcService.java

WEB-INF/application-context.xml:将接口声明为HTTP invoker服务

<bean id="httpService"

        class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">

        <property name="service">

            <ref bean="ucService" />

        </property>

        <property name="serviceInterface"

            value="com.netqin.baike.service.UcService">

        </property>

    </bean>

    <bean id="ucService" class="com.netqin.baike.service.impl.UCServiceImpl"/>

说明:HttpInvokerServiceExporter实际上是一个spring mvc控制器,它处理客户端的请求并调用服务实现。

 WEB-INF/service-servlet.xml:HttpInvokerServiceExporter实际上是一个spring mvc控制器,所以需要为其提供spring URL 处理器,这里我们使用SimpleUrlHandlerMapping

<bean

        class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

         <property name="mappings">

            <props>

                  <prop key="/httpService">httpService</prop>

            </props>

        </property>

    </bean>

WEB-INF/web.xml:配置spring监听及DispatcherServlet

<context-param>

        <param-name>contextConfigLocation</param-name>

        <param-value>

            /WEB-INF/application-context.xml

        </param-value>

    </context-param>

 

    <listener>

        <listener-class>

            org.springframework.web.context.ContextLoaderListener

        </listener-class>

    </listener>

 

<servlet>

        <servlet-name>service</servlet-name>

        <servlet-class>

            org.springframework.web.servlet.DispatcherServlet

        </servlet-class>

        <load-on-startup>1</load-on-startup>

    </servlet>

 

    <servlet-mapping>

        <servlet-name>service</servlet-name>

        <url-pattern>/service/*</url-pattern>

    </servlet-mapping>

说明:不了解为什么这么配置的可以去看看spring mvc方面的资料。

好了,经过以上配置,一个基于spring HTTP invoker的远程服务就完成了,服务的地址为:

http://${serviceName}:${port}/${contextPath}/service/httpService

客户端

1.       创建服务接口及网络间传输的DTO类

为了方便,可以将服务器端创建好的的UcService.java和UserInfo.java拷贝到客户端,或打个jar包放到lib下。

2.       配置访问服务

WEB-INF/application-context.xml:如果项目中已经存在spring配置文件,则不需要创建该文件,需要配置HTTP invoker的代理

<bean id="httpService"

class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">

        <property name="serviceUrl">

            <value> http://${serviceName}:${port}/${contextPath}/service/httpService

</value>

        </property>

        <property name="serviceInterface"

            value="com.netqin.baike.service.UcService">

        </property>

</bean>

说明:客户端使用HttpInvokerProxyFactoryBean代理客户端向服务器端发送请求,请求接口为UcService的服务

注意:需要修改serviceUrl为实际的服务器地址

 WEB-INF/web.xml:配置spring监听

如果项目没有spring环境,则需要在web.xml中加入对spring的支持

<context-param>

        <param-name>contextConfigLocation</param-name>

        <param-value>

            /WEB-INF/application-context.xml

        </param-value>

    </context-param>

 

    <listener>

        <listener-class>

            org.springframework.web.context.ContextLoaderListener

        </listener-class>

</listener>

 

3.       访问服务方法

读取spring上下文,以远程调用getUserInfobyName方法为例

在jsp,servlet,action等等文件中

UcService service = (UcService) WebApplicationContextUtils

        .getRequiredWebApplicationContext(

            request.getSession().getServletContext()).getBean(

            "httpService");

UserInfo user = service.getUserInfobyName("hanqunfeng");

 如果不想配置spring运行环境,可以使用如下方式:

ApplicationContext applicationContextnew FileSystemXmlApplicationContext("classpath:application-context.xml");

service = (UcService) applicationContext.getBean("httpService");

依赖注入,远程调用recordLog方法为例

 在WEB-INF/application-context.xml中加入如下配置:

<bean id="abc" class="com.netqin.test.abc">

        <property name="service">

            <ref bean="httpService" />

        </property>

</bean>

为com.netqin.test.abc中加入对service的set方法:

private UcService service;

    public void setService(UcService service){

        this.service = service;

    }

 

    public String recordUserLog(String username,String point,String operate,String desc){

        String result = service.recordLog(username, point, operate, desc);

        return result;

}

 

关于服务器端配置的补充说明:

 有一个误区:有些关于springMVC的书上说,如果没有明确声明一个处理适配器,默认会使用org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,这个适配器专门负责处理所有实现了

org.springframework.web.servlet.mvc.Controller接口的处理器,我就是受其影响,认为org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter实现的是org.springframework.web.HttpRequestHandler接口,所以按理说应该使用的处理适配器是org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,但实际上并不会出现异常。

其实,原因是因为spring默认会使用四个处理适配器(参看DispatcherServlet.properties,spring2.5,spring2.0只默认三个,2.5增加注解方式):

org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,/
 org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,/
 org.springframework.web.servlet.mvc.throwaway.ThrowawayControllerHandlerAdapter,/
 org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

 关于DispatcherServlet.properties的详细信息可以参看:

http://blog.csdn.net/hanqunfeng/archive/2010/01/08/5161319.aspx

但是,如果明确声明了其它的处理适配器,比如org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter,等等,则默认规则则会覆盖,需要明确声明org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter这个处理适配器,否则系统会抛异常:

javax.servlet.ServletException: No adapter for handler [org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter@179bd14]: Does your handler implement a supported interface like Controller?

所以,建议在使用spring invoker时,最好明确声明org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter这个处理适配器

另外,默认情况下,客户端的HttpInvokerProxy使用J2SE的HTTP Client来建立连接,即org.springframework.remoting.httpinvoker.SimpleHttpInvokerRequestExecutor,可以通过设置httpInvokerRequestExecutor属性来改变默认配置,spring提供了另外一种HttpClient,org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor。

修改配置如下:

<bean id="httpService"
  class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
  <property name="serviceUrl">
   <value>http://vm.netqin.com:4080/ucs/service/httpService</value>
  </property>
  <property name="serviceInterface" value="com.netqin.baike.service.UcService">
  </property>
  <property name="httpInvokerRequestExecutor">
   <bean
    class="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor" />
  </property>
 </bean>

需要在项目中引入两个jar包:

commons-codec-x.x.jar

commons-httpclient-x.x.x.jar

CommonsHttpInvokerRequestExecutor具有HTTP connection pooling,不过通过使用jmeter进行压力测试发现,SimpleHttpInvokerRequestExecutor性能高于CommonsHttpInvokerRequestExecutor

转至:http://blog.csdn.net/hanqunfeng/article/details/4303127

分享到:
评论

相关推荐

    spring-httpinvoker-demo

    Spring HTTP Invoker是spring框架中的一个远程调用模型,执行基于HTTP的远程调用,也就是说,可以通过防火墙,并使用java的序列化机制在网络间传递对象。客户端可以很轻松的像调用本地对象一样调用远程服务器上的...

    Java学习之路-Spring的HttpInvoker学习

    Hessian和Burlap都是基于HTTP的,他们都解决了RMI所头疼的防火墙渗透问题。但当传递过来的RPC消息中包含序列化对象时,RMI完胜...  Spring的HttpInvoker,它基于HTTP之上提供RPC,同时又使用了Java的对象序列化机

    基于Spring的HttpInvoker实现改写egova_invoker.zip

    基于Spring的HttpInvoker实现改写服务器端调用: HttpInvoker.invoker 方法,设置InvokerProcess处理客户端调用: ProxyFactory.proxy 方法,生成接口的代理对象,直接调用方法客户端和服务器端的接口和实体类要...

    Spring 实现远程访问详解——rmi

    2. Spring的HTTP调用器(Spring’s Http Invoker): Spring提供了一种特殊的允许通过HTTP进行Java串行化的远程调用策略,支持任意Java接口(就像RMI调用器)。相对应的支持类是 HttpInvokerProxyFactoryBean和 ...

    spring jar 包详解

    (9) spring-remoting.jar 这个jar文件包含支持EJB、JMS、远程调用Remoting(RMI、Hessian、Burlap、Http Invoker、JAX-RPC)方面的类。 (10) spring-support.jar 这个jar文件包含支持缓存Cache(ehcache)、JCA、...

    Spring 2.5 jar 所有开发包及完整文档及项目开发实例

     这个jar文件包含支持EJB、JMS、远程调用Remoting(RMI、Hessian、Burlap、Http Invoker、JAX-RPC)方面的类。 (10) spring-support.jar  这个jar文件包含支持缓存Cache(ehcache)、JCA、JMX、邮件服务(Java ...

    最新最全的spring开发包

     这个jar文件包含支持EJB、JMS、远程调用Remoting(RMI、Hessian、Burlap、Http Invoker、JAX-RPC)方面的类。 (10) spring-support.jar  这个jar文件包含支持缓存Cache(ehcache)、JCA、JMX、邮件服务(Java ...

    基于Spring的RPC通讯模型的使用与比较

    主要介绍了基于Spring的RPC通讯模型的使用与比较,详细的介绍了RMI、Caucho的Hessian和Burlap以及Spring自带的HTTP invoker,感兴趣的可以了解一下

    Manning.Spring.in.Action.4th.Edition.2014.11.epub

    15.4. Using Spring’s HttpInvoker 15.4.1. Exposing beans as HTTP services 15.4.2. Accessing services via HTTP 15.5. Publishing and consuming web services 15.5.1. Creating Spring-enabled JAX-WS ...

    spring in action英文版

     6.4 使用HTTP invoker  6.4.1 通过HTTP访问服务  6.4.2 把Bean作为HTTP服务公开  6.5 使用EJB  6.5.1 访问EJB  6.5.2 用Spring开发EJB  6.6 使用JAX-RPC的Web Service  6.6.1 用JAX-RPC应用...

    Spring in Action(第2版)中文版

    8.4使用httpinvoker 8.4.1通过http访问服务 8.4.2把bean作为http服务公开 8.5spring和web服务 8.5.1使用xfire将bean输出为web服务 8.5.2使用jsr-181注释声明web服务 8.5.3消费web服务 8.5.4使用xfire客户端...

    Spring in Action(第二版 中文高清版).part2

    8.4 使用HTTP invoker 8.4.1 通过HTTP访问服务 8.4.2 把Bean作为HTTP服务公开 8.5 Spring和Web服务 8.5.1 使用XFire将Bean输出为Web服务 8.5.2 使用JSR-181注释声明Web服务 8.5.3 消费Web服务 8.5.4 使用...

    Spring in Action(第二版 中文高清版).part1

    8.4 使用HTTP invoker 8.4.1 通过HTTP访问服务 8.4.2 把Bean作为HTTP服务公开 8.5 Spring和Web服务 8.5.1 使用XFire将Bean输出为Web服务 8.5.2 使用JSR-181注释声明Web服务 8.5.3 消费Web服务 8.5.4 使用...

    spring-rest-invoker:将远程REST服务映射到本地接口的Spring Invoke

    Spring休息祈求者Spring调用程序将远程JSON REST服务绑定到Java接口, 工作方式。 在这些接口上调用方法将向远程服务发出HTTP请求,并将任何对象与JSON(反序列化)。 接口和远程服务之间的具体映射可以通过编程或...

    soar:一个简单的rpc框架

    Soar技术文档 功能需求 跨机房切换(自动) 支持异步(消费方、提供方均提供异步...ServiceContainer:服务容器(考虑支持spring和注解扫描两种方式实现) soar注册中心树形结构 soar多机房和集群容错 protocol(tcp)

    java开源包1

    它是 Spring HttpInvoker的一个轻量级选择,特别适合于当你不想在客户端程序中使用Spring框架。 API访问授权的开放标准 OAuth OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式...

    java开源包11

    它是 Spring HttpInvoker的一个轻量级选择,特别适合于当你不想在客户端程序中使用Spring框架。 API访问授权的开放标准 OAuth OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式...

    java开源包2

    它是 Spring HttpInvoker的一个轻量级选择,特别适合于当你不想在客户端程序中使用Spring框架。 API访问授权的开放标准 OAuth OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式...

    java开源包3

    它是 Spring HttpInvoker的一个轻量级选择,特别适合于当你不想在客户端程序中使用Spring框架。 API访问授权的开放标准 OAuth OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式...

    java开源包6

    它是 Spring HttpInvoker的一个轻量级选择,特别适合于当你不想在客户端程序中使用Spring框架。 API访问授权的开放标准 OAuth OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式...

Global site tag (gtag.js) - Google Analytics