基于annotation方式的通用报文处理框架

我们在开发报文处理服务时,会考虑对报文处理的简洁易配置,通常会想到通过配置文件,关联交易代码及相应的处理类,但新增的报文,需要修改该配置文件,会显得不够灵活,如果通过annotation避免配置文件的方式,易于扩展,简单易用,大概思路如下:

1、构建annontion接口,用于标识业务处理类

package com.variflight.data.analysis.core.msgengine.handler;

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author sunli
 * 
 * @date 2015年11月24日 下午3:52:03
 */
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MessageHandlerMarker {

	String version() default "";

	String code();

	boolean checkSign() default true;
}

2、报文处理基类

package com.variflight.data.analysis.core.msgengine.handler;

import java.util.Date;
import java.util.Iterator;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.alibaba.fastjson.JSON;
import com.variflight.data.analysis.core.msgengine.exception.ApplicationException;
import com.variflight.data.analysis.core.msgengine.exception.BizCheckException;
import com.variflight.data.analysis.core.msgengine.model.MessageObject;
import com.variflight.data.analysis.core.msgengine.model.MetaInfo;

/**
 * @author sunli
 * 
 * @date 2015年11月24日 下午3:52:03
 */
public abstract class AbstractMessageHandler<REQ, RSP> implements IMessageHandler<REQ> {

	private static Log logger = LogFactory.getLog(AbstractMessageHandler.class);

	private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

	@Override
	public MessageObject onEvent(MetaInfo meta, REQ request, String sign) throws BizCheckException {
		if (logger.isDebugEnabled()) {
			logger.debug("request message meta is :" + meta + ",data is : " + request);
		}
		RSP rspData = null;
		Set<ConstraintViolation<REQ>> constraintViolations = validator.validate(request);
		if (constraintViolations.size() > 0) {
			String errCode = meta.getMsgCode() + "00";
			StringBuffer errSB = new StringBuffer();
			Iterator<ConstraintViolation<REQ>> it = constraintViolations.iterator();
			while (it.hasNext()) {
				errSB.append(it.next().getMessage());
				if (it.hasNext()) {
					errSB.append(",");
				}
			}
			String error = String.format("参数校验失败:%s", errSB.toString());
			logger.info("请求参数: " + request + ", " + error);
			rspData = onApplicationException(meta, request, new ApplicationException(errCode, error));
		}
		if (rspData == null) {
			rspData = validateRequest(request);
		}
		if (rspData == null) {
			rspData = onHandler(meta, request, sign);
		}
		String rspSerno = genRspSerno(meta, request);
		MessageObject rsp = buildResponseMessage(meta, rspSerno, rspData);
		if (logger.isDebugEnabled()) {
			logger.debug("response message meta is :" + JSON.toJSONString(rsp.getMeta()) + ",data is : "
					+ JSON.toJSONString(rsp.getData()));
		}
		return rsp;
	}

	protected abstract String genRspSerno(MetaInfo meta, REQ request);

	// 校验报文有效性
	public abstract RSP validateRequest(REQ request);

	private String storeRequestMessage(REQ request) {
		return "123";
	}

	private RSP onHandler(MetaInfo meta, REQ request, String sign) {
		String msgId = storeRequestMessage(request);
		if (msgId == null) {
			throw new BizCheckException();
		}
		try {
			return onMessage(meta, request);
		} catch (ApplicationException appEx) {
			// 服务端非正常结束,如:抛出异常,使事务回滚
			return onApplicationException(meta, request, appEx);
		}
	}

	protected abstract RSP onMessage(MetaInfo meta, REQ request);

	protected abstract RSP onApplicationException(MetaInfo meta, REQ request, ApplicationException appEx);

	private MessageObject buildResponseMessage(MetaInfo meta, String rspSerno, RSP rspData) {
                // 应答报文
		MessageObject rspMessage = new MessageObject();
		rspMessage.setMeta(rspMeta);
		rspMessage.setData(rspData);
		return rspMessage;
	}

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
	}

}

3、系统启动时发现并注册消息处理类

系统接收到报文后,通过getTxProcessor方法txCode,version参数找到对应的处理类

package com.variflight.data.analysis.core.msgengine.handler;

import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.framework.Advised;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import com.variflight.data.analysis.core.msgengine.model.MessageObject;

/**
 * @author sunli
 * 
 * @date 2015年11月25日 下午13:02:22
 */
@Component
@SuppressWarnings({ "rawtypes", "unchecked" })
public class HandlersRegistry implements ApplicationContextAware {

	private final static Log logger = LogFactory.getLog(HandlersRegistry.class);

