一,Spring HTTP Invoker-远程调用模式
Spring HTTP invoker 是 spring 框架中的一个远程调用模型,执行基于 HTTP 的远程调用(意味着可以通过防火墙),并使用 java 的序列化机制在网络间传递对象。客户端可以很轻松的像调用本地对象一样调用远程服务器上的对象,这有点类似于 webservice,但又不同于 webservice ,区别如下:
webservice | HTTP invoker |
跨平台,跨语言 | 只支持 java 语言 |
支持 SOAP ,提供 wsdl | 不支持 |
结构庞大,依赖特定的 webservice 实现,如 xfire等 | 结构简单,只依赖于 spring 框架本身 |
HTTP invoker 服务模式
说明:
1. 服务器端:通过 HTTP invoker 服务将服务接口的某个实现类提供为远程服务
2. 客户端:通过 HTTP invoker 代理向服务器端发送请求,远程调用服务接口的方法
3. 服务器端与客户端通信的数据需要序列化
Spring HTTP Invoker有两种实现方式
1,基于Url映射方式,远程系统处理请求的方式同SpringMVC的controller类似,所有的请求通过在web.xml中的 org.springframework.web.servlet.DispatcherServlet统一处理,根据url映射,去对应的 【servlet名称-servlet.xml】文件中,查询跟请求的url匹配的bean配置
基于Servlet方式,
2,由org.springframework.web.context.support.HttpRequestHandlerServlet去拦截url- pattern匹配的请求,如果匹配成功,去ApplicationContext中查找name与servlet-name一致的bean,完成远程方法调用。
注意:如果涉及java对象因为是在网络间传输对象,所以需要将 对象实现 Serializable 接口,并指定一个 serialVersionUID (任意值即可,同时客户端也要有这个类,否则在客户端接收对象时会因为 serialVersionUID 不匹配而出现异常)
配置服务器端
1. 添加 springJAR 文件
建议使用 spring2+.jar 版本
2. 创建服务接口
3. 创建服务接口的具体实现类
4. 公开服务
(
将接口声明为 HTTP invoker 服务
(如:
< bean id = "httpService"
class = "org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter" >
< property name = "service" >
< ref= "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 >
)
一个基于 spring HTTP invoker 的远程服务就完成了,服务的地址为:
http://${serviceName}:${port}/${contextPath}/service/httpService
)
配置客户端
1. 添加 springJAR 文件
建议使用 spring2+.jar 版本
2. 创建服务接口
(
为了方便,可以将服务器端创建好的的 UcService.java 和 UserInfo.java 拷贝到客户端 , 或打个 jar 包放到 lib 下。
)
3.配置访问服务
(
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 为实际的服务器地址
)
4. 访问服务
(
读取 spring 上下文,以远程调用 getUserInfobyName 方法为例
在 jsp,servlet,action 等等文件中
UcService service = (UcService) WebApplicationContextUtils
.getRequiredWebApplicationContext(
request.getSession().getServletContext()).getBean(
"httpService" );
UserInfo user = service .getUserInfobyName( "hanqunfeng" );
如果不想配置 spring 运行环境,可以使用如下方式:
ApplicationContext applicationContext
= new 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;
}
)
二,Spring HTTP Invoker高级篇
默认情况下,客户端的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