Spring HTTP invoker簡(jiǎn)介
Spring HTTP invoker是spring框架中的一個(gè)遠(yuǎn)程調(diào)用模型,執(zhí)行基于HTTP的遠(yuǎn)程調(diào)用(意味著可以通過防火墻),并使用java的序列化機(jī)制在網(wǎng)絡(luò)間傳遞對(duì)象??蛻舳丝梢院茌p松的像調(diào)用本地對(duì)象一樣調(diào)用遠(yuǎn)程服務(wù)器上的對(duì)象,這有點(diǎn)類似于webservice,但又不同于webservice,區(qū)別如下:
webservice
|
HTTP invoker
|
跨平臺(tái),跨語(yǔ)言
|
只支持java語(yǔ)言
|
支持SOAP,提供wsdl
|
不支持
|
結(jié)構(gòu)龐大,依賴特定的webservice實(shí)現(xiàn),如xfire等
|
結(jié)構(gòu)簡(jiǎn)單,只依賴于spring框架本身
|
項(xiàng)目中使用哪種遠(yuǎn)程調(diào)用機(jī)制取決于項(xiàng)目本身的要求。
² HTTP invoker 服務(wù)模式
說明:
1. 服務(wù)器端:通過HTTP invoker服務(wù)將服務(wù)接口的某個(gè)實(shí)現(xiàn)類提供為遠(yuǎn)程服務(wù)
2. 客戶端:通過HTTP invoker代理向服務(wù)器端發(fā)送請(qǐng)求,遠(yuǎn)程調(diào)用服務(wù)接口的方法
3. 服務(wù)器端與客戶端通信的數(shù)據(jù)需要序列化
配置服務(wù)器端和客戶端的步驟
配置服務(wù)器端
1. 添加springJAR文件
建議使用spring2+.jar版本
2. 創(chuàng)建服務(wù)接口
3. 創(chuàng)建服務(wù)接口的具體實(shí)現(xiàn)類
4. 公開服務(wù)
配置客戶端
1. 添加springJAR文件
建議使用spring2+.jar版本
2. 創(chuàng)建服務(wù)接口
3. 訪問服務(wù)
實(shí)例講解
服務(wù)器端
1.服務(wù)接口:UcService.java
它提供兩項(xiàng)服務(wù),查詢用戶信息和記錄日志,如下:
- public interface UcService {
-
- public UserInfo getUserInfobyName(String userName);
-
- public int recordLog(String username, String point, String operate, String desc);
-
- }
說明:舉這個(gè)列子是因?yàn)槠浔容^有代表性,它將展示普通數(shù)據(jù)類型(int,long等)和復(fù)雜數(shù)據(jù)類型(DTO等)的遠(yuǎn)程調(diào)用方式。UserInfo是一個(gè)普通的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;
-
- }
-
- }
-
注意:因?yàn)槭窃诰W(wǎng)絡(luò)間傳輸對(duì)象,所以需要將UserInfo實(shí)現(xiàn)Serializable接口,并指定一個(gè)serialVersionUID(任意值即可,同時(shí)客戶端也要有這個(gè)類,否則在客戶端接收對(duì)象時(shí)會(huì)因?yàn)閟erialVersionUID不匹配而出現(xiàn)異常)
回到UcService.java,它提供了兩個(gè)服務(wù)(在這里一個(gè)方法代表一個(gè)服務(wù)功能),我們需要具體的實(shí)現(xiàn)類來實(shí)現(xiàn)真正的服務(wù)
2.實(shí)現(xiàn)類是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注入的一個(gè)數(shù)據(jù)查詢類,因?yàn)樗chttp invoker沒有直接關(guān)系,所以不進(jìn)行介紹。
3.公開服務(wù)UcService.java
² WEB-INF/application-context.xml:將接口聲明為HTTP invoker服務(wù)
- <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實(shí)際上是一個(gè)spring mvc控制器,它處理客戶端的請(qǐng)求并調(diào)用服務(wù)實(shí)現(xiàn)。
² WEB-INF/service-servlet.xml:HttpInvokerServiceExporter實(shí)際上是一個(gè)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監(jiān)聽及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方面的資料。
好了,經(jīng)過以上配置,一個(gè)基于spring HTTP invoker的遠(yuǎn)程服務(wù)就完成了,服務(wù)的地址為:
http://${serviceName}:${port}/${contextPath}/service/httpService
客戶端
1. 創(chuàng)建服務(wù)接口及網(wǎng)絡(luò)間傳輸?shù)腄TO類
為了方便,可以將服務(wù)器端創(chuàng)建好的的UcService.java和UserInfo.java拷貝到客戶端,或打個(gè)jar包放到lib下。
2. 配置訪問服務(wù)
² WEB-INF/application-context.xml:如果項(xiàng)目中已經(jīng)存在spring配置文件,則不需要?jiǎng)?chuàng)建該文件,需要配置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代理客戶端向服務(wù)器端發(fā)送請(qǐng)求,請(qǐng)求接口為UcService的服務(wù)
注意:需要修改serviceUrl為實(shí)際的服務(wù)器地址
² WEB-INF/web.xml:配置spring監(jiān)聽
如果項(xiàng)目沒有spring環(huán)境,則需要在web.xml中加入對(duì)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. 訪問服務(wù)方法
u 讀取spring上下文,以遠(yuǎn)程調(diào)用getUserInfobyName方法為例
² 在jsp,servlet,action等等文件中
- UcService service = (UcService) WebApplicationContextUtils
-
- .getRequiredWebApplicationContext(
-
- request.getSession().getServletContext()).getBean(
-
- "httpService");
-
- UserInfo user = service.getUserInfobyName("hanqunfeng");
-
² 如果不想配置spring運(yùn)行環(huán)境,可以使用如下方式:
- ApplicationContext applicationContext
-
- = new FileSystemXmlApplicationContext("classpath:application-context.xml");
-
- service = (UcService) applicationContext.getBean("httpService");
u 依賴注入,遠(yuǎn)程調(diào)用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中加入對(duì)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;
-
- }
-