	private Map<String, METAINF> cache = new Hashtable<String, METAINF>();
	private ApplicationContext appCtx = null;
	private boolean isLoaded = false;

	public void setApplicationContext(ApplicationContext appCtx) throws BeansException {
		this.appCtx = appCtx;
	}

	/**
	 * Called by spring
	 */
	public void dispose() {
		cache.clear();
		cache = null;
	}

	public METAINF getTxProcessor(String version, String txCode) {
		if (logger.isDebugEnabled()) {
			logger.debug("try to load bean " + version + "::" + txCode);
		}
		if (cache.isEmpty()) {
			checkingHandler();
		}
		return cache.get(version + "::" + txCode);
	}

	private synchronized void checkingHandler() {
		if (!isLoaded) {
			isLoaded = true;
			Map<String, IMessageHandler> txProviders = BeanFactoryUtils.beansOfTypeIncludingAncestors(appCtx,
					IMessageHandler.class);

			if (logger.isDebugEnabled()) {
				logger.debug("Find result:" + txProviders);
			}

			for (Iterator<IMessageHandler> it = txProviders.values().iterator(); it.hasNext();) {
				IMessageHandler tx = it.next();
				// 被代理的类
				if (tx instanceof Advised) {
					Advised advised = (Advised) tx;
					try {
						tx = (IMessageHandler) advised.getTargetSource().getTarget();
					} catch (Exception ex) {
						logger.error("This should never happend", ex);
						throw new RuntimeException(ex);
					}
				}

				Class<? extends IMessageHandler> rc = tx.getClass();
				if (logger.isDebugEnabled()) {
					for (Annotation a : rc.getAnnotations()) {
						logger.debug(a);
					}
				}
				MessageHandlerMarker txMarker = rc.getAnnotation(MessageHandlerMarker.class);
				if (txMarker != null) {
					if (logger.isDebugEnabled()) {
						logger.debug("Find Processor ==>" + tx);
					}
					// 如果是直接实现接口
					Type ts[] = rc.getGenericInterfaces();
					if (ts.length > 0) {
						if (logger.isDebugEnabled()) {
							logger.debug("Processor implements IMessageHandler , checking it now");
						}
						for (Type t : ts) {
							if (t instanceof ParameterizedType) {
								Type[] p = ((ParameterizedType) t).getActualTypeArguments();
								METAINF metainf = new METAINF((Class<? extends MessageObject>) p[0], tx,
										txMarker.version(), txMarker.code(), txMarker.checkSign());
								cache.put(txMarker.version() + "::" + txMarker.code(), metainf);
								if (logger.isDebugEnabled()) {
									logger.debug("Added.");
								}
								break;
							}
						}
					}
					{
						// 检查是否实现类
						if (logger.isDebugEnabled()) {
							logger.debug(
									"Processor extends some class that implements IMessageHandler , checking it now");
						}
						Type sc = rc.getGenericSuperclass();
						if (sc instanceof ParameterizedType) {
							Type[] p = ((ParameterizedType) sc).getActualTypeArguments();
							METAINF metainf = new METAINF((Class<?>) p[0], tx, txMarker.version(), txMarker.code(),
									txMarker.checkSign());
							cache.put(txMarker.version() + "::" + txMarker.code(), metainf);
							if (logger.isDebugEnabled()) {
								logger.debug("Added.");
							}
						}
						if (logger.isDebugEnabled()) {
							logger.debug("Added.");
						}
					}
				}
			}
		}
	}

	/*------------- Inner Classes ------------------*/
	public static class METAINF {

		Class<?> requestClass;
		IMessageHandler<?> processor;
		String version;
		String msgType;
		boolean isCaSupport = true;

		public METAINF(Class<?> requestClass, IMessageHandler<? extends MessageObject> processor) {
			super();
			this.requestClass = requestClass;
			this.processor = processor;
		}

		public METAINF(Class<?> requestClass, IMessageHandler<?> processor, String version, String msgType,
				boolean isCaSupport) {
			super();
			this.requestClass = requestClass;
			this.processor = processor;
			this.version = version;
			this.msgType = msgType;
			this.isCaSupport = isCaSupport;
		}

		public Class<?> getRequestClass() {
			return requestClass;
		}

		public IMessageHandler<?> getProcessor() {
			return processor;
		}

		public boolean isCaSupport() {
			return this.isCaSupport;
		}

		@Override
		public String toString() {
			return "METAINF [version=" + version + ", msgType=" + msgType + ", processor=" + processor
					+ ", isCaSupport=" + isCaSupport + ",requestClass=" + requestClass + "]";
		}

	};

} 

4、报文处理类(例子)

