项目介绍
最近在一个互联网跨境支付项目组,所使用的技术比较老,代码是写于2006年的,整个系统采用服务的架构模式,连接件使用hessian进行同步调用,使用MQ进行异步调用。
跨境系统的服务分类上,主要有两类,一类是线上的,比如交易,网关,出金,入金等,一类是线下的,比如对账,核算等。这个分类方法,有点像之前金融市场业务功能分成前中后台子系统。言归正传,本文主要是讲一下,hessian在该项目中的使用。
划分模块
整个工程分为两个WEB模块:客户调用模块client,服务处理模块handler。两个基本jar组件:服务注册组件register,hessian工具组件hessianutil.
register : 只有一个枚举,用于注册服务,一个服务一个枚举。是不是瞬间感觉低端了。
hessianutil : 提供了hessian操作的工具类套件。之所以将这两个分开,是因为hessianutil基本不变,而注册类就经常变动了
client : 服务调用者
handler : 服务提供者
代码
register:
public enum SerCode {
SIMPLE_CALL_RETURN_STRING("000000","简单调用"),
SIMPLE_CALL_RETURN_MAP("000001","返回字典");
private String code;
private String desc;
SerCode(String code, String desc) {
this.code = code;
this.desc = desc;
}
public String getCode() {
return code;
}
public String getDesc() {
return desc;
}
}
client:
注意在hessian的service中传入了handler的服务调用地址,hessian会创建代理,来实现RPC调用
public void makeSimpleCall(){
Map<String, String> paraMap = new HashMap<String,String>();
String reqMsg = JSonUtil.toJSonString(paraMap);
HessianInvokeParam param = HessianInvokeHelper.processRequest(reqMsg);
String sysTraceNo = SysTraceNoService
.generateSysTraceNo(SystemCodeEnum.WEBGATE.getCode());
String result = clientHessianService.invoke(
SerCode.SIMPLE_CALL_RETURN_STRING.getCode(), sysTraceNo,
SystemCodeEnum.WEBGATE.getCode(),
SystemCodeEnum.TXNCORE.getCode(),
SystemCodeEnum.TXNCORE.getVersion(), param.getDataLength(),
param.getMsgCompress(), param.getDataMsg());
param.parse(result);
HessianInvokeHelper.processResponse(param);
result = param.getDataMsg();
System.out.println("result:"+result);
}
<bean id="client-txnCoreService"
class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
<property name="serviceUrl" value="http://localhost:8080/handler/service/invoke" />
<property name="serviceInterface" value="com.mvp.hessian.service.HessianInvokeService" />
</bean>
handler:
public class SimpleHandler implements EventHandler {
public String handle(String dataMsg) throws HessianInvokeException {
return "this is from simple handler";
}
}
<!--bean配置-->
<bean id="txncoreService" class="com.mvp.hessian.service.HessianService">
<property name="eventHandlerMap" ref="eventHandlerMap" />
</bean>
<bean id="eventHandlerMap" class="java.util.HashMap">
<constructor-arg>
<map>
<entry key="000000" value-ref="simpleHandler" />
</map>
</constructor-arg>
</bean>
<bean id="simpleHandler" class="com.mvp.hessian.handler.SimpleHandler">
</bean>
<!--servlet配置-->
<bean name="/invoke" class="org.springframework.remoting.caucho.HessianServiceExporter">
<property name="serviceInterface" value="com.mvp.hessian.service.HessianInvokeService"/>
<property name="service" ref="txncoreService"/>
</bean>
<!--web.xml-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:context/**/*.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>remoting</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:remote/**/*.xml
</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>remoting</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>
通过如上配置,客户端就可以通过访问http://localhost:8080/handler...和对应的code来访问handler了。
hessianutil
封装了hessian的功能,便于调用。里面的类就不一一做介绍了。主要包括枚举类和帮助类。
//所有handler必须实现的接口
public interface EventHandler {
String handle(String dataMsg) throws HessianInvokeException;
}
//hessian调用时用的接口
public interface HessianInvokeService {
/**
* Hessian通讯服务接口
*
* @param serCode
* 服务代码
* @param sysTraceNo
* 系统跟踪号
* @param originNo
* 源系统编号
* @param targetNo
* 目的系统编号
* @param versionNo
* 接口版本号 格式:1.0.0
* @param dataLength
* 消息正文长度
* @param msgCompress
* 消息正文是否压缩
* @param dataMsg
* 消息正文
* @return
*/
String invoke(String serCode, String sysTraceNo, String originNo,
String targetNo, String versionNo, int dataLength, int msgCompress,
String dataMsg);
}
//调用的主要方法类
public class HessianService implements HessianInvokeService {
private final Log logger = LogFactory.getLog(HessianService.class);
private Map<String, EventHandler> eventHandlerMap;
public void setEventHandlerMap(Map<String, EventHandler> eventHandlerMap) {
this.eventHandlerMap = eventHandlerMap;
}
@SuppressWarnings("unchecked")
@Override
public String invoke(String serCode, String sysTraceNo, String originNo,
String targetNo, String versionNo, int dataLength, int msgCompress,
String dataMsg) {
logger.info("requet auth system:" + "serCode:" + serCode
+ "sysTraceNo:" + sysTraceNo + "originNo:" + originNo
+ "targetNo:" + targetNo + "versionNo:" + versionNo);
if(logger.isDebugEnabled()){
logger.info("dataMsg:" + dataMsg);
}
Map<String, String> result = new HashMap<String, String>();
try {
// 验证请求参数
HessianInvokeHelper.validateReqParam(serCode, sysTraceNo, originNo,
targetNo, versionNo, dataLength, msgCompress, dataMsg);
// 验证请求服务代码是否正确
EventHandler handler = eventHandlerMap.get(serCode);
if (handler == null) {
throw new HessianInvokeException(
ResponseCodeEnum.UNDEFINED_SERVICE.getCode(),
ResponseCodeEnum.UNDEFINED_SERVICE.getDesc());
}
// 验证目标系统编码
HessianInvokeHelper.validateTargetNo(targetNo,
SystemCodeEnum.TXNCORE.getCode());
// 验证请求消息正文内容长度
HessianInvokeHelper.validateDataMsgSize(dataLength, dataMsg);
String reqMsg = dataMsg;
// 判断是否需要解压请求消息正文内容
if (msgCompress == 1) {
try {
reqMsg = ZipUtil.uncompress(dataMsg);
} catch (IOException e) {
throw new HessianInvokeException(
ResponseCodeEnum.UNCOMPRESS_FAILURE.getCode(),
ResponseCodeEnum.UNCOMPRESS_FAILURE.getDesc(), e);
}
}
if(logger.isDebugEnabled()){
logger.info("reqMsg:" + reqMsg);
}
Map<String, Object> map = JSonUtil.toObject(reqMsg, Map.class);
map.put("sysTraceNo", sysTraceNo);
String rsp = handler.handle(JSonUtil.toJSonString(map));
return HessianInvokeHelper.buildResponse(serCode, sysTraceNo,
SystemCodeEnum.TXNCORE.getCode(), originNo, versionNo, rsp);
} catch (Exception e) {
logger.error(e.getMessage(), e);
logger.error(e.getMessage(), e);
result.put("responseCode",
ResponseCodeEnum.UNDEFINED_ERROR.getCode());
result.put("responseDesc",
ResponseCodeEnum.UNDEFINED_ERROR.getDesc());
}
return HessianInvokeHelper.buildResponse(serCode, sysTraceNo,
SystemCodeEnum.TXNCORE.getCode(), originNo, versionNo,
JSonUtil.toJSonString(result));
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。