Spring Http Invoker使用简介

一、Spring HTTP Invoker简介

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

WebService Http Invoker
跨平台,跨语言 只支持 java 语言
支持 SOAP ,提供 wsdl 不支持
结构庞大,依赖特定的 webservice 实现,如 xfire等 结构简单,只依赖于 spring 框架本身

说明:

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

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

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

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

配置服务器端

?1. 添?加 springJAR 文件?

2. 创建相应的DTO(如果需要用到的话)

3. 创建服务接口

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

5. 公开服务

配置客户端

1. 添加 springJAR 文件

2. 创建相应的DTO(如果需要用到的话)

3. 创建服务接口

4. 访问服务

三、实例讲解

?

配置服务器端

先来个项目结构图:

1). 添加 springJAR 文件,这就不用说了,直接照着图片添加相应的类库。

2). 创建服务接口和相应的DTO

这里我们需要调用远端的服务来查询一个User对象,因此需要DTO啦。下面这个User类就是用于在网络中传输的POJO类,也就是DTO啦,因此需要实现Serializable接口:

package com.abc.invoke.bean;

import java.io.Serializable;

public class User implements Serializable {
    private static final long serialVersionUID = -6970967506712260305L;
    private String name;
    private int age;
    private String email;

    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        this.age = age;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + ", email=" + email + "]";
    }
}

3). UserService是一个接口,里面定义了服务的方法,这里面的方法将会被客户端调用:

package com.abc.invoke.server.service;

import com.abc.invoke.bean.User;

public interface UserService {
    public User getUserbyName(String name);
}

4). 创建服务接口的具体实现类。这里的UserServiceImpl是实现了UserService方法:

package com.abc.invoke.server.service.impl;

import com.abc.invoke.bean.User;
import com.abc.invoke.server.service.UserService;

public class UserServiceImpl implements UserService {
    public User getUserbyName(String name) {
        User u = new User();
        u.setName(name);
        u.setEmail("[email protected]");
        u.setAge(20);
        return u;
    }
}

这里面我没有写DAO等层面的东西,我只是简单的将传给服务端的参数封装到对象里的一个字段就返回了。

5). 公开服务

