spring整合hessain远程访问
1.1 Hessian简介
Hessian是一个轻量级的Web服务实现工具,它采用的是二进制协议,因此很适合发送二进制数据。它的一个基本原理就是把远程服务对象以二进制的方式进行发送和接收
1.2 整合
1.2.1 概述
对于Hessian而言,有服务端和客户端,所以我们的整合也需要分服务端的整合和客户端的整合。服务端的整合是通过SpringMVC进行的,而客户端的整合则是通过Spring的bean进行的
1.2.2 服务端整合
[code="java"]public interface CouponService { public void add(); public void update(); public void delete(); }
我们再建一个实现接口 CouponServiceImpl:
public class CouponServiceImpl implements CouponService{ public void add(){ System.out.println("-----add------"); } public void update(){ System.out.println("-----update------"); } public void delete(){ System.out.println("-----delete------"); } }
那么接下来我们要做的就是把UserServiceImpl作为一个远程服务进行发布,以致客户端能够进行访问。 首先我们需要在web.xml中配置一个SpringMVC的DispatcherServlet用于接收所有的Web服务请求,这里我们这样配置:
<servlet> <servlet-name>remote</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:bean-hessian.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>remote</servlet-name> <url-pattern>/remote/*</url-pattern> </servlet-mapping>
可以看到我们这个DispatcherServlet会处理url为“/remote/*”的请求,通配符“*”就对应着我们的处理器映射。
接下来就是在SpringMVC的配置文件中利用Hessian来定义我们的远程服务了,这是通过Spring提供的HessianServiceExporter来实现的。我们需要在SpringMVC的配置文件中定义一个类型为HessianServiceExporter的bean对象。该bean对象需要接收两个属性,一个是service属性,用于关联真正的service对象,另一个是serviceInterface属性,用于指定当前的服务对应的接口。HessianServiceExporter实现了HttpRequestHandler接口,当我们请求某一个远程服务的时候实际上请求的就是其对应的HessianServiceExporter对象,HessianServiceExporter会把请求的服务以二进制的方式返回给客户端。这里我们在SpringMVC的配置文件中这样定义
<bean id="couponService" class="com.coupon.service.rpc.CouponServiceImpl"> <bean name="/couponService" class="org.springframework.remoting.caucho.HessianServiceExporter"> <property name="service" ref="couponService" /> <property name="serviceInterface" value="com.xebest.api.coupon.CouponService" /> </bean>
注意,因为是根据beanName来进行映射的,所以我们必须要给HessianServiceExporter bean对象指定name属性,而且其对应的name必须以“/”开头,这样我们的客户端才能访问到对应的服务。
1.2.3 客户端 rpc 自定义工厂调用
跟服务端对应的接口
package com.tiantian.hessianserver.service; public interface CouponService { public void add(); public void update(); public void delete(); }
这时候可以用spring配置文件整合也可以自己写一个工厂类去调用 在这里我们写一个工厂类类去调用
import java.net.MalformedURLException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.XMLConfiguration; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.caucho.hessian.client.HessianProxyFactory; public class CouponServiceFactory { private static Logger log = LoggerFactory.getLogger(CouponServiceFactory.class); private static int nodeCount; private static class LazyHolder{ private static final CouponServiceFactory INSTANCE= new CouponServiceFactory(); } public static CouponServiceFactory getInstance() { return LazyHolder.INSTANCE; } private CouponServiceFactory(){ init(); } private static Map<String, CouponService> couponService = new HashMap<String, CouponService>(); /** * 实例化 * PassportServiceFactory.instanceService()<BR> * <P>Author : hz </P> * <P>Date : 2014-1-24 </P> * @return */ public CouponService instanceService(){ Random rnd = new Random(); int i = rnd.nextInt(nodeCount); String index = "node" + i; if (couponService.get(index) != null) { return couponService.get(index); } return null; } /** * 初始化 * PassportServiceFactory.init()<BR> * <P>Author : hz </P> * <P>Date : 2014-1-24 </P> */ private static void init(){ XMLConfiguration wsConfigManager = null; try { wsConfigManager = new XMLConfiguration("xe-coupon-service.xml"); } catch (ConfigurationException e) { e.printStackTrace(); } List<Object> nodeList = wsConfigManager.getList("cluster.snode.id"); if(nodeList.size()==0) return ; nodeCount = nodeList.size(); for(int nodeIndex=0;nodeIndex<nodeList.size();nodeIndex++){ String url = wsConfigManager.getString("cluster.snode("+nodeIndex+").url"); String serviceName = wsConfigManager.getString("cluster.snode("+nodeIndex+").serviceName"); String hessianServiceName = wsConfigManager.getString("cluster.snode("+nodeIndex+").hessianServiceName"); String wsdlURL = ""; if(StringUtils.isNotBlank(serviceName)) { wsdlURL = "http://"+url + "/"+serviceName+"/"+hessianServiceName; } else { wsdlURL = "http://"+url + "/" +hessianServiceName; } log.info("url:==>" + wsdlURL); HessianProxyFactory hp = new HessianProxyFactory(); hp.setOverloadEnabled(true); try { couponService.put("node" + nodeIndex, (CouponService) hp.create(CouponService.class,wsdlURL)); } catch (MalformedURLException e) { } } } }
xml配置文件:xe-coupon-service.xml
<?xml version="1.0" encoding="UTF-8"?> <test-service> <!-- web service xfire配置开始 --> <cluster> <id>test-server</id> <snode> <id>snode2</id> <url>qa-manager-new.xebest.com</url> <hessianServiceName>remote/couponService</hessianServiceName> <trailnumber></trailnumber> <hessianuser></hessianuser> </snode> </cluster> <!-- web service xfire 配置结束 --> </test-service>
调用 :
public class Demo{ //获取接口 CouponService couponService=CouponServiceFactory.getInstance.instanceService(); couponService.add(); couponService.update(); couponService.delete(); }
1.2.4 也可以用spring 配置文件调用:
接口:
package com.tiantian.hessianserver.service; public interface CouponService { public void add(); public void update(); public void delete(); }
spring的配置文件:
<bean name="couponService" class="org.springframework.remoting.caucho.HessianProxyFactoryBean"> <property name="serviceUrl" value="http://qa-manager-new.xebest.com/remote/couponService" /> <property name="serviceInterface" value="com.tiantian.hessianserver.service.CouponService"/> </bean>
调用:
public class Demo{ @Auwrite CouponService couponService; couponService.add(); couponService.update(); couponService.delete(); }