Hessian在實際項目中的使用

項目介紹

最近在一個互聯網跨境支付項目組,所使用的技術比較老,代碼是寫於2006年的,整個系統採用服務的架構模式,鏈接件使用hessian進行同步調用,使用MQ進行異步調用。
跨境系統的服務分類上,主要有兩類,一類是線上的,好比交易,網關,出金,入金等,一類是線下的,好比對帳,覈算等。這個分類方法,有點像以前金融市場業務功能分紅前中後臺子系統。言歸正傳,本文主要是講一下,hessian在該項目中的使用。java

劃分模塊

整個工程分爲兩個WEB模塊:客戶調用模塊client,服務處理模塊handler。兩個基本jar組件:服務註冊組件register,hessian工具組件hessianutil.web

register : 只有一個枚舉,用於註冊服務,一個服務一個枚舉。是否是瞬間感受低端了。
hessianutil : 提供了hessian操做的工具類套件。之因此將這兩個分開,是由於hessianutil基本不變,而註冊類就常常變更了
client : 服務調用者
handler : 服務提供者spring

代碼

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了。app

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));
    }
}
相關文章
相關標籤/搜索