下面是web.xml文件的内容:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
	<display-name>SpringInvoke</display-name>
	<servlet>
		<servlet-name>service</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:service-servlet.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>service</servlet-name>
		<url-pattern>/service/*</url-pattern>
	</servlet-mapping>
	<welcome-file-list>
	        <welcome-file>index.html</welcome-file>
	</welcome-file-list>
</web-app>

这里我们使用/service作为service的前缀,那么客户端请求调用时需要加上这个前缀,比如:

http://{host}:{port}/InvokeServer/service/{serviceName}

里面用service-servlet文件:

<?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:context="http://www.springframework.org/schema/context"
    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">

    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/userService">userServiceInvoker</prop>
            </props>
        </property>
    </bean>

    <!-- Announce that this interface is a HTTP invoker service. -->
    <bean id="userServiceInvoker" 
        class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
        <property name="service" ref="userServiceImpl" />
        <property name="serviceInterface" value="com.abc.invoke.server.service.UserService" />
    </bean>
    <bean id="userServiceImpl" class="com.abc.invoke.server.service.impl.UserServiceImpl" />
</beans>

注意:

  1. <prop key="/userService">userServiceInvoker</prop>中的/userService是请求的服务的URL中的一部分,就是说这样的URL会被userServiceInvoker处理
  2. 这里将com.abc.invoke.server.service.UserService映射给了com.abc.invoke.server.service.impl.UserServiceImpl类了。

到此为止,服务器算是配置好了,接下来开始配置客户端。

配置客户端

先来看看项目结构图:

1). 添加 springJAR 文件,这也不用说了,直接照着图片添加相应的类库。

2). 创建服务接口和相应的DTO。

特别注意:这个类和Server端声明的DTO要一样,包名和字段名都要一样才行。因为客户端发起请求查询User,服务端处理后先将User序列化后在返回给客户端,而客户端拿到这个User后需要将其反序列化。如果包名或者字段名不同,则会被认为是不同的对象,会反序列化失败,调用也就出错了。我之前就是将User类的包名不一样(User类的包名在服务端为com.abc.invoke.server.bean,而在客户端则为com.abc.invoke.client.bean),报了以下错误:

Exception in thread "main" org.springframework.remoting.RemoteAccessException: 
	Could not deserialize result from HTTP invoker remote service [http://localhost:8080/InvokeServer/service/userService]; 
	nested exception is java.lang.ClassNotFoundException: com.abc.invoke.server.bean.User
	at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.convertHttpInvokerAccessException(HttpInvokerClientInterceptor.java:208)
	at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.invoke(HttpInvokerClientInterceptor.java:145)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
	at com.sun.proxy.$Proxy0.getUserbyName(Unknown Source)
	at com.abc.invoke.client.Test.main(Test.java:14)

3). 创建服务接口

这也没啥好说的,接口和Server端定义的一样就行,不一样肯定报错。可以直接将DTO和接口定义的类拷贝到客户端即可。这个接口将会被看做是客户端和服务端通信的“契约”。

4). 访问服务

来看看application-context.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:context="http://www.springframework.org/schema/context"
	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">
    
    <!-- 客户端使用 HttpInvokerProxyFactoryBean 代理客户端向服务器端发送请求,请求接口为 UserService 的服务 -->
    <bean id="userService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean" >
        <property name="serviceUrl" value="http://localhost:8080/InvokeServer/service/userService"/>
        <property name="serviceInterface" value="com.abc.invoke.client.service.UserService" />
    </bean>
    
</beans>

这里使用了org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean这个类来作为一个service的代理类。注意到serviceUrl属性为http://localhost:8080/InvokeServer/service/userService,这个URL的地址以/service开始,因此会被Server端拦截下来,而URL中的 /userService则为service路径,该路径与在Server端中service-servlet.xml中声明的

<prop key="/userService">userServiceInvoker</prop>

路径一致,因此这个调用会被userServiceInvoker处理。

最后再写一个简单的测试类Test.java:

package com.abc.invoke.client;

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

import com.abc.invoke.bean.User;
import com.abc.invoke.client.service.UserService;

public class Test {
   public static void main(String[] args) {
       ApplicationContext ac = new ClassPathXmlApplicationContext(
                       "classpath:application-context.xml");
       UserService service = (UserService)ac.getBean("userService");
       User u = service.getUserbyName("Alvis");
       System.out.println(u);
   }
}

这个类也很简单,就是从Spring的Context中取出了定义的userService这个Bean(这其实就是服务端service的一个代理类),然后直接调用该service的方法获得结果并打印。

到此为止,客户端配置完成。

四、启动服务并测试

直接启动Tomcat,可以看到路径/userService的处理者是userServiceInvoker:

下面是执行结果:

从结果中可以看到,我代码里写的名字叫Alvis,用客户端调用服务端的service后,返回的对象中名字是客户端设置的名字,测试成功。

参考页面:http://hanqunfeng.iteye.com/blog/868210

时间: 2024-08-26 00:17:29

Spring Http Invoker使用简介的相关文章

Spring Http Invoker

配置如下: ①web.xml配置 <servlet> <servlet-name>remote</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置该Servlet随应用启动时候启动 --> <load-on-startup>1</load-on-startup&g

[转]spring 监听器 IntrospectorCleanupListener简介

"在服务器运行过程中,Spring不停的运行的计划任务和OpenSessionInViewFilter,使得Tomcat反复加载对象而产生框架并用时可能产生的内存泄漏,则使用IntrospectorCleanupListener作为相应的解决办法."对于这一句话,引用关于IntrospectorCleanupListener一段解释:引用spring中的提供了一个名为org.springframework.web.util.IntrospectorCleanupListener的监听器

Spring表达式语言SpEL简介

Spring3引入了Spring表达式语言(Spring Expression Language,SpEL). SpEL有很多特性,比较常用的包括: 1.使用bean的id来引用bean, 下面这个例子就是将卧室这个bean通过SpEL注入到house这个bean的bedroom属性中. <bean id="bedroom" class="go.derek.Bedroom"/> <bean id="house" class=&q

spring相关—AOP编程简介

1 AOP概述 ●AOP(Aspect-Oriented Programming,面向切面编程):是一种新的方法论,是对传统 OOP(Object-Oriented Programming,面向对象编程)的补充. 作用:本质上来说是一种简化代码的方式     继承机制     封装方法     动态代理     -- ●AOP编程操作的主要对象是切面(aspect),而切面模块化横切关注点. ●在应用AOP编程时,仍然需要定义公共功能,但可以明确的定义这个功能应用在哪里,以什么方式应用,并且不必

java程序员培训:为什么要用Spring含三大框架简介

文章来源:http://www.zretc.com/technologyDetail/476.html Spring作为三大框架之一,一直困惑她有什么用?为什么要使用Spring呢?(大部分来自网上,引用出处太多,恕不一一标明.). SSH在J2EE项目中表示了3种框架,即 Spring + Struts +Hibernate. Struts对Model,View和Controller都提供了对应的组件.Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架,它由Rod Jo

Spring Cloud Config - RSA简介以及使用RSA加密配置文件

简介 RSA非对称加密有着非常强大的安全性,HTTPS的SSL加密就是使用这种方法进行HTTPS请求加密传输的.因为RSA算法会涉及Private Key和Public Key分别用来加密和解密,所以称为非对称加密.Private Key和Public Key有互操作性,即用private key加密的可以用public key解密,用public key加密的可以用private key解密.传统的单向认证则只用public key进行加密,有private key的一方才可进行解密.例如,一

Spring中Ordered接口简介

前言 Spring中提供了一个Ordered接口.Ordered接口,顾名思义,就是用来排序的. Spring是一个大量使用策略设计模式的框架,这意味着有很多相同接口的实现类,那么必定会有优先级的问题. 于是,Spring就提供了Ordered这个接口,来处理相同接口实现类的优先级问题. Ordered接口介绍 首先,我们来看下Ordered接口的定义: public interface Ordered { int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;

Spring Tools Suite (STS) 简介

首先,sts是一个定制版的Eclipse,专为Spring开发定制的,方便创建调试运行维护Spring应用. 官方页面.下载地址(3.8.1 win x64). 其次,没什么好介绍的,用一下就明白了. 创建Spring应用的过程同 https://start.spring.io/ 中所示--实际上访问的接口一致. 下载之后,可以看到一个sts-bundle,里面有三个文件夹,一个法律信息,一个tc Server,一个sts. 注意,文件夹名称越短越好,否则会出错. 另外,note.txt是我自己

Spring MVC 3.0简介

1.    背景介绍 Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块.使用 Spring 可插入的 MVC 架构,可以选择是使用内置的 Spring Web 框架还是 Struts 这样的 Web 框架.通过策略接口,Spring 框架是高度可配置的,而且包含多种视图技术,例如 JavaServer Pages(JSP)技术.Velocity.Tiles.iText 和 POI.Spring MVC 框架并不知道使用的视图,所以不会强迫您只使用 JSP 技术.Spring