因为公司的新项目不使用dubbo进行接口调用,为了复用dubbo部分的代码,将dubbo的接口改为hession接口。
本教程使用hession-4.0.33实现java远程过程调用,并和spring进行集成,记录使用过程中出现的问题和解决方法。
提供hession服务需要定义接口和实现,然后通过spring暴露引用。
<dependency>
<groupId>com.cauchogroupId>
<artifactId>hessianartifactId>
<version>4.0.38version>
dependency>
从maven库中下载的hession包缺少相关序列化和反序列化的配置,实际使用中BigDecimal会丢失精度,可以从Hessian-4.0.37jar包中获取,文件位于\META-INF\hessian,将其粘贴到本地库的jar包中,即可修复此bug。
将hessian接口、实体bean和异常类放入同一个工程中,方便客户端引用。api工程pom不引用任何其他依赖包,然后发布到公司maven库中,供客户端引用。
我采用的结构如下:

dto包:放入自定义的实体类,继承Serializable接口
exception:异常类,因为是从dubbo移植过来,异常类都继承了RuntimeException
service:接口定义
base.pojo:数据库实体bean,因为有时接口需要直接使用数据库实体bean,为了不影响mybaties的调用,必须将类移植到api工程中,并且不修改其所在包名,但需要继承Serializable接口。
hession对List、Map、BigDecimal等非基础类型进行了特殊处理,不能直接使用自定义泛型、使用继承List、Map的自定义类在传输过程中会丢失额外增加的字段数据。但可以参考BigDecimalDeserializer和StringValueSerializer等进行实现,然后在\META-INF\hessian进行配置。
hessian支持的数据类型请参考hessian java 类型
接口定义实例如下
public interface ZcpayService {
/**
* 获取菜单信息
* @return 菜单信息集合
*/
List<ZcpayMenu> getMenus();
}
需要实现spring的@Service接口,托管到spring中
@Service
public class ZcpayServiceImpl implements ZcpayService {
@Autowired
private ZcpayMenuService zcpayMenuService;
@Override
public List<ZcpayMenu> getMenus() {
return zcpayMenuService.selectByExample(null);
}
spring配置如下:
<beans xmlns="http://www.springframework.org/schema/beans" 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.xsd"
default-lazy-init="false">
<description>Spring Hession 服务端配置description>
<bean name="/zcpay" class="org.springframework.remoting.caucho.HessianServiceExporter">
<property name="service" ref="zcpayServiceImpl"/>
<property name="serviceInterface" value="com.bwjf.zcpay.api.service.ZcpayService"/>
bean>
beans>
web.xml配置
<servlet>
<servlet-name>hessian-servletservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath*:/spring-hessian-server.xmlparam-value>
init-param>
<load-on-startup>2load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>hessian-servletservlet-name>
<url-pattern>/hessian/*url-pattern>
servlet-mapping>
PS:如果系统使用了shiro或其他权限过滤,需要将/hessian/**地址设置为不校验权限。shiro配置如下
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
.......
<property name="filterChainDefinitions">
<value>
/hessian/**=anon
value>
property>
bean>
需要引用服务端API的maven依赖和hessian
<dependency>
<groupId>com.cauchogroupId>
<artifactId>hessianartifactId>
<version>4.0.38version>
dependency>
<dependency>
<groupId>com.whtygroupId>
<artifactId>zcpay-apiartifactId>
<version>1.0.0.zcversion>
dependency>
spring配置:
<beans xmlns="http://www.springframework.org/schema/beans"
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.xsd"
default-lazy-init="false">
<description>Spring hessian配置description>
<bean id="zcpayService" class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
<property name="serviceUrl">
<value>${zcpay_url}/zcpay/hessian/pgsmvalue>
property>
<property name="serviceInterface">
<value>com.whty.pgsm.api.service.PgsmServicevalue>
property>
bean>
beans>
以上配置完成后,即可在客户端使用@Autowired进行注入后使用
@Autowired
private ZcpayService zcpayService;