您的位置:首页 > 编程语言 > Java开发

Spring整合Hessian

2015-10-29 17:27 453 查看


转载自 Spring整合Hessian


前言:

近日着手研究了一下Hessian的rmi方案,因为客户端是多种移动终端平台,本来想采用传说中的phprpc(hprose?)的,但看了下官方的文档,发现没有object-c的版本,故而放弃。

跟着hessian 的官方例子走,跑起来是没有问题的,但我在试着跟spring整合的时候,出了不少的问题。记录一下,方便自己以及路人,呵呵。



环境说明:

spring version 3.0 RELEASE.
Hessian version 4.0.7 WHATEVER.

JEE version 2.5


实现步骤:

配置 web.xml ,添加对spring-web中 DispatcherServlet的定义.具体如下:

Xml代码


<servlet>

<servlet-name>test-remote</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<init-param>

<param-name>contextConfigLocation</param-name>

<param-value>/WEB-INF/config/test-remote.xml</param-value>

</init-param>

<load-on-startup>4</load-on-startup>

</servlet>



<servlet-mapping>

<servlet-name>test-remote</servlet-name>

<url-pattern>/remote/*</url-pattern>

</servlet-mapping>

Tips:

A. 很多网友都说一定要在WEB-INF下面放入跟servlet-name相对应的 test-remote-servlet.xml 配置文件,实际上是不一定要那么处理的。如果指定了 contextConfigLocation的话,就可以解决这个问题。意味着spring不会强制要求你配置文件的位置。

B. DispatcherServlet是可以配置多个的,我这里还有一个test-local,mapping着 "/" 路径,他们之间并不会影响。当然可以单纯的配置多个 servlet-mapping.我只是想验证一下,结果说明确实是可以的。
传输对象类Space 的定义:

Java代码


package test.remote.dto;



import java.io.Serializable;

import java.util.Date;



/**

* Space data transfer object.

* @author gogo

*

*/

public class Space implements Serializable{



/**

* auto generated serialVersionUid.

*/

private static final long serialVersionUID = 5632812127919571530L;



/** public space name for people in the space.*/

private String publicName;

private String privateName;

private boolean isActive;

private Date lastUpdatedTime;



/**

* setter & getter

*/



@Override

public String toString() {

StringBuilder buffer = new StringBuilder("Space:");

buffer.append("public name:").append(publicName).append(", ");

buffer.append("private name:").append(privateName).append(", ");

buffer.append("is actived:").append(isActive).append(", ");

buffer.append("lastUpdatedTime:").append(lastUpdatedTime.getTime());

return buffer.toString();

}

}


服务接口的定义如下:

package test.remote.service;

Java代码


import java.util.List;



import test.remote.dto.Space;



/**

*

* @author gogo

*

*/

public interface SpaceService {



List showSpaceNames(); //返回名字集合



Space findSpace(String id);//找到空间名字



boolean updateSpaceName(String name); //更新空间名字



}


服务接口实现类:

package test.remote.service.impl;

Java代码


import java.util.ArrayList;

import java.util.Date;

import java.util.List;



import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import org.springframework.remoting.caucho.HessianServiceExporter;



import test.remote.dto.Space;

import test.remote.service.SpaceService;



/**

* 这个是一个远程接口的测试实现<br>

* 该接口会由spring的 {@link HessianServiceExporter}以Http服务的形式暴露.<br>

* 客户端会依赖Hessian实现

* @see HessianServiceExporter

* @author gogo

*

*/

public class SpaceServiceImpl implements SpaceService{



private static final Log log = LogFactory.getLog(SpaceServiceImpl.class);



private Space createSpace() {

Space space = new Space();

space.setPublicName("roosher-space");

space.setPrivateName("my-private-room");

space.setActive(true);

space.setLastUpdatedTime(new Date());

return space;

}



public Space findSpace(String id) {

// TODO Auto-generated method stub

log.debug("find space id is :" + id);

return createSpace();

}



public List showSpaceNames() {

// TODO Auto-generated method stub

List names = new ArrayList<String>();

for (int i = 0; i < 10; i++) {

names.add("Hello space "+ i);

}

return names;

}



public boolean updateSpaceName(String name) {

// TODO Auto-generated method stub

log.debug("updated space name : " + name );

return true;

}



}


