用户工具

站点工具


分享:技术:交易监控:交易监控中间件_实现

这是本文档旧的修订版!


交易监控中间件_实现

目前情况

暂时还没有搞成真正的中间件,只是把相关代码写在这里,想要集成的朋友可以copy到项目中。

之后有时间,考虑下做成真正的中间件,以jar/pom的方式方便感兴趣的朋友集成!

SQL

update.sql
############################
#交易监控需求
############################
CREATE TABLE `la_trans_monitor` (
  `id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `sys_date` CHAR(8) NOT NULL COMMENT '系统日期',
  `sys_time` CHAR(6) NOT NULL COMMENT '系统时间',
  `method_type` VARCHAR(10) NOT NULL COMMENT '方法类型,PO:提供对外服务方法,IN:内部服务方法,IO:调用外部方法,SQL:内部sql',
  `outer_system` VARCHAR(20) COMMENT '外部系统代码',
  `method_route` VARCHAR(500) NOT NULL COMMENT '方法路径',
  `method_name` VARCHAR(500) NOT NULL COMMENT '方法名称',
  `request` longtext COMMENT '入参',
  `response` longtext COMMENT '出参',
  `is_exception` INT(1) NOT NULL DEFAULT '0' COMMENT '是否异常发生,0:没发生异常,1:发生异常',
  `begin_time` TIMESTAMP(3) NOT NULL COMMENT '开始时间',
  `end_time` TIMESTAMP(3) NOT NULL COMMENT '结束时间',
  `used_time` BIGINT NOT NULL COMMENT '耗时(毫秒)',
  `ip` VARCHAR(100) COMMENT '机器ip',
  `resv1` VARCHAR(100) COMMENT '备注字段1',
  `resv2` VARCHAR(100) COMMENT '备注字段2',
  `resv3` VARCHAR(100) COMMENT '备注字段3',
  `is_delete` INT(1) NOT NULL DEFAULT '0' COMMENT '是否删除,0:不删除,1:删除',
  `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '数据创建时间',
  `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '数据更新时间',
  PRIMARY KEY (`id`),
  KEY `ix_sys_date` (`sys_date`) ,
  KEY `ix_method_type` (`method_type`) ,
  KEY `ix_method_route` (`method_route`) ,
  KEY `ix_is_exception` (`is_exception`) ,
  KEY `ix_created_at` (`created_at`),
  KEY `ix_updated_at` (`updated_at`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='交易监控表';

LogMethodTime.java

LogMethodTime.java
package com.shhxzq.fin.lifeapp.model.base;
 
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;
 
import org.apache.commons.lang.StringUtils;
 
/** 
 * 方法打日志并计算时间注解
 * @author Gxx
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface LogMethodTime {
	/**
	 * 是否监控
	 * 前提:true才监控
	 * @return
	 */
	boolean isMonitor() default false;
 
	/**
	 * 监控方法类型枚举
	 * @return
	 */
	MonitorMethodTypeEnum monitorMethodType() default MonitorMethodTypeEnum.IN;
 
	/**
	 * 外部系统代码
	 * @return
	 */
	SystemEnum outerSystem() default SystemEnum.LIFE_APP;
 
	/**
	 * 方法名称
	 * @return
	 */
	String methodName() default StringUtils.EMPTY;
 
	/**
	 * 备注字段1
	 * @return
	 */
	String resv1() default StringUtils.EMPTY;
 
	/**
	 * 备注字段2
	 * @return
	 */
	String resv2() default StringUtils.EMPTY;
 
	/**
	 * 备注字段3
	 * @return
	 */
	String resv3() default StringUtils.EMPTY;
}

MonitorMethodTypeEnum.java

MonitorMethodTypeEnum.java
package com.shhxzq.fin.lifeapp.model.base;
 
import org.apache.commons.lang.StringUtils;
 
/**
 * 监控方法类型枚举
 * @author Gxx
 */
public enum MonitorMethodTypeEnum {
 
	PROVIDE_OUT("PO", "提供对外服务方法"),
	IN("IN", "内部服务方法"),
	INVOKE_OUT("IO", "调用外部方法"),
	SQL("SQL", "SQL"),
	;
 
	/**
	 * 类型
	 */
	private String type;
 
	/**
	 * 名称
	 */
	private String name;
 
	/**
	 * 构造函数
	 * @param type
	 * @param name
	 */
	MonitorMethodTypeEnum(String type, String name){
		this.type = type;
		this.name = name;
	}
 
	/**
	 * 根据type获取枚举,查不到返回null
	 * @param type
	 * @return
	 */
	public static MonitorMethodTypeEnum getMonitorMethodTypeEnumByType(String type){
		/**
		 * 循环便利该类中的所有枚举
		 */
		for(MonitorMethodTypeEnum temp : MonitorMethodTypeEnum.values()){
			if(StringUtils.equals(temp.getType(), type)){
				return temp;
			}
		}
		/**
		 * 查询不到,返回null
		 */
		return null;
	}
 
	public String getType() {
		return type;
	}
 
	public void setType(String type) {
		this.type = type;
	}
 
	public String getName() {
		return name;
	}
 
	public void setName(String name) {
		this.name = name;
	}
}

SystemEnum.java

SystemEnum.java
package com.shhxzq.fin.lifeapp.model.base;
 
import org.apache.commons.lang.StringUtils;
 
/**
 * 系统枚举
 * @author Gxx
 */
public enum SystemEnum {
 
	LIFE_APP("la", "生活应用"),
	BANK_ENGINE("be", "银行引擎"),
	SUPER_GATEWAY("spw", "超网"),
	BEI_DOU("beidou", "安全中心"),
	CTS("cts", "交易"),
	;
 
	/**
	 * 类型
	 */
	private String system;
 
	/**
	 * 名称
	 */
	private String name;
 
	/**
	 * 构造函数
	 * @param system
	 * @param name
	 */
	SystemEnum(String system, String name){
		this.system = system;
		this.name = name;
	}
 
	/**
	 * 根据system获取枚举,查不到返回null
	 * @param system
	 * @return
	 */
	public static SystemEnum getSystemEnumBySystem(String system){
		/**
		 * 循环便利该类中的所有枚举
		 */
		for(SystemEnum temp : SystemEnum.values()){
			if(StringUtils.equals(temp.getSystem(), system)){
				return temp;
			}
		}
		/**
		 * 查询不到,返回null
		 */
		return null;
	}
 
	public String getSystem() {
		return system;
	}
 
	public void setSystem(String system) {
		this.system = system;
	}
 
	public String getName() {
		return name;
	}
 
	public void setName(String name) {
		this.name = name;
	}
}

application-context.xml

application-context.xml
	<!-- 服务层AOP begin -->
	<bean id="serviceAop" class="com.shhxzq.fin.lifeapp.biz.utils.ServiceAop" />
	<aop:config>
		<aop:aspect id="serviceAspect" ref="serviceAop">
			<aop:pointcut id="target" expression="execution(* com.shhxzq.fin.lifeapp..*.*(..))" />
			<aop:around method="around" pointcut-ref="target" />
		</aop:aspect>
	</aop:config>
	<!-- 服务层AOP end -->

spring-mcv.xml

spring-mcv.xml
	<!-- 扫描控制器类 -->
	<context:component-scan base-package="com.shhxzq.fin.lifeapp" />
 
	<!-- 让aop可以切面到controller -->
	<aop:aspectj-autoproxy proxy-target-class="true"/>

ServiceAop.java

ServiceAop.java
package com.shhxzq.fin.lifeapp.biz.utils;
 
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
 
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;
 
import com.shhxzq.fin.lifeapp.biz.service.RabbitService;
import com.shhxzq.fin.lifeapp.model.base.BaseUuidLogger;
import com.shhxzq.fin.lifeapp.model.base.BusinessException;
import com.shhxzq.fin.lifeapp.model.base.LogMethodTime;
import com.shhxzq.fin.lifeapp.model.base.MonitorMethodTypeEnum;
import com.shhxzq.fin.lifeapp.model.base.SystemEnum;
 
/**
 * 服务层AOP
 * @author Gxx
 */
public class ServiceAop {
 
	/**
	 * 日志记录器
	 */
	Logger logger = BaseUuidLoggerUtils.getBaseUuidLogger();
 
	/**
	 * 方法前后操作
	 * @param pjp
	 * @return
	 * @throws Exception
	 */
	public Object around(ProceedingJoinPoint pjp) throws Throwable {
		/**
		 * 获取切面方法
		 */
		Signature sig = pjp.getSignature();
		MethodSignature msig = null;
		if (!(sig instanceof MethodSignature)) {
			throw new IllegalArgumentException("该注解只能用于方法");
		}
		msig = (MethodSignature) sig;
		Object target = pjp.getTarget();
		Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
 
		/**
		 * 判断是否有Logger对象,有则强制设置为BaseUuidLogger
		 */
		Field[] files = target.getClass().getDeclaredFields();
		for(Field field : files) {
			if(field.getType() == Logger.class) {
				/**
				 * 私有变量必须先设置Accessible为true
				 */
	            field.setAccessible(true);
				/**
				 * 判断是否第一次赋值
				 */
				if(!(field.get(target) instanceof BaseUuidLogger)) {
					/**
					 * 创建基础日志操作实体-同一个线程的uuid是一样的
					 */
					BaseUuidLogger uuidLogger = new BaseUuidLogger();
					/**
					 * 拷贝属性-父类向子类拷贝(两层父类)
					 */
					BeanUtils.copyPropertiesLevel2(uuidLogger, field.get(target));
					/**
					 * 覆盖设置Logger对象
					 */
		            field.set(target, uuidLogger);
				}
			}
		}
 
		/**
		 * 判断是否加注解@LogMethodTime 和 是否落地
		 */
		boolean isLogMethodTime = currentMethod.isAnnotationPresent(LogMethodTime.class);//是否加注解@LogMethodTime
		boolean isMonitor = false;//是否监控
		MonitorMethodTypeEnum monitorMethodType = null;//监控方法类型枚举
		SystemEnum outerSystem = null;//外部系统代码
		String methodName = null;//方法名称
		String resv1 = null;//备注字段1
		String resv2 = null;//备注字段2
		String resv3 = null;//备注字段3
 
		/**
		 * 判断是否加注解@LogMethodTime
		 */
		if(isLogMethodTime) {
			Annotation p = currentMethod.getAnnotation(LogMethodTime.class);
 
			Method m = p.getClass().getDeclaredMethod("isMonitor", null);
			isMonitor = (boolean) m.invoke(p, null);
 
			/**
			 * 判断是否监控
			 */
			if(isMonitor) {
				m = p.getClass().getDeclaredMethod("monitorMethodType", null);
				monitorMethodType = (MonitorMethodTypeEnum) m.invoke(p, null);
 
				m = p.getClass().getDeclaredMethod("outerSystem", null);
				outerSystem = (SystemEnum) m.invoke(p, null);
 
				m = p.getClass().getDeclaredMethod("methodName", null);
				methodName = (String) m.invoke(p, null);
 
				m = p.getClass().getDeclaredMethod("resv1", null);
				resv1 = (String) m.invoke(p, null);
 
				m = p.getClass().getDeclaredMethod("resv2", null);
				resv2 = (String) m.invoke(p, null);
 
				m = p.getClass().getDeclaredMethod("resv3", null);
				resv3 = (String) m.invoke(p, null);
			}
		}
 
		/**
		 * 类.方法 名字
		 */
		String targetName = pjp.getTarget().getClass().getName() + "." + pjp.getSignature().getName();
		String request = StringUtils.EMPTY;
		String response = StringUtils.EMPTY;
 
		/**
		 * 判断是否加注解@LogMethodTime
		 */
		if(isLogMethodTime) {
			request = BeAopUtil.getStringFromRequest(pjp.getArgs());
			String requestMsg = "log - {0} request - {1}";
			logger.info(MessageFormat.format(requestMsg, new Object[] { targetName, request }));
		}
 
		/**
		 * 开始时间 结束时间 耗时 是否异常发生
		 */
		long begin = DateUtils.getNow().getTime();
		long end = 0;
		long usedTime = 0;
		boolean isException = false;
 
		Object result = null;
		try {
			/**
			 * 执行方法
			 */
			result = pjp.proceed();
 
			/**
			 * 返回信息
			 */
			response = BeAopUtil.getStringFromResponse(result);
 
			/**
			 * 返回结果
			 */
			return result;
		} catch (BusinessException t) {
			logger.error(targetName + " exception occure!reason:" + t.getMessage());
 
			/**
			 * 异常发生,返回报文为异常信息
			 */
			isException = true;
			response = t.getMessage();
 
			throw t;
		} catch (Throwable t) {
			logger.error(targetName + " exception occure!", t);
 
			/**
			 * 异常发生,返回报文为异常信息
			 */
			isException = true;
			response = t.getMessage();
 
			throw t;
		} finally {
			try {
				/**
				 * 注解@LogMethodTime才计算计算时间
				 */
				if(isLogMethodTime) {
					end = DateUtils.getNow().getTime();
					usedTime = end - begin;
					logger.info(targetName + " use time : " + usedTime / 1000.0 + "s");
 
					/**
					 * 没有异常发生,打印返回信息
					 */
					if(!isException) {
						String responseMsg = "log - {0} response - {1}";
						logger.info(MessageFormat.format(responseMsg, new Object[] { targetName, response }));
					}
 
					/**
					 * 判断是否监控
					 */
					if(isMonitor) {
						/**
						 * 获取本地ip
						 */
						String localIP = StringUtils.EMPTY;
						try {
							InetAddress localHost = InetAddress.getLocalHost();
							localIP = localHost.getHostAddress();
						} catch (Exception e) {
							logger.error("获取本地ip异常发生", e);
						}
 
						/**
						 * 获取方法路径(包括参数类型)
						 */
						String methodRoute = TransMonitorUtils.getMethodRoute(targetName, pjp.getArgs());
 
						/**
						 * 组织map
						 */
						Map<String, Object> map = new HashMap<String, Object>();
						map.put("methodType", monitorMethodType == null ? StringUtils.EMPTY : monitorMethodType.getType());//方法类型
						map.put("outerSystem", outerSystem == null ? StringUtils.EMPTY : outerSystem.getSystem());//外部系统代码
						map.put("methodRoute", methodRoute);//方法路径
						map.put("methodName", methodName);//方法名称
						map.put("request", BaseUuidLogger.uuid.get() + request);//入参
						map.put("response", response);//出参
						map.put("isException", isException);//是否异常发生
						map.put("beginTime", begin);//开始时间
						map.put("endTime", end);//结束时间
						map.put("usedTime", usedTime);//耗时(毫秒)
						map.put("ip", localIP);//本地ip
 
						/**
						 * 从ThreadLocal中MAP获取resv1,2,3 
						 * 优先级高于
						 * 从注解中解析表达式获取对象
						 */
						String resv1InMap = TransMonitorUtils.getResv1(methodRoute);//从ThreadLocal中MAP获取备注字段1
						String resv2InMap = TransMonitorUtils.getResv2(methodRoute);//从ThreadLocal中MAP获取备注字段2
						String resv3InMap = TransMonitorUtils.getResv3(methodRoute);//从ThreadLocal中MAP获取备注字段3
						if(null != resv1InMap) {
							map.put("resv1", resv1InMap);
						} else {
							map.put("resv1", ExpressLanUtils.getObjectFromExpressexToString(resv1, pjp.getArgs(), result, isException));//从注解中解析表达式获取对象-备注字段1
						}
						if(null != resv2InMap) {
							map.put("resv2", resv2InMap);
						} else {
							map.put("resv2", ExpressLanUtils.getObjectFromExpressexToString(resv2, pjp.getArgs(), result, isException));//从注解中解析表达式获取对象-备注字段2
						}
						if(null != resv3InMap) {
							map.put("resv3", resv3InMap);
						} else {
							map.put("resv3", ExpressLanUtils.getObjectFromExpressexToString(resv3, pjp.getArgs(), result, isException));//从注解中解析表达式获取对象-备注字段3
						}
 
						/**
						 * 异步执行任务-提交任务
						 */
						AsynUtils.getInstance().submitTask(new Callable<Boolean>() {
							@Override
							public Boolean call() throws Exception {
								/**
								 * 推送la交易监控(为了异步执行)
								 */
								SpringUtils.getInstance().getBean(RabbitService.class).sendLaTransMonitor(map);
								return true;
							}
						});
					}
				}
			} catch (Exception e) {
				logger.error("切面处理异常发生!", e);
			}
		}
	}
}

BeAopUtil.java

BeAopUtil.java
package com.shhxzq.fin.lifeapp.biz.utils;
 
import java.math.BigDecimal;
import java.util.List;
import java.util.Set;
 
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
 
/**
 * Aop工具类
 * @author Gxx
 */
public class BeAopUtil {
 
	/**
	 * 根据入参获取字符串
	 * @param args
	 * @return
	 */
	public static String getStringFromRequest(Object[] args){
		String req = "";
		for(Object arg:args){
			if(arg == null){
				req = req + "null,";
				continue;
			}else if(arg instanceof List == true || arg instanceof Set == true){
				req = req + JsonTools.toJSONString(arg);
			}
			else if(arg.getClass().isArray()){
				req = req + JSONArray.fromObject(arg);
			}
			else if( arg instanceof Enum){
				req = req + JsonTools.toJSONString(arg)+",";
			}else if(!(arg instanceof String)
					&& !(arg instanceof BigDecimal)
					&& !(arg instanceof Boolean)
					&& !(arg instanceof Integer)
					&& (arg instanceof Object)){
				req = req+JSONObject.fromObject(arg).toString()+",";
			}else{
				req = req+arg.toString()+",";
			}
		}
		if(req.endsWith(",")) {
			req = req.substring(0, req.length() - 1);
		}
		return req;
	}
 
	/**
	 * 根据出参获取字符串
	 * @param arg
	 * @return
	 */
	public static String getStringFromResponse(Object arg){
		String rsp = "";
		if(arg == null){
			rsp = rsp + "null";
			return rsp;
		}else if(arg instanceof List || arg instanceof Set == true){
			rsp = rsp + JsonTools.toJSONString(arg);
			return rsp;
		}else if( arg instanceof Enum){
			rsp = rsp + JsonTools.toJSONString(arg);
			return rsp;
		}else if(!(arg instanceof String )
				&& !(arg instanceof BigDecimal)
				&& !(arg instanceof Boolean)
				&& !(arg instanceof Integer )
				&& (arg instanceof Object)){
			rsp = rsp+JSONObject.fromObject(arg).toString()+",";
		}else{
			rsp = rsp+arg.toString()+",";
		}
		if(rsp.endsWith(",")) {
			rsp = rsp.substring(0, rsp.length() - 1);
		}
		return rsp;
	}
}

TransMonitorUtils.java

TransMonitorUtils.java
package com.shhxzq.fin.lifeapp.biz.utils;
 
import java.util.HashMap;
import java.util.Map;
 
import org.apache.log4j.Logger;
 
/** 
 * 交易监控工具类
 * @author Gxx
 */
public class TransMonitorUtils {
	/**
	 * 日志记录器
	 */
	static Logger logger = BaseUuidLoggerUtils.getBaseUuidLogger();
 
	/**
	 * 通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值
	 * 使得同一个线程的resvMap是一样的,存放监控方法的备注字段
	 */
	private static ThreadLocal<Map<String, String>> resvMap = new ThreadLocal<Map<String, String>>() {
		/**
		 * 初始值
		 */
		public Map<String, String> initialValue() {
			return new HashMap<>();
		}
	};
 
	/**
	 * 往ThreadLocal中MAP设置备注字段1
	 * @param className 类名
	 * @param methodName 方法名
	 * @param args 参数
	 * @param string 备注字段1
	 */
	public synchronized static void setResv1(String className, String methodName, Object[] args, String string) {
		String methodRoute = getMethodRoute(className + "." + methodName, args);
		resvMap.get().put(methodRoute + ".resv1", string);
	}
 
	/**
	 * 往ThreadLocal中MAP设置备注字段2
	 * @param className 类名
	 * @param methodName 方法名
	 * @param args 参数
	 * @param string 备注字段2
	 */
	public synchronized static void setResv2(String className, String methodName, Object[] args, String string) {
		String methodRoute = getMethodRoute(className + "." + methodName, args);
		resvMap.get().put(methodRoute + ".resv2", string);
	}
 
	/**
	 * 往ThreadLocal中MAP设置备注字段3
	 * @param className 类名
	 * @param methodName 方法名
	 * @param args 参数
	 * @param string 备注字段3
	 */
	public synchronized static void setResv3(String className, String methodName, Object[] args, String string) {
		String methodRoute = getMethodRoute(className + "." + methodName, args);
		resvMap.get().put(methodRoute + ".resv3", string);
	}
 
	/**
	 * 从ThreadLocal中MAP获取备注字段1
	 * @param string
	 */
	public synchronized static String getResv1(String methodRoute) {
		return resvMap.get().get(methodRoute + ".resv1");
	}
 
	/**
	 * 从ThreadLocal中MAP获取备注字段2
	 * @param string
	 */
	public synchronized static String getResv2(String methodRoute) {
		return resvMap.get().get(methodRoute + ".resv2");
	}
 
	/**
	 * 从ThreadLocal中MAP获取备注字段3
	 * @param string
	 */
	public synchronized static String getResv3(String methodRoute) {
		return resvMap.get().get(methodRoute + ".resv3");
	}
 
	/**
	 * 获取方法路径(包括参数类型)
	 * @param targetName 类名+方法名
	 * @param args 参数数组
	 * @return
	 */
	public static String getMethodRoute(String targetName, Object[] args) {
		String methodRoute = targetName + "(";
		if(null != args) {
			for(int i=0;i<args.length;i++) {
				if(i > 0) {
					methodRoute += ", ";
				}
				Object object = args[i];
				String type = object.getClass().getTypeName();
				methodRoute += type;
			}
		}
		methodRoute += ")";
		return methodRoute;
	}
}

ExpressLanUtils.java

ExpressLanUtils.java
package com.shhxzq.fin.lifeapp.biz.utils;
 
import org.apache.commons.jexl3.JexlContext;
import org.apache.commons.jexl3.JexlEngine;
import org.apache.commons.jexl3.JexlExpression;
import org.apache.commons.jexl3.MapContext;
import org.apache.commons.jexl3.internal.Engine;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
 
/** 
 * 表达式语言工具类
 * 依赖commons-jexl3包
 * @author Gxx
 */
public class ExpressLanUtils {
	/**
	 * 日志记录器
	 */
	static Logger logger = BaseUuidLoggerUtils.getBaseUuidLogger();
	/**
	 * 请求参数前缀标示
	 */
	public static final String REQUEST_PREFIX = "{request";
	/**
	 * 请求参数后缀标示
	 */
	public static final String REQUEST_SUFFIX = "}";
	/**
	 * 请求参数前缀标示
	 */
	public static final String RESPONSE_PREFIX = "{response";
	/**
	 * 请求参数后缀标示
	 */
	public static final String RESPONSE_SUFFIX = "}";
	/**
	 * 分隔符
	 */
	public static final String SPLIT_STRING = "\\{\\|\\}";
 
	/**
	 * 判断是否是表达式
	 * @param string
	 * @return
	 */
	public static boolean isExpress(String string) {
		return isRequestExpress(string) || isResponseExpress(string);
	}
 
	/**
	 * 判断是否是[获取请求]表达式
	 * @param string
	 * @return
	 */
	public static boolean isRequestExpress(String string) {
		/**
		 * 判断非空
		 */
		if(StringUtils.isNotBlank(string)) {
			string = StringUtils.trim(string);
			if(string.startsWith(REQUEST_PREFIX) && string.endsWith(REQUEST_SUFFIX)) {
				return true;
			}
		}
		return false;
	}
 
	/**
	 * 判断是否是[获取返回]表达式
	 * @param string
	 * @return
	 */
	public static boolean isResponseExpress(String string) {
		/**
		 * 判断非空
		 */
		if(StringUtils.isNotBlank(string)) {
			string = StringUtils.trim(string);
			if(string.startsWith(RESPONSE_PREFIX) && string.endsWith(RESPONSE_SUFFIX)) {
				return true;
			}
		}
		return false;
	}
 
	/**
	 * 从表达式(按分隔符拆分后)获取对象
	 * 1.非表达式,原样返回
	 * 2.[获取请求]表达式,解析表达式,返回[请求]中的值
	 * 3.[获取返回]表达式,
	 * 3.1.没有异常发生,解析表达式,返回[返回]中的值
	 * 3.2.有异常发生,返回null
	 * @param express 表达式:[获取请求]表达式/[获取返回]表达式
	 * @param request 请求参数数组
	 * @param response 返回参数
	 * @param isException 是否发生异常
	 * @return
	 */
	public static Object getObjectFromExpress(String express, Object[] request, Object response, boolean isException) {
		try {
			/**
			 * 1.非表达式,原样返回
			 */
			boolean isRequestExpress = isRequestExpress(express);
			boolean isResponseExpress = isResponseExpress(express);
			if(!isRequestExpress && !isResponseExpress) {
				return express;
			}
			/**
			 * 2.[获取请求]表达式,解析表达式,返回[请求]中的值
			 * 比如:
			 * {request} : 取第一个request参数
			 * {request[0]} : 取第一个request参数
			 * {request[1]} : 取第二个request参数
			 * {request.custNo} : 取第一个request参数的属性
			 * {request.createdAt.time} : 取第一个request参数的属性的属性
			 * {request[0].custNo} : 取第一个request参数的属性
			 * {request[0].createdAt.time} : 取第一个request参数的属性的属性
			 * {request[1].createdAt.time} : 取第二个request参数的属性的属性
			 */
			if(isRequestExpress) {
				/**
				 * 2.0.判空
				 */
				if(null == request || request.length == 0) {
					return null;
				}
				/**
				 * 2.1.去掉开头:{request
				 */
				express = express.substring(REQUEST_PREFIX.length());
				/**
				 * 2.2.去掉结尾:}
				 */
				express = express.substring(0, express.length() - 1);
				/**
				 * 2.3.判空 {request}
				 */
				if(StringUtils.isBlank(express)) {
					return request[0];
				}
				/**
				 * 2.4.判断.开头
				 */
				Object object = null;
				if(express.startsWith(".")) {
					express = express.substring(1);
					object = request[0];
					return getObjectFromExpress(express, object);
				}
				/**
				 * 2.4.判断[开头
				 */
				if(express.startsWith("[")) {
					express = express.substring(1);
					int index = express.indexOf("]");
					int indexValue = Integer.parseInt(express.substring(0, index));
					object = request[indexValue];
					express = express.substring(index + 1);
					/**
					 * 2.4.1.判断request[*]
					 */
					if(StringUtils.isBlank(express)) {
						return object;
					}
					/**
					 * 2.4.2.判断request[*].custNo
					 */
					if(express.startsWith(".")) {
						express = express.substring(1);
						return getObjectFromExpress(express, object);
					}
				}
 
			}
			/**
			 * 3.[获取返回]表达式,解析表达式,返回[返回]中的值
			 * 比如:
			 * {response} : 取第一个request参数
			 * {response.custNo} : 取第一个request参数的属性
			 * {response.createdAt.time} : 取第一个request参数的属性的属性
			 */
			if(isResponseExpress) {
				/**
				 * 3.0.判空
				 */
				if(null == response) {
					return null;
				}
				/**
				 * 3.1.去掉开头:{response
				 */
				express = express.substring(RESPONSE_PREFIX.length());
				/**
				 * 3.2.去掉结尾:}
				 */
				express = express.substring(0, express.length() - 1);
				/**
				 * 3.3.判空 {response}
				 */
				if(StringUtils.isBlank(express)) {
					return response;
				}
				/**
				 * 3.4.判断.开头
				 */
				if(express.startsWith(".")) {
					express = express.substring(1);
					return getObjectFromExpress(express, response);
				}
			}
			return null;
		} catch (Exception e) {
			logger.error("从表达式获取对象异常发生", e);
			return null;
		}
	}
 
	/**
	 * 从表达式(jexl)获取对象
	 * @param express
	 * @param object
	 * @return
	 */
	public static Object getObjectFromExpress(String express, Object object) {
		try {
			/**
			 * 判空
			 */
			if(null == object) {
				return null;
			}
			JexlEngine JEXL = new Engine();
			JexlExpression e = JEXL.createExpression("object." + express);
	        JexlContext jc = new MapContext();
	        jc.set("object", object);
	        return e.evaluate(jc);
		} catch (Exception e) {
			logger.error("从表达式获取对象异常发生", e);
			return null;
		}
	}
 
	/**
	 * 从表达式(按分隔符拆分后)获取对象并转成string
	 * @param express
	 * @param request
	 * @param response
	 * @param isException
	 * @return
	 */
	public static String getObjectFromExpressToString(String express, Object[] request, Object response, boolean isException) {
		/**
		 * 从表达式获取对象
		 */
		Object result = getObjectFromExpress(express, request, response, isException);
		if(null == result) {
			return null;
		} else {
			return result.toString();
		}
	}
 
	/**
	 * 从表达式(按分隔符拆分前)获取对象并转成string
	 * @param express
	 * @param request
	 * @param response
	 * @param isException
	 * @return
	 */
	public static Object getObjectFromExpressexToString(String express, Object[] request, Object response, boolean isException) {
		try {
			/**
			 * 1.非表达式,原样返回
			 * NORMAL_STRING
			 * NORMAL_STRING{|}{response.*}{|}{request[*].*}
			 * {request.*}
			 * {request[*].*}
			 * {response.*}
			 * {request.*}{|}{request[*].*}
			 * {request[*].*}{|}{response.*}
			 * {response.*}{|}{response.*}{|}{request[*].*}
			 */
			if(StringUtils.isBlank(express)) {
				return express;
			}
			String result = StringUtils.EMPTY;
			String[] expressArray = express.split(SPLIT_STRING);
			for(int i=0;i<expressArray.length;i++) {
				if(i > 0) {
					result += "|";
				}
				/**
				 * 从表达式获取对象
				 */
				Object temp = getObjectFromExpressToString(expressArray[i], request, response, isException);
				/**
				 * 空则略过
				 */
				if(null != temp) {
					result += temp.toString();
				}
			}
			return result;
		} catch (Exception e) {
			logger.error("从表达式(按分隔符拆分前)获取对象并转成string异常发生!", e);
			return express;
		}
	}
}

AsynUtils.java

AsynUtils.java
package com.shhxzq.fin.lifeapp.biz.utils;
 
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
 
/**
 * 异步执行任务工具类
 * @author Gxx
 * @param <T>
 */
public final class AsynUtils {
	/**
	 * 单例模式
	 */
    private static AsynUtils instance = new AsynUtils();
 
    /**
	 * 进行异步任务列表
	 */
    private List<FutureTask> futureTasks = new ArrayList<FutureTask>();
 
	/**
	 * 线程池 暂时约定初始化5个线程 和JDBC连接池是一个意思 实现重用
	 */
    private ExecutorService executorService = Executors.newFixedThreadPool(5);
 
    public static AsynUtils getInstance() {
    	return instance;
    }
 
    /**
     * 异步执行任务-提交任务
     */
    public void submitTask(Callable callable) {
    	/**
		 * 创建一个异步任务
		 */
		FutureTask futureTask = new FutureTask(callable);
		futureTasks.add(futureTask);
		/**
		 * 提交异步任务到线程池,让线程池管理任务
		 * 由于是异步并行任务,所以这里并不会阻塞
		 * 注意:一旦提交,线程池如果有可用线程,马上分配执行!
		 */
		executorService.submit(futureTask);
    }
}

RabbitService.java

RabbitService.java
package com.shhxzq.fin.lifeapp.biz.service;
 
import java.util.Map;
 
/**
 * rabbit服务接口
 * @author Gxx
 */
public interface RabbitService {
	/**
	 * 推送la交易监控(为了异步执行)
	 * @param wechatMap
	 */
	public void sendLaTransMonitor(Map<String, Object> map);
}

RabbitServiceImpl.java

RabbitServiceImpl.java
package com.shhxzq.fin.lifeapp.biz.impl;
 
import java.util.Map;
 
import com.shhxzq.fin.lifeapp.biz.utils.HawkeyeUtil;
import com.shhxzq.fin.lifeapp.model.base.LaMonitorType;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.shhxzq.fin.lifeapp.biz.service.RabbitService;
 
/**
 * rabbit服务实现类
 * @author Gxx
 */
@Service("rabbitService")
public class RabbitServiceImpl implements RabbitService {
 
	/**
	 * 日志记录器
	 */
	Logger logger = Logger.getLogger(RabbitServiceImpl.class);
 
	/**
	 * mq执行器
	 */
	@Autowired
	private AmqpTemplate amqpTemplate;
 
	/**
	 * 推送la交易监控(为了异步执行)
	 * @param wechatMap
	 */
	public void sendLaTransMonitor(Map<String, Object> map) {
		String jsonString = StringUtils.EMPTY;
		try {
			/**
			 * 默认值为null不会转json,这里强制转
			 * {"a":1,"b":"","c":null,"d":"wuzhuti.cn"}
			 */
			jsonString  = JSON.toJSONString(map, SerializerFeature.WriteMapNullValue);
			logger.info("推送la交易监控(为了异步执行),开始!");
			amqpTemplate.convertAndSend("la_queue_la_trans_monitor_key", jsonString);
			logger.info("推送la交易监控(为了异步执行),结束!");
		} catch (Exception e) {
			/**
			 * mq异常捕获,不往外抛
			 */
			logger.error("推送la交易监控(为了异步执行)[json:" + jsonString + "]!", e);
            /**
             * 报警
             */
			HawkeyeUtil.logEvent(LaMonitorType.RABBIT_MQ.getType(), LaMonitorType.RABBIT_MQ_EXCEPTION.getType(), e.getMessage());
		}
	}
}

application-mq-rabbit.xml

application-mq-rabbit.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:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task"
	xmlns:rabbit="http://www.springframework.org/schema/rabbit"
	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.xsd
      http://www.springframework.org/schema/integration/ip
      http://www.springframework.org/schema/integration/ip/spring-integration-ip-2.0.xsd
      http://www.springframework.org/schema/integration
      http://www.springframework.org/schema/integration/spring-integration.xsd
      http://www.springframework.org/schema/task
      http://www.springframework.org/schema/task/spring-task-3.0.xsd
      http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
      http://www.springframework.org/schema/rabbit
      http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd">
 
	<!-- mq连接服务配置 -->
	<rabbit:connection-factory id="connectionFactory"
		host="${la.rabbit.host}" username="${la.rabbit.username}" password="${la.rabbit.password}"
		port="${la.rabbit.port}" />
 
	<rabbit:admin connection-factory="connectionFactory" />
 
	<rabbit:template id="amqpTemplate" connection-factory="connectionFactory"
		exchange="payment_exchange" />
 
	<!-- 推送la交易监控(为了异步执行) -->
	<rabbit:queue id="la_queue_la_trans_monitor"
		durable="true" auto-delete="false" exclusive="false"
		name="la_queue_la_trans_monitor" />
 
	<rabbit:direct-exchange name="payment_exchange"
		durable="true" auto-delete="false" id="payment_exchange">
 
		<rabbit:bindings>
			<!-- 通知la消息 -->
			<rabbit:binding queue="la_queue_la_trans_monitor"
				key="la_queue_la_trans_monitor_key" />
		</rabbit:bindings>
 
	</rabbit:direct-exchange>
 
	<!-- queue litener 观察 监听模式 当有消息到达时会通知监听在对应的队列上的监听对象 task-executor="taskExecutor" -->
	<rabbit:listener-container
		connection-factory="connectionFactory" acknowledge="auto">
 
		<!-- 接收la消息 -->
		<rabbit:listener queues="la_queue_la_trans_monitor" ref="laTransMonitorListener" />
 
	</rabbit:listener-container>
</beans>

LaTransMonitorListener.java

LaTransMonitorListener.java
package com.shhxzq.fin.lifeapp.biz.impl.mq;
 
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import com.shhxzq.fin.lifeapp.biz.utils.DateUtils;
import com.shhxzq.fin.lifeapp.dao.credit.LaTransMonitorMapper;
import com.shhxzq.fin.lifeapp.model.base.BaseUuidLogger;
import com.shhxzq.fin.lifeapp.model.constants.CreditConstants;
import com.shhxzq.fin.lifeapp.model.credit.vo.LaTransMonitorWithBLOBs;
 
import net.sf.json.JSONObject;
 
/**
 * 接受la交易监控推送(异步执行)
 * @author Gxx
 */
@Service(value = "laTransMonitorListener")
public class LaTransMonitorListener implements MessageListener {
 
	/**
	 * 日志处理器
	 */
	private Logger logger = Logger.getLogger(LaTransMonitorListener.class);
 
	@Autowired
	private LaTransMonitorMapper laTransMonitorMapper;
 
	@Override
	public void onMessage(Message message) {
		try {
			/**
			 * 刷新uuid
			 */
			((BaseUuidLogger)logger).refreshUuid();
			logger.info("接受la交易监控推送(异步执行)对象:" + message);
			/**
			 * 接受消息
			 */
			String receiveMsg;
			try {
				receiveMsg = new String(message.getBody(), message.getMessageProperties().getContentEncoding());
			} catch (Exception e) {
				logger.error("接受la交易监控推送(异步执行),字符转换失败", e);
				return;
			}
			/**
			 * 判断消息为空
			 */
			if (StringUtils.isBlank(receiveMsg)) {
				logger.error("接受la交易监控推送(异步执行)收到消息为空");
				return;
			} else {
				/**
				 * 获取数据
				 */
				JSONObject jsonObject = JSONObject.fromObject(receiveMsg);
				String methodType = jsonObject.getString("methodType");//方法类型
				String outerSystem = jsonObject.getString("outerSystem");//外部系统代码
				String methodRoute = jsonObject.getString("methodRoute");//方法路径
				String methodName = jsonObject.getString("methodName");//方法名称
				String request = jsonObject.getString("request");//入参
				String response = jsonObject.getString("response");//出参
				Boolean isException = jsonObject.getBoolean("isException");//是否异常发生
				Long beginTime = jsonObject.getLong("beginTime");//开始时间
				Long endTime = jsonObject.getLong("endTime");//结束时间
				Long usedTime = jsonObject.getLong("usedTime");//耗时(毫秒)
				String ip = jsonObject.getString("ip");//本地ip
				String resv1 = jsonObject.getString("resv1");//备注字段1
				String resv2 = jsonObject.getString("resv2");//备注字段2
				String resv3 = jsonObject.getString("resv3");//备注字段3
 
				/**
				 * 字符串长度处理
				 */
				request = (null != request && request.length() > 1000 ? request.substring(0, 1000) + "..." : request);
				response = (null != response && response.length() > 1000 ? response.substring(0, 1000) + "..." : response);
				resv1 = (null != resv1 && resv1.length() > 100 ? resv1.substring(0, 100) : resv1);
				resv2 = (null != resv2 && resv2.length() > 100 ? resv2.substring(0, 100) : resv2);
				resv3 = (null != resv3 && resv3.length() > 100 ? resv3.substring(0, 100) : resv3);
 
				/**
				 * 交易监控落库
				 */
				LaTransMonitorWithBLOBs laTransMonitorWithBLOBs = new LaTransMonitorWithBLOBs();
				laTransMonitorWithBLOBs.setSysDate(DateUtils.getCurrentDate());
				laTransMonitorWithBLOBs.setSysTime(DateUtils.getCurrentTime());
				laTransMonitorWithBLOBs.setMethodType(methodType);
				laTransMonitorWithBLOBs.setOuterSystem(outerSystem);
				laTransMonitorWithBLOBs.setMethodRoute(methodRoute);
				laTransMonitorWithBLOBs.setMethodName(methodName);
				laTransMonitorWithBLOBs.setRequest(request);
				laTransMonitorWithBLOBs.setResponse(response);
				laTransMonitorWithBLOBs.setIsException(isException ? CreditConstants.IS_EXCEPTION_YES : CreditConstants.IS_EXCEPTION_NO);
				laTransMonitorWithBLOBs.setBeginTime(DateUtils.getDate(beginTime));
				laTransMonitorWithBLOBs.setEndTime(DateUtils.getDate(endTime));
				laTransMonitorWithBLOBs.setUsedTime(usedTime);
				laTransMonitorWithBLOBs.setIp(ip);
				laTransMonitorWithBLOBs.setResv1(resv1);
				laTransMonitorWithBLOBs.setResv2(resv2);
				laTransMonitorWithBLOBs.setResv3(resv3);
				laTransMonitorWithBLOBs.setIsDelete(CreditConstants.IS_DELETE_NO);
				laTransMonitorWithBLOBs.setCreatedAt(DateUtils.getNow());
				laTransMonitorWithBLOBs.setUpdatedAt(DateUtils.getNow());
				laTransMonitorMapper.insert(laTransMonitorWithBLOBs);
				logger.info("交易监控落库完成!");
			}
		} catch (Exception e) {
			logger.error("交易监控接受落库异常发生!", e);
		}
	}
 
}

LaTransMonitorMapper.java

LaTransMonitorMapper.java
package com.shhxzq.fin.lifeapp.dao.credit;
 
import org.springframework.stereotype.Repository;
 
import com.shhxzq.fin.lifeapp.model.credit.vo.LaTransMonitor;
import com.shhxzq.fin.lifeapp.model.credit.vo.LaTransMonitorWithBLOBs;
 
@Repository
public interface LaTransMonitorMapper {
    int deleteByPrimaryKey(Integer id);
 
    int insert(LaTransMonitorWithBLOBs record);
 
    int insertSelective(LaTransMonitorWithBLOBs record);
 
    LaTransMonitorWithBLOBs selectByPrimaryKey(Integer id);
 
    int updateByPrimaryKeySelective(LaTransMonitorWithBLOBs record);
 
    int updateByPrimaryKeyWithBLOBs(LaTransMonitorWithBLOBs record);
 
    int updateByPrimaryKey(LaTransMonitor record);
}

LaTransMonitorWithBLOBs.java

LaTransMonitorWithBLOBs.java
package com.shhxzq.fin.lifeapp.model.credit.vo;
 
public class LaTransMonitorWithBLOBs extends LaTransMonitor {
    private String request;
 
    private String response;
 
    public String getRequest() {
        return request;
    }
 
    public void setRequest(String request) {
        this.request = request == null ? null : request.trim();
    }
 
    public String getResponse() {
        return response;
    }
 
    public void setResponse(String response) {
        this.response = response == null ? null : response.trim();
    }
 
	@Override
	public String toString() {
		return "LaTransMonitorWithBLOBs [request=" + request + ", response=" + response + "] LaTransMonitor [" + super.toString() + "]";
	}
}

LaTransMonitor.java

LaTransMonitor.java
package com.shhxzq.fin.lifeapp.model.credit.vo;
 
import java.util.Date;
 
public class LaTransMonitor {
    private Integer id;
 
    private String sysDate;
 
    private String sysTime;
 
    private String methodType;
 
    private String outerSystem;
 
    private String methodRoute;
 
    private String methodName;
 
    private Integer isException;
 
    private Date beginTime;
 
    private Date endTime;
 
    private Long usedTime;
 
    private String ip;
 
    private String resv1;
 
    private String resv2;
 
    private String resv3;
 
    private Integer isDelete;
 
    private Date createdAt;
 
    private Date updatedAt;
 
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    public String getSysDate() {
        return sysDate;
    }
 
    public void setSysDate(String sysDate) {
        this.sysDate = sysDate == null ? null : sysDate.trim();
    }
 
    public String getSysTime() {
        return sysTime;
    }
 
    public void setSysTime(String sysTime) {
        this.sysTime = sysTime == null ? null : sysTime.trim();
    }
 
    public String getMethodType() {
        return methodType;
    }
 
    public void setMethodType(String methodType) {
        this.methodType = methodType == null ? null : methodType.trim();
    }
 
    public String getOuterSystem() {
        return outerSystem;
    }
 
    public void setOuterSystem(String outerSystem) {
        this.outerSystem = outerSystem == null ? null : outerSystem.trim();
    }
 
    public String getMethodRoute() {
        return methodRoute;
    }
 
    public void setMethodRoute(String methodRoute) {
        this.methodRoute = methodRoute == null ? null : methodRoute.trim();
    }
 
    public String getMethodName() {
        return methodName;
    }
 
    public void setMethodName(String methodName) {
        this.methodName = methodName == null ? null : methodName.trim();
    }
 
    public Integer getIsException() {
        return isException;
    }
 
    public void setIsException(Integer isException) {
        this.isException = isException;
    }
 
    public Date getBeginTime() {
        return beginTime;
    }
 
    public void setBeginTime(Date beginTime) {
        this.beginTime = beginTime;
    }
 
    public Date getEndTime() {
        return endTime;
    }
 
    public void setEndTime(Date endTime) {
        this.endTime = endTime;
    }
 
    public Long getUsedTime() {
        return usedTime;
    }
 
    public void setUsedTime(Long usedTime) {
        this.usedTime = usedTime;
    }
 
    public String getIp() {
        return ip;
    }
 
    public void setIp(String ip) {
        this.ip = ip == null ? null : ip.trim();
    }
 
    public String getResv1() {
        return resv1;
    }
 
    public void setResv1(String resv1) {
        this.resv1 = resv1 == null ? null : resv1.trim();
    }
 
    public String getResv2() {
        return resv2;
    }
 
    public void setResv2(String resv2) {
        this.resv2 = resv2 == null ? null : resv2.trim();
    }
 
    public String getResv3() {
        return resv3;
    }
 
    public void setResv3(String resv3) {
        this.resv3 = resv3 == null ? null : resv3.trim();
    }
 
    public Integer getIsDelete() {
        return isDelete;
    }
 
    public void setIsDelete(Integer isDelete) {
        this.isDelete = isDelete;
    }
 
    public Date getCreatedAt() {
        return createdAt;
    }
 
    public void setCreatedAt(Date createdAt) {
        this.createdAt = createdAt;
    }
 
    public Date getUpdatedAt() {
        return updatedAt;
    }
 
    public void setUpdatedAt(Date updatedAt) {
        this.updatedAt = updatedAt;
    }
}

LaTransMonitorMapper.xml

LaTransMonitorMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.shhxzq.fin.lifeapp.dao.credit.LaTransMonitorMapper" >
  <resultMap id="BaseResultMap" type="com.shhxzq.fin.lifeapp.model.credit.vo.LaTransMonitor" >
    <id column="id" property="id" jdbcType="INTEGER" />
    <result column="sys_date" property="sysDate" jdbcType="CHAR" />
    <result column="sys_time" property="sysTime" jdbcType="CHAR" />
    <result column="method_type" property="methodType" jdbcType="VARCHAR" />
    <result column="outer_system" property="outerSystem" jdbcType="VARCHAR" />
    <result column="method_route" property="methodRoute" jdbcType="VARCHAR" />
    <result column="method_name" property="methodName" jdbcType="VARCHAR" />
    <result column="is_exception" property="isException" jdbcType="INTEGER" />
    <result column="begin_time" property="beginTime" jdbcType="TIMESTAMP" />
    <result column="end_time" property="endTime" jdbcType="TIMESTAMP" />
    <result column="used_time" property="usedTime" jdbcType="BIGINT" />
    <result column="ip" property="ip" jdbcType="VARCHAR" />
    <result column="resv1" property="resv1" jdbcType="VARCHAR" />
    <result column="resv2" property="resv2" jdbcType="VARCHAR" />
    <result column="resv3" property="resv3" jdbcType="VARCHAR" />
    <result column="is_delete" property="isDelete" jdbcType="INTEGER" />
    <result column="created_at" property="createdAt" jdbcType="TIMESTAMP" />
    <result column="updated_at" property="updatedAt" jdbcType="TIMESTAMP" />
  </resultMap>
  <resultMap id="ResultMapWithBLOBs" type="com.shhxzq.fin.lifeapp.model.credit.vo.LaTransMonitorWithBLOBs" extends="BaseResultMap" >
    <result column="request" property="request" jdbcType="LONGVARCHAR" />
    <result column="response" property="response" jdbcType="LONGVARCHAR" />
  </resultMap>
  <sql id="Base_Column_List" >
    id, sys_date, sys_time, method_type, outer_system, method_route, method_name, is_exception, 
    begin_time, end_time, used_time, ip, resv1, resv2, resv3, is_delete, created_at, 
    updated_at
  </sql>
  <sql id="Blob_Column_List" >
    request, response
  </sql>
  <select id="selectByPrimaryKey" resultMap="ResultMapWithBLOBs" parameterType="java.lang.Integer" >
    select 
    <include refid="Base_Column_List" />
    ,
    <include refid="Blob_Column_List" />
    from la_trans_monitor
    where id = #{id,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
    delete from la_trans_monitor
    where id = #{id,jdbcType=INTEGER}
  </delete>
  <insert id="insert" parameterType="com.shhxzq.fin.lifeapp.model.credit.vo.LaTransMonitorWithBLOBs" >
    insert into la_trans_monitor (id, sys_date, sys_time, 
      method_type, outer_system, method_route, 
      method_name, is_exception, begin_time, 
      end_time, used_time, ip, 
      resv1, resv2, resv3, 
      is_delete, created_at, updated_at, 
      request, response)
    values (#{id,jdbcType=INTEGER}, #{sysDate,jdbcType=CHAR}, #{sysTime,jdbcType=CHAR}, 
      #{methodType,jdbcType=VARCHAR}, #{outerSystem,jdbcType=VARCHAR}, #{methodRoute,jdbcType=VARCHAR}, 
      #{methodName,jdbcType=VARCHAR}, #{isException,jdbcType=INTEGER}, #{beginTime,jdbcType=TIMESTAMP}, 
      #{endTime,jdbcType=TIMESTAMP}, #{usedTime,jdbcType=BIGINT}, #{ip,jdbcType=VARCHAR}, 
      #{resv1,jdbcType=VARCHAR}, #{resv2,jdbcType=VARCHAR}, #{resv3,jdbcType=VARCHAR}, 
      #{isDelete,jdbcType=INTEGER}, #{createdAt,jdbcType=TIMESTAMP}, #{updatedAt,jdbcType=TIMESTAMP}, 
      #{request,jdbcType=LONGVARCHAR}, #{response,jdbcType=LONGVARCHAR})
  </insert>
  <insert id="insertSelective" parameterType="com.shhxzq.fin.lifeapp.model.credit.vo.LaTransMonitorWithBLOBs" >
    insert into la_trans_monitor
    <trim prefix="(" suffix=")" suffixOverrides="," >
      <if test="id != null" >
        id,
      </if>
      <if test="sysDate != null" >
        sys_date,
      </if>
      <if test="sysTime != null" >
        sys_time,
      </if>
      <if test="methodType != null" >
        method_type,
      </if>
      <if test="outerSystem != null" >
        outer_system,
      </if>
      <if test="methodRoute != null" >
        method_route,
      </if>
      <if test="methodName != null" >
        method_name,
      </if>
      <if test="isException != null" >
        is_exception,
      </if>
      <if test="beginTime != null" >
        begin_time,
      </if>
      <if test="endTime != null" >
        end_time,
      </if>
      <if test="usedTime != null" >
        used_time,
      </if>
      <if test="ip != null" >
        ip,
      </if>
      <if test="resv1 != null" >
        resv1,
      </if>
      <if test="resv2 != null" >
        resv2,
      </if>
      <if test="resv3 != null" >
        resv3,
      </if>
      <if test="isDelete != null" >
        is_delete,
      </if>
      <if test="createdAt != null" >
        created_at,
      </if>
      <if test="updatedAt != null" >
        updated_at,
      </if>
      <if test="request != null" >
        request,
      </if>
      <if test="response != null" >
        response,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides="," >
      <if test="id != null" >
        #{id,jdbcType=INTEGER},
      </if>
      <if test="sysDate != null" >
        #{sysDate,jdbcType=CHAR},
      </if>
      <if test="sysTime != null" >
        #{sysTime,jdbcType=CHAR},
      </if>
      <if test="methodType != null" >
        #{methodType,jdbcType=VARCHAR},
      </if>
      <if test="outerSystem != null" >
        #{outerSystem,jdbcType=VARCHAR},
      </if>
      <if test="methodRoute != null" >
        #{methodRoute,jdbcType=VARCHAR},
      </if>
      <if test="methodName != null" >
        #{methodName,jdbcType=VARCHAR},
      </if>
      <if test="isException != null" >
        #{isException,jdbcType=INTEGER},
      </if>
      <if test="beginTime != null" >
        #{beginTime,jdbcType=TIMESTAMP},
      </if>
      <if test="endTime != null" >
        #{endTime,jdbcType=TIMESTAMP},
      </if>
      <if test="usedTime != null" >
        #{usedTime,jdbcType=BIGINT},
      </if>
      <if test="ip != null" >
        #{ip,jdbcType=VARCHAR},
      </if>
      <if test="resv1 != null" >
        #{resv1,jdbcType=VARCHAR},
      </if>
      <if test="resv2 != null" >
        #{resv2,jdbcType=VARCHAR},
      </if>
      <if test="resv3 != null" >
        #{resv3,jdbcType=VARCHAR},
      </if>
      <if test="isDelete != null" >
        #{isDelete,jdbcType=INTEGER},
      </if>
      <if test="createdAt != null" >
        #{createdAt,jdbcType=TIMESTAMP},
      </if>
      <if test="updatedAt != null" >
        #{updatedAt,jdbcType=TIMESTAMP},
      </if>
      <if test="request != null" >
        #{request,jdbcType=LONGVARCHAR},
      </if>
      <if test="response != null" >
        #{response,jdbcType=LONGVARCHAR},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.shhxzq.fin.lifeapp.model.credit.vo.LaTransMonitorWithBLOBs" >
    update la_trans_monitor
    <set >
      <if test="sysDate != null" >
        sys_date = #{sysDate,jdbcType=CHAR},
      </if>
      <if test="sysTime != null" >
        sys_time = #{sysTime,jdbcType=CHAR},
      </if>
      <if test="methodType != null" >
        method_type = #{methodType,jdbcType=VARCHAR},
      </if>
      <if test="outerSystem != null" >
        outer_system = #{outerSystem,jdbcType=VARCHAR},
      </if>
      <if test="methodRoute != null" >
        method_route = #{methodRoute,jdbcType=VARCHAR},
      </if>
      <if test="methodName != null" >
        method_name = #{methodName,jdbcType=VARCHAR},
      </if>
      <if test="isException != null" >
        is_exception = #{isException,jdbcType=INTEGER},
      </if>
      <if test="beginTime != null" >
        begin_time = #{beginTime,jdbcType=TIMESTAMP},
      </if>
      <if test="endTime != null" >
        end_time = #{endTime,jdbcType=TIMESTAMP},
      </if>
      <if test="usedTime != null" >
        used_time = #{usedTime,jdbcType=BIGINT},
      </if>
      <if test="ip != null" >
        ip = #{ip,jdbcType=VARCHAR},
      </if>
      <if test="resv1 != null" >
        resv1 = #{resv1,jdbcType=VARCHAR},
      </if>
      <if test="resv2 != null" >
        resv2 = #{resv2,jdbcType=VARCHAR},
      </if>
      <if test="resv3 != null" >
        resv3 = #{resv3,jdbcType=VARCHAR},
      </if>
      <if test="isDelete != null" >
        is_delete = #{isDelete,jdbcType=INTEGER},
      </if>
      <if test="createdAt != null" >
        created_at = #{createdAt,jdbcType=TIMESTAMP},
      </if>
      <if test="updatedAt != null" >
        updated_at = #{updatedAt,jdbcType=TIMESTAMP},
      </if>
      <if test="request != null" >
        request = #{request,jdbcType=LONGVARCHAR},
      </if>
      <if test="response != null" >
        response = #{response,jdbcType=LONGVARCHAR},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKeyWithBLOBs" parameterType="com.shhxzq.fin.lifeapp.model.credit.vo.LaTransMonitorWithBLOBs" >
    update la_trans_monitor
    set sys_date = #{sysDate,jdbcType=CHAR},
      sys_time = #{sysTime,jdbcType=CHAR},
      method_type = #{methodType,jdbcType=VARCHAR},
      outer_system = #{outerSystem,jdbcType=VARCHAR},
      method_route = #{methodRoute,jdbcType=VARCHAR},
      method_name = #{methodName,jdbcType=VARCHAR},
      is_exception = #{isException,jdbcType=INTEGER},
      begin_time = #{beginTime,jdbcType=TIMESTAMP},
      end_time = #{endTime,jdbcType=TIMESTAMP},
      used_time = #{usedTime,jdbcType=BIGINT},
      ip = #{ip,jdbcType=VARCHAR},
      resv1 = #{resv1,jdbcType=VARCHAR},
      resv2 = #{resv2,jdbcType=VARCHAR},
      resv3 = #{resv3,jdbcType=VARCHAR},
      is_delete = #{isDelete,jdbcType=INTEGER},
      created_at = #{createdAt,jdbcType=TIMESTAMP},
      updated_at = #{updatedAt,jdbcType=TIMESTAMP},
      request = #{request,jdbcType=LONGVARCHAR},
      response = #{response,jdbcType=LONGVARCHAR}
    where id = #{id,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.shhxzq.fin.lifeapp.model.credit.vo.LaTransMonitor" >
    update la_trans_monitor
    set sys_date = #{sysDate,jdbcType=CHAR},
      sys_time = #{sysTime,jdbcType=CHAR},
      method_type = #{methodType,jdbcType=VARCHAR},
      outer_system = #{outerSystem,jdbcType=VARCHAR},
      method_route = #{methodRoute,jdbcType=VARCHAR},
      method_name = #{methodName,jdbcType=VARCHAR},
      is_exception = #{isException,jdbcType=INTEGER},
      begin_time = #{beginTime,jdbcType=TIMESTAMP},
      end_time = #{endTime,jdbcType=TIMESTAMP},
      used_time = #{usedTime,jdbcType=BIGINT},
      ip = #{ip,jdbcType=VARCHAR},
      resv1 = #{resv1,jdbcType=VARCHAR},
      resv2 = #{resv2,jdbcType=VARCHAR},
      resv3 = #{resv3,jdbcType=VARCHAR},
      is_delete = #{isDelete,jdbcType=INTEGER},
      created_at = #{createdAt,jdbcType=TIMESTAMP},
      updated_at = #{updatedAt,jdbcType=TIMESTAMP}
    where id = #{id,jdbcType=INTEGER}
  </update>
</mapper>

注意点

mysql包依赖5.1.34,如果版本太低,数据库时间相关字段timestamp(3)有可能会漏掉毫秒值,比如:2017-07-02 09:46:21.317,存到数据库中变成2017-07-02 09:46:21.000。

pom.xml
<!-- mysql -->
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>5.1.34</version>
</dependency>
分享/技术/交易监控/交易监控中间件_实现.1499007976.txt.gz · 最后更改: 2017/07/02 23:06 由 gxx