package com.variflight.data.analysis.entity.fs.msg.handler;

import java.text.ParseException;
import java.util.Arrays;
import java.util.Date;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.variflight.data.analysis.common.model.EnumParamUtils;
import com.variflight.data.analysis.core.client.entity.service.AirportCapacityService;
import com.variflight.data.analysis.core.client.entity.service.AirportCapacityService.AirportCapacityQueryFilter;
import com.variflight.data.analysis.core.client.entity.service.AirportCapacityService.ResultCapacityForm;
import com.variflight.data.analysis.core.client.entity.service.CapacityService.ACT_QUERY_TYPE;
import com.variflight.data.analysis.core.client.entity.service.CapacityService.DATE_QUERY_TYPE;
import com.variflight.data.analysis.core.client.model.ServiceResult;
import com.variflight.data.analysis.core.msgengine.exception.ApplicationException;
import com.variflight.data.analysis.core.msgengine.handler.AbstractMessageHandler;
import com.variflight.data.analysis.core.msgengine.handler.MessageHandlerMarker;
import com.variflight.data.analysis.core.msgengine.model.MetaInfo;
import com.variflight.data.analysis.entity.fs.msg.form.AirportCapacityReqForm;
import com.variflight.data.analysis.entity.fs.msg.form.AirportCapacityRspForm;
import com.variflight.data.analysis.entity.fs.msg.form.base.FormBuilder;

/**
 * 机场运力分析
 * 
 * @author sunli
 * 
 * @date 2015年11月27日 上午午08:12:29
 */
@Component
@MessageHandlerMarker(code = "0201", version = "1.0", checkSign = false)
public class AirportCapacityMsgHandler extends AbstractMessageHandler<AirportCapacityReqForm, AirportCapacityRspForm> {
	private static Log logger = LogFactory.getLog(AirportCapacityMsgHandler.class);
	// 日期范围格式错误
	public static final String ER_DATE_FORMAT = "020101";

	@Autowired
	private AirportCapacityService airportCapacityService;

	@Override
	protected String genRspSerno(MetaInfo meta, AirportCapacityReqForm request) {
		return "";
	}

	@Override
	public AirportCapacityRspForm validateRequest(AirportCapacityReqForm request) {

		return null;
	}

	@Override
	protected AirportCapacityRspForm onMessage(MetaInfo meta, AirportCapacityReqForm request) {
		String airportcode = request.getAirport();
		Date begin = null;
		try {
			begin = DateFormatUtils.ISO_DATE_FORMAT.parse(request.getBeginDate());
		} catch (ParseException e) {
		}
		Date end = null;
		try {
			end = DateFormatUtils.ISO_DATE_FORMAT.parse(request.getEndDate());
		} catch (ParseException e) {
		}
		if (begin.compareTo(end) > 0) {
			return FormBuilder.buildRsp(AirportCapacityRspForm.class).setRtnCode(ER_DATE_FORMAT)
					.setRtnInfo("开始日期必须小于结束日期");
		}

		AirportCapacityQueryFilter filter = new AirportCapacityQueryFilter();
		if (StringUtils.isNotBlank(request.getAircodes())) {
			String[] codes = request.getAircodes().split(",");
			for (String code : codes) {
				if (StringUtils.isNotBlank(code)) {
					filter.getAircodes().add(code.toUpperCase());
				}
			}
		}

		if (StringUtils.isNotBlank(request.getDateTypes())) {
			DATE_QUERY_TYPE[] dtypes = EnumParamUtils.valueOfIgnoreCase(DATE_QUERY_TYPE.class, request.getDateTypes(),
					",");
			filter.getDateQueryTypes().addAll(Arrays.asList(dtypes));
		}

		if (StringUtils.isNotBlank(request.getActTypes())) {
			ACT_QUERY_TYPE[] dtypes = EnumParamUtils.valueOfIgnoreCase(ACT_QUERY_TYPE.class, request.getActTypes(),
					",");
			filter.getActQueryTypes().addAll(Arrays.asList(dtypes));
		}
		ServiceResult<ResultCapacityForm> result = airportCapacityService.airportCapacity(airportcode, begin, end,
				filter);
		return FormBuilder.buildRsp(AirportCapacityRspForm.class, result).setAirportCapacity(result.getResultObject());
	}

	@Override
	protected AirportCapacityRspForm onApplicationException(MetaInfo meta, AirportCapacityReqForm request,
			ApplicationException appEx) {
		return FormBuilder.buildRsp(AirportCapacityRspForm.class).setRtnCode(appEx.getResultCode())
				.setRtnInfo(appEx.getResultMsg());

	}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值