test-remote.xml的内容:

Xml代码


<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:context="http://www.springframework.org/schema/context"

xmlns:p="http://www.springframework.org/schema/p"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

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.BeanNameUrlHandlerMapping"

p:order="1"></bean>



<bean id="spaceService" class="test.service.impl.SpaceServiceImpl">

</bean>



<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter">

</bean>



<bean name="/SpaceHessian"

class="org.springframework.remoting.caucho.HessianServiceExporter"

p:serviceInterface="test.remote.service.SpaceService"

p:service-ref="spaceService">

</bean>



<bean name="/SpaceBurlap"

class="org.springframework.remoting.caucho.BurlapServiceExporter"

p:serviceInterface="test.remote.service.SpaceService"

p:service-ref="spaceService">

</bean>



</beans>

Tips:

A. BeanNameUrlHandlerMapping 属性中的 p:order="1",可以不用配置.避免跟自己的冲突.

B. HttpRequestHandlerAdapter 在这里面非常关键,没有它可能会出现这种错误:

-- No adapter for handler Does your handler implement a supported interface like Controller ? HttpRequestHandlerAdapter它的作用就是让spring-mvc放出权限给下面的Exporter自己处理整个HTTP 流程.毕竟HessianServiceExporter也是实现的HttpRequestHandler
客户端的两种实现:

A. 就是基于spring的实现,采用org.springframework.remoting.caucho.HessianProxyFactoryBean实现,相关配置如下:



Java代码


<bean id="spaceServiceHessian"

class="org.springframework.remoting.caucho.HessianProxyFactoryBean">

<property name="serviceUrl"

value="http://localhost:8080/test/remote/SpaceHessian" />

<property name="serviceInterface" value="test.remote.service.SpaceService" />

</bean>



<bean id="spaceServiceBurlap"

class="org.springframework.remoting.caucho.BurlapProxyFactoryBean">

<property name="serviceUrl"

value="http://localhost:8080/test/remote/SpaceBurlap" />

<property name="serviceInterface" value="test.remote.service.SpaceService" />

</bean>

注意到里面的URL了没? 其中 http://localhost:8080/test/remote/SpaceHessian 的/SpaceHessian 对应的是之前在remote-test.xml中配置的<bean name="/SpaceHessian"> </bean>的URI.

然后通过spring获取上下文之后,就可以直接注入 SpaceService service = context.getBean("spaceServiceBurlap");

B . 就是基于Hessian 自己提供的客户端,这里展示的是Java版本.



Java代码


package test.remote;



import java.net.MalformedURLException;

import java.util.List;



import com.caucho.hessian.client.HessianProxyFactory;

import test.remote.dto.Space;

import test.remote.service.SpaceService;



/**

* 连接客户端。测试时要注意 url的ip地址.

* @see Space

* @author gogo

*

*/

public class SpaceClient {



public static void main(String[] args) {

String url = "http://192.168.0.9:8080/test/remote/SpaceHessian";

HessianProxyFactory factory = new HessianProxyFactory();

try {

SpaceService spaceService = (SpaceService) factory.create(

SpaceService.class, url);

System.out.println(spaceService.findSpace("testid"));

System.out.println(spaceService.updateSpaceName("whatever"));



List spaceNames = spaceService.showSpaceNames();

System.out.println("\r\nGet space names:");

for (int i = 0; i < spaceNames.size(); i++) {

System.out.print(spaceNames.get(i) + ", ");

}

System.out.println();

System.out.println("space names list finished");

} catch (MalformedURLException e) {

e.printStackTrace();

}

}

}

如果后台没有什么太大的问题,直接跑起来就可以测试了。

测试结果:

Java代码


Space:public name:roosher-space, private name:my-private-room, is actived:true,

lastUpdatedTime:1282196778538

true



Get space names:

Hello space 0, Hello space 1, Hello space 2, Hello space 3, Hello space 4, Hello space 5

, Hello space 6, Hello space 7, Hello space 8, Hello space 9,

space names list finished
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: