Spring HttpInvoker的简单封装,优点如下:
1、客户端无xml配置
2、客户端基于接口调用,无需知道接口的服务名。
(大众型使用方式:接口可以打成jar分发到服务端和客户端程序使用。我是使用maven构建项目,所以建立了一个service-code项目供serviceProject和clientProject引用)
3、服务端只需配置简单的2步骤,后面介绍。
封装文件一共7个类,先分别说下客户端和服务端的使用配置,再解释原理:
SpringMVCApplicationContextUtil.java
SpringRemoteServiceContext.java
RemoteServiceDescService.java
DefaultRemoteServiceDescServiceImpl.java
HttpInvokerRemoteServiceDescContainer.java
HttpInvokerClientServiceFactory.java
RemoteConnectFailureExceptionExt.java
客户端调用服务的示例代码如下:
HttpInvokerClientServiceFactory.init();//只需初始化一次 String serverURL = "http://localhost:8080/liangfa-analysis";//服务地址 //获得远程服务TestService,就像是调用本地服务那样(自行捕获通信异常) TestService testService = HttpInvokerClientServiceFactory.getService(serverURL, TestService.class); //调用服务 testService.sayHello(); //客户端api是不是很简单?? 只需要一个HttpInvokerClientServiceFactory就搞定了 : )
服务端的2处配置:
1、配置远程服务文件remoting-servlet.xml,除了配置业务有关的服务(如TestService),需要加入RemoteServiceDescService,服务名约定为“/remote/remoteServiceDesc”
(HttpInvokerRemoteServiceDescContainer中有常量配置)
<!--暴漏远程服务:服务列表描述 required--> <bean name="RemoteServiceDescService" class="com.ksource.liangfa.ws.core.util.remote.DefaultRemoteServiceDescServiceImpl"> </bean> <bean name="/remote/remoteServiceDesc" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter"> <property name="service" ref="RemoteServiceDescService"></property> <property name="serviceInterface" value="com.ksource.liangfa.ws.core.util.remote.RemoteServiceDescService"/> </bean> <!--测试服务--> <bean name="/remote/TestService" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter"> <property name="service" ref="RemoteTestService"></property> <property name="serviceInterface" value="com.ksource.liangfa.ws.core.service.datacenter.TestService"/> </bean> ......其他服务.......
2、初始化服务描述的上下文(remoting-servlet.xml)
SpringRemoteServiceContext.initContext(SpringMVCApplicationContextUtil.getWebApplicationContext(config.getServletContext(), "springServletName"));
我的做法是在项目的初始化servlet(SystemInit.init)里调用,如下:
配置web.xm,在项目启动servlet里
<servlet> <servlet-name>SystemInit</servlet-name> <servlet-class>com.ksource.syscontext.SystemInit</servlet-class> <load-on-startup>3</load-on-startup> </servlet>
public class SystemInit extends HttpServlet { @Override public void init(ServletConfig config) throws ServletException { SpringRemoteServiceContext.initContext(SpringMVCApplicationContextUtil.getWebApplicationContext(config.getServletContext(), "springServlet")); ....... ....... } }
实现思路:
SpringMVCApplicationContextUtil用于获取spring mvc的bean容器,这个容器包含了spring mvc配置文件里配置的bean(同样包含remoting-servlet.xml)
DefaultRemoteServiceDescServiceImpl本身也是暴漏的服务,但他的作用主要是用于描述服务端暴漏的服务,有点类WSDL的意味。
SpringRemoteServiceContext通过bean容器找出暴漏的服务,保存到map中
public class SpringRemoteServiceContext { private static Map<String, HttpInvokerServiceExporter> servicesMap; public static void initContext( ApplicationContext applicationContext) { servicesMap = applicationContext.getBeansOfType(HttpInvokerServiceExporter.class); } public static Map<String, HttpInvokerServiceExporter> getServicesMap(){ return servicesMap; } }
HttpInvokerRemoteServiceDescContainer用于保存一个服务端的全部接口的服务地址。
HttpInvokerClientServiceFactory用于根据接口名称,来获取远程服务对象。
HttpInvokerClientServiceFactory.getService(String serverUrl, Class<T> clazz)方法,会根据
serverUrl来获取HttpInvokerRemoteServiceDescContainer对象,然后通过服务描述来创建HttpInvokerProxyFactoryBean对象,然后HttpInvokerProxyFactoryBean.getObject()来得到远程服务。
大致思路如上,整理的比较乱,可参见源码,包名可自行修改后使用。