暂时还没有搞成真正的中间件,只是把相关代码写在这里,想要集成的朋友可以copy到项目中。
之后有时间,考虑下做成真正的中间件,以jar/pom的方式方便感兴趣的朋友集成!
############################ #交易监控需求 ############################ 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='交易监控表';
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; }
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; } }
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; } }
<!-- 服务层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 -->
/** * 信用卡服务接口实现类 * * @author Gxx */ @Service("laCreditService") public class LaCreditServiceImpl implements LaCreditService { /** * 查询是否显示信用卡管理菜单 * * @param request * @return */ @LogMethodTime(isMonitor = true, monitorMethodType = MonitorMethodTypeEnum.PROVIDE_OUT, methodName = "查询是否显示信用卡管理菜单", resv1="{request[0].custNo}", resv2="{response}") @Override public boolean queryShowCreditMenu(QueryShowCreditMenuRequest request) { ... } }
<!-- 扫描控制器类 --> <context:component-scan base-package="com.shhxzq.fin.lifeapp" /> <!-- 让aop可以切面到controller --> <aop:aspectj-autoproxy proxy-target-class="true"/>
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); } } } }
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; } }
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; } }
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; } } }
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); } }
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); }
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()); } } }
<?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>
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); } } }
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); }
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() + "]"; } }
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; } }
<?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。
<!-- mysql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.34</version> </dependency>
界面功能(查询明细,统计,实时监控)我在config_center上做了一套,后端查询record_app的实现。
所以以下代码不属于lifeapp,属于config_center+record_app
<!DOCTYPE html> <!-- This is a starter template page. Use this page to start your new project from scratch. This page gets rid of all links and provides the needed markup only. --> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>查看监控</title> <!-- Tell the browser to be responsive to screen width --> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"> <!-- Bootstrap 3.3.6 --> <link rel="stylesheet" href="${rc.contextPath}/bootstrap/css/bootstrap.min.css"> <!-- Font Awesome --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css"> <!-- Ionicons --> <!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css"> --> <!-- Theme style --> <link rel="stylesheet" href="${rc.contextPath}/dist/css/AdminLTE.min.css"> <!-- AdminLTE Skins. We have chosen the skin-blue for this starter page. However, you can choose any other skin. Make sure you apply the skin class to the body tag so the changes take effect. --> <link rel="stylesheet" href="${rc.contextPath}/dist/css/skins/skin-blue.min.css"> <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> <![endif]--> <!-- daterange picker --> <link rel="stylesheet" href="${rc.contextPath}/plugins/daterangepicker/daterangepicker.css"> <!-- bootstrap datepicker --> <link rel="stylesheet" href="${rc.contextPath}/plugins/datepicker/datepicker3.css"> <!-- bootstrap datetimepicker --> <link rel="stylesheet" href="${rc.contextPath}/plugins/datetimepicker/bootstrap-datetimepicker.css"> <!--自动换行--> <style> td { word-wrap:break-word; word-break:break-all; } </style> <script src="${rc.contextPath}/js/base.js"></script> <script type="text/javascript"> var contextPath = "${rc.contextPath}/"; var monitorArray = new Array();//监控信息集合 var pageSize = 10;//每页大小 var activePage = 1;//当前页数 var totalPage = 0;//总页数 var totalCount = 0;//总数 var isRequesting = false;//是否正在与服务器端交互 //查询监控信息 function queryMonitor(){ if(isRequesting){ showAttention("正在与服务器端交互,请稍等!"); return; } isRequesting = true; $("#monitor_table").css("display", "none"); $.ajax({ type: 'POST', url: '${rc.contextPath}/monitor/query.htm', data: 'methodRoute=' + $("#method_route").val() + '&methodType=' + $("#method_type").val() + '&outerSystem=' + $("#outer_system").val() + '&isException=' + $("#is_exception").val() + '&beginTime=' + $("#begin_time").val() + '&endTime=' + $("#end_time").val() + '&beginUsedTime=' + $("#begin_used_time").val() + '&endUsedTime=' + $("#end_used_time").val() + '&ip=' + $("#ip").val() + '&resv1=' + $("#resv1").val() + '&resv2=' + $("#resv2").val() + '&resv3=' + $("#resv3").val() + '&pageSize=' + pageSize + '&activePage=' + activePage, success: function(data) { isRequesting = false; var obj = data; monitorArray = obj.list; totalPage = obj.totalPage; totalCount = obj.totalCount; if(totalPage == 0){ totalPage = 1; activePage = 1; } showMonitor(); showSuccess("查询监控成功!"); } }); } //用户监控信息 function showMonitor(){ var content = "<div class='box-header with-border'> <h3 class='box-title'>查询结果</h3>" +"<div class='box-tools pull-right'>" +"<button type='button' class='btn btn-box-tool' data-widget='collapse'>" +"<i class='fa fa-minus'></i>" +"</button>" +"<button type='button' class='btn btn-box-tool' data-widget='remove'><i class='fa fa-times'></i></button>" +"</div></div>" +"<div class='box-body table-responsive no-padding'>" +"<table class='table table-bordered table-hover' style='width: 2500px;'>" +"<tbody>" +"<tr>" +"<th class='text-center'>主键</th>" +"<th class='text-center'>系统日期</th>" +"<th class='text-center'>系统时间</th>" +"<th class='text-center'>方法路径</th>" +"<th class='text-center'>方法名称</th>" +"<th class='text-center'>方法类型</th>" +"<th class='text-center'>外部系统</th>" +"<th class='text-center'>入参</th>" +"<th class='text-center'>出参</th>" +"<th class='text-center'>是否异常发生</th>" +"<th class='text-center'>开始时间</th>" +"<th class='text-center'>结束时间</th>" +"<th class='text-center'>耗时(毫秒)</th>" +"<th class='text-center'>机器ip</th>" +"<th class='text-center'>备注字段1</th>" +"<th class='text-center'>备注字段2</th>" +"<th class='text-center'>备注字段3</th>" +"</tr>"; if(monitorArray.length == 0){ content += "<tr><td class='text-center' colspan='17'>无相关数据!</td></tr>"; } else { for(var i=0;i<monitorArray.length;i++){ var obj = monitorArray[i]; content += "<tr id='tr_" + obj["id"] + "'>" +"<td class='text-center'>" + obj["id"] + "</td>" +"<td class='text-center'>" + obj["sysDate"] + "</td>" +"<td class='text-center'>" + obj["sysTime"] + "</td>" +"<td style='width: 300px;overflow:auto;'>" + obj["methodRoute"] + "</td>" +"<td class='text-center'>" + obj["methodName"] + "</td>" +"<td class='text-center'>" + obj["methodType"] + "</td>" +"<td class='text-center'>" + obj["outerSystem"] + "</td>" +"<td class='text-center'>" + obj["request"] + "</td>" +"<td class='text-center' style='width: 300px;overflow:auto;'>" + obj["response"] + "</td>" +"<td class='text-center'>" + obj["isException"] + "</td>" +"<td class='text-center'>" + obj["beginTime"] + "</td>" +"<td class='text-center'>" + obj["endTime"] + "</td>" +"<td class='text-center'>" + obj["usedTime"] + "</td>" +"<td class='text-center'>" + obj["ip"] + "</td>" +"<td class='text-center'>" + obj["resv1"] + "</td>" +"<td class='text-center'>" + obj["resv2"] + "</td>" +"<td class='text-center'>" + obj["resv3"] + "</td>" +"</tr>"; } } content += "</tbody>" +"</table>" +"</div>"; content += getTfoot(); $("#monitor_table").html(content); $("#monitor_table").css("display", "block"); } function getTfoot(){ var content = "<div class='box-footer clearfix'>" + "<ul class='pagination pagination-sm no-margin pull-right'>" + "<li>" + "<a>总数:[" + totalCount + "] 总页数:[" + totalPage + "]</a>" + "</li>" + "<li><a href=\"javascript: jump2page(1)\" title=\"首页\">« 首页</a></li>"; if(activePage > 1){ content += "<li><a href=\"javascript: jump2page(" + (activePage-1) + ")\" title=\"上一页\">« 上一页</a></li>"; } //显示前2页,本页,后2页 for(var i=activePage-2;i<activePage+3;i++){ if(i >= 1 && i <= totalPage){ content += "<li" + (i==activePage?" class='active'":"") + "><a href=\"javascript: jump2page(" + i + ")\" class=\"number" + ((i==activePage)?" current":"") + "\" title=\"" + i + "\">" + i + "</a></li>"; } } if(activePage < totalPage){ content += "<li><a href=\"javascript: jump2page(" + (activePage+1) + ")\" title=\"下一页\">下一页 »</a></li>"; } content += "<li><a href=\"javascript: jump2page(" + totalPage + ")\" title=\"尾页\">尾页 »</a></li>" + "</ul>" + "</div>"; return content; } function jump2page(index){ activePage = index; queryMonitor(); } //统计监控信息 function countMonitor(){ if(isRequesting){ showAttention("正在与服务器端交互,请稍等!"); return; } isRequesting = true; $("#monitor_table").css("display", "none"); $.ajax({ type: 'POST', url: '${rc.contextPath}/monitor/count.htm', data: 'methodRoute=' + $("#method_route").val() + '&methodType=' + $("#method_type").val() + '&outerSystem=' + $("#outer_system").val() + '&isException=' + $("#is_exception").val() + '&beginTime=' + $("#begin_time").val() + '&endTime=' + $("#end_time").val() + '&beginUsedTime=' + $("#begin_used_time").val() + '&endUsedTime=' + $("#end_used_time").val() + '&ip=' + $("#ip").val() + '&resv1=' + $("#resv1").val() + '&resv2=' + $("#resv2").val() + '&resv3=' + $("#resv3").val() + '&pageSize=' + pageSize + '&activePage=' + activePage, success: function(data) { isRequesting = false; showCountMonitor(data); showSuccess("统计监控成功!"); } }); } //统计监控信息 function showCountMonitor(obj){ var content = "<div class='box-header with-border'> <h3 class='box-title'>统计结果</h3>" +"<div class='box-tools pull-right'>" +"<button type='button' class='btn btn-box-tool' data-widget='collapse'>" +"<i class='fa fa-minus'></i>" +"</button>" +"<button type='button' class='btn btn-box-tool' data-widget='remove'><i class='fa fa-times'></i></button>" +"</div></div>" +"<div class='box-body table-responsive no-padding'>" +"<table class='table table-bordered table-hover'>" +"<tbody>" +"<tr>" +"<th class='text-center'>并发数</th>" +"<th class='text-center'>平均耗时(毫秒)</th>" +"<th class='text-center'>tps(事务数/秒)</th>" +"</tr>"; content += "<tr>" +"<td class='text-center'>" + obj.totalCount + "</td>" +"<td class='text-center'>" + obj.avgUsedTime + "</td>" +"<td class='text-center'>" + obj.tps + "</td>" +"</tr>"; content += "</tbody>" +"</table>" +"</div>"; $("#monitor_table").html(content); $("#monitor_table").css("display", "block"); } </script> <style type="text/css"> div.alert { padding-top: 5px; padding-bottom: 5px } </style> </head> <!-- BODY TAG OPTIONS: ================= Apply one or more of the following classes to get the desired effect |---------------------------------------------------------| | SKINS | skin-blue | | | skin-black | | | skin-purple | | | skin-yellow | | | skin-red | | | skin-green | |---------------------------------------------------------| |LAYOUT OPTIONS | fixed | | | layout-boxed | | | layout-top-nav | | | sidebar-collapse | | | sidebar-mini | |---------------------------------------------------------| --> <body class="hold-transition skin-blue sidebar-mini"> <div class="wrapper"> <!-- Main Header --> <header class="main-header"> <!-- Logo --> <a href="index2.html" class="logo"> <!-- mini logo for sidebar mini 50x50 pixels --> <span class="logo-mini"><b>RA</b></span> <!-- logo for regular state and mobile devices --> <span class="logo-lg"><b>Record App</b></span> </a> <!-- Header Navbar --> <nav class="navbar navbar-static-top" role="navigation"> <!-- Sidebar toggle button--> <a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button"> <span class="sr-only">Toggle navigation</span> </a> <!-- Navbar Right Menu --> <div class="navbar-custom-menu"> <ul class="nav navbar-nav"> <!-- User Account Menu --> <li class="dropdown user user-menu"> <!-- Menu Toggle Button --> <a href="#" class="dropdown-toggle" data-toggle="dropdown"> <!-- The user image in the navbar--> <img src="${rc.contextPath}/dist/img/user2-160x160.jpg" class="user-image" alt="User Image"> <!-- hidden-xs hides the username on small devices so only the image appears. --> <span class="hidden-xs">管理员</span> </a> <ul class="dropdown-menu"> <!-- The user image in the menu --> <li class="user-header"><img src="${rc.contextPath}/dist/img/user2-160x160.jpg" class="img-circle" alt="User Image"> <p> 管理员 <small>您已成功登录</small> </p></li> <!-- Menu Footer--> <li class="user-footer"> <div class="pull-right"> <a href="${rc.contextPath}/logout.htm" class="btn btn-default btn-flat">退出</a> </div> </li> </ul> </li> </ul> </div> </nav> </header> <!-- Left side column. contains the logo and sidebar --> <aside class="main-sidebar"> <!-- sidebar: style can be found in sidebar.less --> <section class="sidebar"> <!-- Sidebar user panel (optional) --> <div class="user-panel"> <div class="pull-left image"> <img src="${rc.contextPath}/dist/img/user2-160x160.jpg" class="img-circle" alt="User Image"> </div> <div class="pull-left info"> <p>管理员</p> <!-- Status --> <a href="#"><i class="glyphicon glyphicon-record text-success"></i> 已登录</a> </div> </div> <!-- Sidebar Menu --> <ul class="sidebar-menu"> <li class="header">配置</li> <!-- Optionally, you can add icons to the links --> <li> <a href="${rc.contextPath}/index.htm"> <i class="glyphicon glyphicon-search"></i> <span>查询配置</span> </a> </li> <li> <a href="${rc.contextPath}/config/add.htm"> <i class="glyphicon glyphicon-pencil"></i> <span>新增配置</span> </a> </li> <li class="header">交易监控</li> <!-- Optionally, you can add icons to the links --> <li class="active"> <a href="${rc.contextPath}/monitor/query.htm"> <i class="glyphicon glyphicon-search"></i> <span>监控查询</span> </a> </li> <li> <a href="${rc.contextPath}/monitor/realtime.htm"> <i class="glyphicon glyphicon-search"></i> <span>实时监控</span> </a> </li> </ul> <!-- /.sidebar-menu --> </section> <!-- /.sidebar --> </aside> <!-- Content Wrapper. Contains page content --> <div class="content-wrapper"> <!-- Main content --> <section class="content"> <div id="message_id" style="display: none;"></div> <div class="box box-primary"> <div class="box-header with-border"> <h3 class="box-title">监控查询</h3> <div class="box-tools pull-right"> <button type="button" class="btn btn-box-tool" data-widget="collapse"> <i class="fa fa-minus"></i> </button> <button type="button" class="btn btn-box-tool" data-widget="remove"><i class="fa fa-times"></i></button> </div> </div> <!-- /.box-header --> <div class="box-body"> <div class="row"> <div class="col-xs-12 col-sm-6 col-md-4"> <label>方法路径</label> <select class="form-control" id="method_route"> <option value="">全部</option> <#if Session.method_route_list?exists> <#list Session.method_route_list as node> <option value="${node}">${node}</option> </#list> </#if> </select> </div> <div class="col-xs-12 col-sm-6 col-md-4"> <label>方法类型</label> <select class="form-control" id="method_type"> <option value="">全部</option> <#if Session.method_type_list?exists> <#list Session.method_type_list as node> <option value="${node}">${node}</option> </#list> </#if> </select> </div> <div class="col-xs-12 col-sm-6 col-md-4"> <label>外部系统</label> <select class="form-control" id="outer_system"> <option value="">全部</option> <#if Session.outer_system_list?exists> <#list Session.outer_system_list as node> <option value="${node}">${node}</option> </#list> </#if> </select> </div> <div class="col-xs-12 col-sm-6 col-md-4"> <label>是否异常发生</label> <select class="form-control" id="is_exception"> <option value="">全部</option> <#if Session.is_exception_list?exists> <#list Session.is_exception_list as node> <option value="${node}">${node}</option> </#list> </#if> </select> </div> <div class="col-xs-12 col-sm-6 col-md-4"> <label>开始时间</label> <div class="input-group date"> <div class="input-group-addon"> <i class="glyphicon glyphicon-calendar"></i> </div> <input type="text" class="form-control pull-right" id="begin_time"> </div> </div> <div class="col-xs-12 col-sm-6 col-md-4"> <label>结束时间</label> <div class="input-group date"> <div class="input-group-addon"> <i class="glyphicon glyphicon-calendar"></i> </div> <input type="text" class="form-control pull-right" id="end_time"> </div> </div> <div class="col-xs-12 col-sm-6 col-md-4"> <label>最小耗时(毫秒)(>=)</label> <input type="text" class="form-control" placeholder="Enter ..." id="begin_used_time"> </div> <div class="col-xs-12 col-sm-6 col-md-4"> <label>最大耗时(毫秒)(<=)</label> <input type="text" class="form-control" placeholder="Enter ..." id="end_used_time"> </div> <div class="col-xs-12 col-sm-6 col-md-4"> <label>机器ip</label> <select class="form-control" id="ip"> <option value="">全部</option> <#if Session.ip_list?exists> <#list Session.ip_list as node> <option value="${node}">${node}</option> </#list> </#if> </select> </div> <div class="col-xs-12 col-sm-6 col-md-4"> <label>备注字段1</label> <input type="text" class="form-control" placeholder="Enter ..." id="resv1"> </div> <div class="col-xs-12 col-sm-6 col-md-4"> <label>备注字段2</label> <input type="text" class="form-control" placeholder="Enter ..." id="resv2"> </div> <div class="col-xs-12 col-sm-6 col-md-4"> <label>备注字段3</label> <input type="text" class="form-control" placeholder="Enter ..." id="resv3"> </div> <div class="col-xs-6 col-sm-3 col-md-2"> <label> </label> <button type="button" class="btn btn-block btn-primary" onclick="activePage=1;queryMonitor();">查询</button> </div> <div class="col-xs-6 col-sm-3 col-md-2"> <label> </label> <button type="button" class="btn btn-block btn-primary" onclick="activePage=1;countMonitor();">统计</button> </div> </div> </div> </div> <div id="monitor_table" class="box box-primary" style="display: none;"> <div class="box-header with-border"> <h3 class="box-title">查询结果</h3> </div> <!-- /.box-header --> <div class="box-body table-responsive no-padding"> <table class="table table-hover"> <tbody> <tr> <th style="width: 10px">ID</th> <th>环境</th> <th>项目</th> <th>监控名</th> <th>监控值</th> <th>描述</th> <th style="width: 60px">操作</th> </tr> <tr> <td>1.</td> <td>Update software</td> <td>Update software</td> <td>Update software</td> <td>Update software</td> <td>Update software</td> <td>ware</td> </tr> <tr> <td>2.</td> <td>Update software</td> <td>Update software</td> <td>Update software</td> <td>Update software</td> <td>Update software</td> <td>ware</td> </tr> </tbody> </table> </div> <!-- /.box-body --> <div class="box-footer clearfix"> <ul class="pagination pagination-sm no-margin pull-right"> <li><a href="#">«</a></li> <li><a href="#">1</a></li> <li><a href="#">2</a></li> <li><a href="#">3</a></li> <li><a href="#">»</a></li> </ul> </div> </div> <!-- /.box --> </section> <!-- /.content --> </div> <!-- /.content-wrapper --> <!-- Main Footer --> <footer class="main-footer"> <!-- To the right --> <div class="pull-right hidden-xs">Anything you want</div> <!-- Default to the left --> <strong>Copyright © 2016 <a href="#">Company</a>. </strong> All rights reserved. </footer> <!-- Add the sidebar's background. This div must be placed immediately after the control sidebar --> <div class="control-sidebar-bg"></div> </div> <!-- ./wrapper --> <!-- REQUIRED JS SCRIPTS --> <!-- jQuery 2.2.3 --> <script src="${rc.contextPath}/plugins/jQuery/jquery-2.2.3.min.js"></script> <!-- Bootstrap 3.3.6 --> <script src="${rc.contextPath}/bootstrap/js/bootstrap.min.js"></script> <!-- AdminLTE App --> <script src="${rc.contextPath}/dist/js/app.min.js"></script> <!-- bootstrap datepicker --> <script src="${rc.contextPath}/plugins/datetimepicker/bootstrap-datetimepicker.js"></script> <script type="text/javascript"> //DateTime picker $('#begin_time').datetimepicker({format: 'yyyy-mm-dd hh:ii'}); //DateTime picker $('#end_time').datetimepicker({format: 'yyyy-mm-dd hh:ii'}); </script> <!-- Optionally, you can add Slimscroll and FastClick plugins. Both of these plugins are recommended to enhance the user experience. Slimscroll is required when using the fixed layout. --> </body> </html>
<!DOCTYPE html> <!-- This is a starter template page. Use this page to start your new project from scratch. This page gets rid of all links and provides the needed markup only. --> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>实时监控</title> <!-- Tell the browser to be responsive to screen width --> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"> <!-- Bootstrap 3.3.6 --> <link rel="stylesheet" href="${rc.contextPath}/bootstrap/css/bootstrap.min.css"> <!-- Font Awesome --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css"> <!-- Ionicons --> <!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css"> --> <!-- Theme style --> <link rel="stylesheet" href="${rc.contextPath}/dist/css/AdminLTE.min.css"> <!-- AdminLTE Skins. We have chosen the skin-blue for this starter page. However, you can choose any other skin. Make sure you apply the skin class to the body tag so the changes take effect. --> <link rel="stylesheet" href="${rc.contextPath}/dist/css/skins/skin-blue.min.css"> <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> <![endif]--> <!-- daterange picker --> <link rel="stylesheet" href="${rc.contextPath}/plugins/daterangepicker/daterangepicker.css"> <!-- bootstrap datepicker --> <link rel="stylesheet" href="${rc.contextPath}/plugins/datepicker/datepicker3.css"> <!-- bootstrap datetimepicker --> <link rel="stylesheet" href="${rc.contextPath}/plugins/datetimepicker/bootstrap-datetimepicker.css"> <!--自动换行--> <style> td { word-wrap:break-word; word-break:break-all; } </style> <script src="${rc.contextPath}/js/base.js"></script> <script type="text/javascript"> var contextPath = "${rc.contextPath}/"; var monitorArray = new Array();//监控信息集合 var pageSize = 10;//每页大小 var activePage = 1;//当前页数 var totalPage = 0;//总页数 var totalCount = 0;//总数 var isRequesting = false;//是否正在与服务器端交互 var avgUsedTime = 0;//平均耗时 var tps = 0;//tps var nowBeginTimeString = "";//当前开始统计时间 var nowEndTimeString = "";//当前开始统计时间 //历史统计 function queryHistory() { var beginTime = $("#begin_time").val(); var endTime = $("#end_time").val(); if("" == beginTime || "" == endTime) { showAttention("请选择[历史开始时间]和[历史结束时间]!"); return; } if(beginTime >= endTime) { showAttention("[历史开始时间]必须小于[历史结束时间]!"); return; } var beginTimeObj = parseDate(beginTime, 'yyyy-MM-dd HH:mm'); var endTimeObj = parseDate(endTime, 'yyyy-MM-dd HH:mm'); var gap = parseInt($("#gap").val()) * 1000; if((endTimeObj.getTime() - beginTimeObj.getTime())/gap > 60) { showAttention("取点时间间隔太小,取点太多,服务器扛不住!"); return; } config.data.labels = new Array(); config.data.datasets[0].data = new Array(); config.data.datasets[1].data = new Array(); config.data.datasets[2].data = new Array(); //formatDate() var nowBeginTime = beginTimeObj.getTime(); var nowEndTime = nowBeginTime + gap; nowBeginTimeString = formatDate(nowBeginTime); nowEndTimeString = formatDate(nowEndTime); countMonitor();//统计监控信息 nowBeginTime = nowEndTime; nowEndTime = nowBeginTime + gap; while(nowBeginTime <= endTimeObj.getTime()) { nowBeginTimeString = formatDate(nowBeginTime); nowEndTimeString = formatDate(nowEndTime); countMonitor();//统计监控信息 nowBeginTime = nowEndTime; nowEndTime = nowBeginTime + gap; } } //统计监控信息 function countMonitor(){ if(isRequesting){ showAttention("正在与服务器端交互,请稍等!"); return; } isRequesting = true; $.ajax({ type: 'POST', async: false, url: '${rc.contextPath}/monitor/count.htm', data: 'methodRoute=' + $("#method_route").val() + '&methodType=' + $("#method_type").val() + '&outerSystem=' + $("#outer_system").val() + '&isException=' + $("#is_exception").val() + '&beginTime=' + nowBeginTimeString + '&endTime=' + nowEndTimeString + '&ip=' + $("#ip").val() + '&resv1=' + $("#resv1").val() + '&resv2=' + $("#resv2").val() + '&resv3=' + $("#resv3").val() + '&pageSize=' + pageSize + '&activePage=' + activePage, success: function(data) { isRequesting = false; totalCount = data.totalCount; avgUsedTime = data.avgUsedTime; tps = data.tps; config.data.labels.push(nowBeginTimeString); config.data.datasets[0].data.push(totalCount); config.data.datasets[1].data.push(avgUsedTime); config.data.datasets[2].data.push(tps); window.myLine.update(); } }); } //实时统计 function realtimeCount() { //待实现 } </script> <style type="text/css"> div.alert { padding-top: 5px; padding-bottom: 5px } </style> </head> <!-- BODY TAG OPTIONS: ================= Apply one or more of the following classes to get the desired effect |---------------------------------------------------------| | SKINS | skin-blue | | | skin-black | | | skin-purple | | | skin-yellow | | | skin-red | | | skin-green | |---------------------------------------------------------| |LAYOUT OPTIONS | fixed | | | layout-boxed | | | layout-top-nav | | | sidebar-collapse | | | sidebar-mini | |---------------------------------------------------------| --> <body class="hold-transition skin-blue sidebar-mini"> <div class="wrapper"> <!-- Main Header --> <header class="main-header"> <!-- Logo --> <a href="index2.html" class="logo"> <!-- mini logo for sidebar mini 50x50 pixels --> <span class="logo-mini"><b>RA</b></span> <!-- logo for regular state and mobile devices --> <span class="logo-lg"><b>Record App</b></span> </a> <!-- Header Navbar --> <nav class="navbar navbar-static-top" role="navigation"> <!-- Sidebar toggle button--> <a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button"> <span class="sr-only">Toggle navigation</span> </a> <!-- Navbar Right Menu --> <div class="navbar-custom-menu"> <ul class="nav navbar-nav"> <!-- User Account Menu --> <li class="dropdown user user-menu"> <!-- Menu Toggle Button --> <a href="#" class="dropdown-toggle" data-toggle="dropdown"> <!-- The user image in the navbar--> <img src="${rc.contextPath}/dist/img/user2-160x160.jpg" class="user-image" alt="User Image"> <!-- hidden-xs hides the username on small devices so only the image appears. --> <span class="hidden-xs">管理员</span> </a> <ul class="dropdown-menu"> <!-- The user image in the menu --> <li class="user-header"><img src="${rc.contextPath}/dist/img/user2-160x160.jpg" class="img-circle" alt="User Image"> <p> 管理员 <small>您已成功登录</small> </p></li> <!-- Menu Footer--> <li class="user-footer"> <div class="pull-right"> <a href="${rc.contextPath}/logout.htm" class="btn btn-default btn-flat">退出</a> </div> </li> </ul> </li> </ul> </div> </nav> </header> <!-- Left side column. contains the logo and sidebar --> <aside class="main-sidebar"> <!-- sidebar: style can be found in sidebar.less --> <section class="sidebar"> <!-- Sidebar user panel (optional) --> <div class="user-panel"> <div class="pull-left image"> <img src="${rc.contextPath}/dist/img/user2-160x160.jpg" class="img-circle" alt="User Image"> </div> <div class="pull-left info"> <p>管理员</p> <!-- Status --> <a href="#"><i class="glyphicon glyphicon-record text-success"></i> 已登录</a> </div> </div> <!-- Sidebar Menu --> <ul class="sidebar-menu"> <li class="header">配置</li> <!-- Optionally, you can add icons to the links --> <li> <a href="${rc.contextPath}/index.htm"> <i class="glyphicon glyphicon-search"></i> <span>查询配置</span> </a> </li> <li> <a href="${rc.contextPath}/config/add.htm"> <i class="glyphicon glyphicon-pencil"></i> <span>新增配置</span> </a> </li> <li class="header">交易监控</li> <!-- Optionally, you can add icons to the links --> <li> <a href="${rc.contextPath}/monitor/query.htm"> <i class="glyphicon glyphicon-search"></i> <span>监控查询</span> </a> </li> <li class="active"> <a href="${rc.contextPath}/monitor/realtime.htm"> <i class="glyphicon glyphicon-search"></i> <span>实时监控</span> </a> </li> </ul> <!-- /.sidebar-menu --> </section> <!-- /.sidebar --> </aside> <!-- Content Wrapper. Contains page content --> <div class="content-wrapper"> <!-- Main content --> <section class="content"> <div id="message_id" style="display: none;"></div> <div class="box box-primary"> <div class="box-header with-border"> <h3 class="box-title">实时监控</h3> <div class="box-tools pull-right"> <button type="button" class="btn btn-box-tool" data-widget="collapse"> <i class="fa fa-minus"></i> </button> <button type="button" class="btn btn-box-tool" data-widget="remove"><i class="fa fa-times"></i></button> </div> </div> <!-- /.box-header --> <div class="box-body"> <div class="row"> <div class="col-xs-12 col-sm-6 col-md-4"> <label>方法路径</label> <select class="form-control" id="method_route"> <option value="">全部</option> <#if Session.method_route_list?exists> <#list Session.method_route_list as node> <option value="${node}">${node}</option> </#list> </#if> </select> </div> <div class="col-xs-12 col-sm-6 col-md-4"> <label>方法类型</label> <select class="form-control" id="method_type"> <option value="">全部</option> <#if Session.method_type_list?exists> <#list Session.method_type_list as node> <option value="${node}">${node}</option> </#list> </#if> </select> </div> <div class="col-xs-12 col-sm-6 col-md-4"> <label>外部系统</label> <select class="form-control" id="outer_system"> <option value="">全部</option> <#if Session.outer_system_list?exists> <#list Session.outer_system_list as node> <option value="${node}">${node}</option> </#list> </#if> </select> </div> <div class="col-xs-12 col-sm-6 col-md-4"> <label>是否异常发生</label> <select class="form-control" id="is_exception"> <option value="">全部</option> <#if Session.is_exception_list?exists> <#list Session.is_exception_list as node> <option value="${node}">${node}</option> </#list> </#if> </select> </div> <div class="col-xs-12 col-sm-6 col-md-4"> <label>机器ip</label> <select class="form-control" id="ip"> <option value="">全部</option> <#if Session.ip_list?exists> <#list Session.ip_list as node> <option value="${node}">${node}</option> </#list> </#if> </select> </div> <div class="col-xs-12 col-sm-6 col-md-4"> <label>备注字段1</label> <input type="text" class="form-control" placeholder="Enter ..." id="resv1"> </div> <div class="col-xs-12 col-sm-6 col-md-4"> <label>备注字段2</label> <input type="text" class="form-control" placeholder="Enter ..." id="resv2"> </div> <div class="col-xs-12 col-sm-6 col-md-4"> <label>备注字段3</label> <input type="text" class="form-control" placeholder="Enter ..." id="resv3"> </div> <div class="col-xs-12 col-sm-6 col-md-4"> <label>取点时间间隔</label> <select class="form-control" id="gap"> <option value="60" selected>1分钟</option> <option value="600">10分钟</option> <option value="1800">30分钟</option> <option value="3600">1小时</option> <option value="43200">12小时</option> <option value="86400">1天</option> </select> </div> <div class="col-xs-12 col-sm-6 col-md-4"> </div> <div class="col-xs-12 col-sm-6 col-md-4"> </div> <div class="col-xs-12 col-sm-6 col-md-4"> <label> </label> <button type="button" class="btn btn-block btn-primary" onclick="activePage=1;realtimeCount();">实时统计</button> </div> </div> <div class="row"> <div class="col-xs-12 col-sm-6 col-md-4"> <label>历史开始时间</label> <div class="input-group date"> <div class="input-group-addon"> <i class="glyphicon glyphicon-calendar"></i> </div> <input type="text" class="form-control pull-right" id="begin_time"> </div> </div> <div class="col-xs-12 col-sm-6 col-md-4"> <label>历史结束时间</label> <div class="input-group date"> <div class="input-group-addon"> <i class="glyphicon glyphicon-calendar"></i> </div> <input type="text" class="form-control pull-right" id="end_time"> </div> </div> <div class="col-xs-12 col-sm-6 col-md-4"> <label> </label> <button type="button" class="btn btn-block btn-primary" onclick="activePage=1;queryHistory();">历史统计</button> </div> </div> </div> </div> <canvas id="canvas"></canvas> <!-- /.box --> </section> <!-- /.content --> </div> <!-- /.content-wrapper --> <!-- Main Footer --> <footer class="main-footer"> <!-- To the right --> <div class="pull-right hidden-xs">Anything you want</div> <!-- Default to the left --> <strong>Copyright © 2016 <a href="#">Company</a>. </strong> All rights reserved. </footer> <!-- Add the sidebar's background. This div must be placed immediately after the control sidebar --> <div class="control-sidebar-bg"></div> </div> <!-- ./wrapper --> <!-- REQUIRED JS SCRIPTS --> <!-- jQuery 2.2.3 --> <script src="${rc.contextPath}/plugins/jQuery/jquery-2.2.3.min.js"></script> <!-- Bootstrap 3.3.6 --> <script src="${rc.contextPath}/bootstrap/js/bootstrap.min.js"></script> <!-- AdminLTE App --> <script src="${rc.contextPath}/dist/js/app.min.js"></script> <!-- bootstrap datepicker --> <script src="${rc.contextPath}/plugins/datetimepicker/bootstrap-datetimepicker.js"></script> <!-- http://www.chartjs.org/ --> <script src="http://www.chartjs.org/dist/2.6.0/Chart.bundle.js"></script> <script src="http://www.chartjs.org/samples/latest/utils.js"></script> <script type="text/javascript"> //DateTime picker $('#begin_time').datetimepicker({format: 'yyyy-mm-dd hh:ii'}); //DateTime picker $('#end_time').datetimepicker({format: 'yyyy-mm-dd hh:ii'}); var config = { type: 'line', data: { labels: [], datasets: [{ label: "并发数", fill: false, backgroundColor: window.chartColors.red, borderColor: window.chartColors.red, data: [ ], }, { label: "平均耗时(毫秒)", fill: false, backgroundColor: window.chartColors.blue, borderColor: window.chartColors.blue, data: [ ], }, { label: "tps(事务数/秒)", fill: false, backgroundColor: window.chartColors.yellow, borderColor: window.chartColors.yellow, data: [ ], }] }, options: { responsive: true, title:{ display:true, text:'记录点滴APP交易监控' }, tooltips: { mode: 'index', intersect: false, }, hover: { mode: 'nearest', intersect: true }, scales: { xAxes: [{ display: true, scaleLabel: { display: true, labelString: '时段' } }], yAxes: [{ display: true, scaleLabel: { display: true, labelString: '值' } }] } } }; window.onload = function() { var ctx = document.getElementById("canvas").getContext("2d"); window.myLine = new Chart(ctx, config); }; </script> <!-- Optionally, you can add Slimscroll and FastClick plugins. Both of these plugins are recommended to enhance the user experience. Slimscroll is required when using the fixed layout. --> </body> </html>
config_center下的
package com.gxx.config_center.web.monitor; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import com.alibaba.fastjson.JSONArray; import com.gxx.config_center.dto.MonitorDto; import com.gxx.config_center.interfaces.BaseInterface; import com.gxx.config_center.interfaces.MonitorInterface; import com.gxx.config_center.utils.HttpClientUtils; /** * <dl> * <dt><b>Title:</b></dt> * <dd> * none * </dd> * <dt><b>Description:监控控制器</b></dt> * <dd> * <p>none * </dd> * </dl> * * @author Administrator * @version 1.0, 2017年06月21日 * @since config_center */ @Controller @RequestMapping("/monitor/") public class MonitorController { /** * 日志处理器 */ private final Logger logger = Logger.getLogger(MonitorController.class); /** * 访问交易监控查询页面 * @return */ @RequestMapping(value = "/query", method = RequestMethod.GET) public String queryGet(HttpServletRequest request) { if(null == request.getSession().getAttribute(BaseInterface.KEY_USER)){ logger.info("访问account/login"); return "account/login"; } /** * 初始化session */ initSession(request); logger.info("访问monitor/query"); return "monitor/query"; } /** * 交易监控查询 * @param request * @param monitorDto * @return */ @RequestMapping(value = "/query", method = RequestMethod.POST, produces="application/json") public @ResponseBody String query(HttpServletRequest request, MonitorDto monitorDto) { logger.info("交易监控查询,方法路径:[" + monitorDto.getMethodRoute() + "],方法类型:[" + monitorDto.getMethodType() + "]" + ",外部系统:[" + monitorDto.getOuterSystem() + "],是否异常发生:[" + monitorDto.getIsException() + "]" + ",开始时间:[" + monitorDto.getBeginTime() + "],结束时间:[" + monitorDto.getEndTime() + "]" + ",最小耗时(毫秒)(>=):[" + monitorDto.getBeginUsedTime() + "],最大耗时(毫秒)(<=):[" + monitorDto.getEndUsedTime() + "]" + ",机器ip:[" + monitorDto.getIp() + "]" + ",备注字段1:[" + monitorDto.getResv1() + "],备注字段2:[" + monitorDto.getResv2() + "]" + ",备注字段3:[" + monitorDto.getResv3() + "],每页个数:[" + monitorDto.getPageSize() + "]" + ",当前页数:[" + monitorDto.getActivePage() + "]"); /** * 判登录 */ if(null == request.getSession().getAttribute(BaseInterface.KEY_USER)){ logger.info("请先登录!"); return "{isSuccess:false,message:'请先登录!'}"; } /** * 调record_app查询 */ String url = "http://121.43.104.34:8080/record_app/monitor/query.htm"; Map<String, String> mapData = new HashMap<String, String>(); mapData.put("methodRoute", monitorDto.getMethodRoute()); mapData.put("methodType", processColon(monitorDto.getMethodType())); mapData.put("outerSystem", processColon(monitorDto.getOuterSystem())); mapData.put("isException", StringUtils.isBlank(monitorDto.getIsException())?"-1":processColon(monitorDto.getIsException())); mapData.put("beginTime", monitorDto.getBeginTime()); mapData.put("endTime", monitorDto.getEndTime()); mapData.put("beginUsedTime", StringUtils.isBlank(monitorDto.getBeginUsedTime())?"-1":monitorDto.getBeginUsedTime()); mapData.put("endUsedTime", StringUtils.isBlank(monitorDto.getEndUsedTime())?"-1":monitorDto.getEndUsedTime()); mapData.put("ip", monitorDto.getIp()); mapData.put("resv1", monitorDto.getResv1()); mapData.put("resv2", monitorDto.getResv2()); mapData.put("resv3", monitorDto.getResv3()); mapData.put("pageSize", StringUtils.EMPTY + monitorDto.getPageSize()); mapData.put("activePage", StringUtils.EMPTY + monitorDto.getActivePage()); return HttpClientUtils.getWebContentByPost(url, mapData, "utf-8"); } /** * 交易监控统计 * @param request * @param monitorDto * @return */ @RequestMapping(value = "/count", method = RequestMethod.POST, produces="application/json") public @ResponseBody String count(HttpServletRequest request, MonitorDto monitorDto) { logger.info("交易监控查询,方法路径:[" + monitorDto.getMethodRoute() + "],方法类型:[" + monitorDto.getMethodType() + "]" + ",外部系统:[" + monitorDto.getOuterSystem() + "],是否异常发生:[" + monitorDto.getIsException() + "]" + ",开始时间:[" + monitorDto.getBeginTime() + "],结束时间:[" + monitorDto.getEndTime() + "]" + ",最小耗时(毫秒)(>=):[" + monitorDto.getBeginUsedTime() + "],最大耗时(毫秒)(<=):[" + monitorDto.getEndUsedTime() + "]" + ",机器ip:[" + monitorDto.getIp() + "]" + ",备注字段1:[" + monitorDto.getResv1() + "],备注字段2:[" + monitorDto.getResv2() + "]" + ",备注字段3:[" + monitorDto.getResv3() + "]"); /** * 判登录 */ if(null == request.getSession().getAttribute(BaseInterface.KEY_USER)){ logger.info("请先登录!"); return "{isSuccess:false,message:'请先登录!'}"; } /** * 调record_app查询 */ String url = "http://121.43.104.34:8080/record_app/monitor/count.htm"; Map<String, String> mapData = new HashMap<String, String>(); mapData.put("methodRoute", monitorDto.getMethodRoute()); mapData.put("methodType", processColon(monitorDto.getMethodType())); mapData.put("outerSystem", processColon(monitorDto.getOuterSystem())); mapData.put("isException", StringUtils.isBlank(monitorDto.getIsException())?"-1":processColon(monitorDto.getIsException())); mapData.put("beginTime", monitorDto.getBeginTime()); mapData.put("endTime", monitorDto.getEndTime()); mapData.put("beginUsedTime", StringUtils.isBlank(monitorDto.getBeginUsedTime())?"-1":monitorDto.getBeginUsedTime()); mapData.put("endUsedTime", StringUtils.isBlank(monitorDto.getEndUsedTime())?"-1":monitorDto.getEndUsedTime()); mapData.put("ip", monitorDto.getIp()); mapData.put("resv1", monitorDto.getResv1()); mapData.put("resv2", monitorDto.getResv2()); mapData.put("resv3", monitorDto.getResv3()); return HttpClientUtils.getWebContentByPost(url, mapData, "utf-8"); } /** * 处理字符串,含有:,则返回:之前的字符 * @param string * @return */ private String processColon(String string) { int index = StringUtils.indexOf(string, ":"); if(index > -1) { string = string.substring(0, index); } return string; } /** * 初始化session * @param request */ public void initSession(HttpServletRequest request) { /** * 调record_app查询 */ String url = "http://121.43.104.34:8080/record_app/monitor/queryAllMethodRoutes.htm"; String methodRoutes = HttpClientUtils.getWebContentByGet(url, "utf-8"); JSONArray array = JSONArray.parseArray(methodRoutes); Object[] objArray = null; if(null != array) { objArray = array.toArray(); } /** * 方法路径 */ request.getSession().setAttribute(MonitorInterface.METHOD_ROUTE_LIST, objArray); /** * 方法类型 */ request.getSession().setAttribute(MonitorInterface.METHOD_TYPE_LIST, new String[]{"PO:提供对外服务方法","IN:内部服务方法","IO:调用外部方法","SQL:SQL"}); /** * 外部系统 */ request.getSession().setAttribute(MonitorInterface.OUTER_SYSTEM_LIST, new String[]{"record_app:记录点滴"}); /** * 是否异常发生 */ request.getSession().setAttribute(MonitorInterface.IS_EXCEPTION_LIST, new String[]{"0:无异常发生","1:异常发生"}); /** * 机器ip */ request.getSession().setAttribute(MonitorInterface.IP_LIST, new String[]{"10.117.24.172"}); } /** * 访问实时监控页面 * @return */ @RequestMapping(value = "/realtime", method = RequestMethod.GET) public String realtimeGet(HttpServletRequest request) { if(null == request.getSession().getAttribute(BaseInterface.KEY_USER)){ logger.info("访问account/login"); return "account/login"; } /** * 初始化session */ initSession(request); logger.info("访问monitor/realtime"); return "monitor/realtime"; } /** * 实时监控 * @param request * @param monitorDto * @return */ @RequestMapping(value = "/realtime", method = RequestMethod.POST, produces="application/json") public @ResponseBody String realtime(HttpServletRequest request, MonitorDto monitorDto) { logger.info("交易监控查询,方法路径:[" + monitorDto.getMethodRoute() + "],方法类型:[" + monitorDto.getMethodType() + "]" + ",外部系统:[" + monitorDto.getOuterSystem() + "],是否异常发生:[" + monitorDto.getIsException() + "]" + ",开始时间:[" + monitorDto.getBeginTime() + "],结束时间:[" + monitorDto.getEndTime() + "]" + ",机器ip:[" + monitorDto.getIp() + "]" + ",备注字段1:[" + monitorDto.getResv1() + "],备注字段2:[" + monitorDto.getResv2() + "]" + ",备注字段3:[" + monitorDto.getResv3() + "]"); /** * 判登录 */ if(null == request.getSession().getAttribute(BaseInterface.KEY_USER)){ logger.info("请先登录!"); return "{isSuccess:false,message:'请先登录!'}"; } /** * 调record_app查询 */ String url = "http://121.43.104.34:8080/record_app/monitor/count.htm"; Map<String, String> mapData = new HashMap<String, String>(); mapData.put("methodRoute", monitorDto.getMethodRoute()); mapData.put("methodType", processColon(monitorDto.getMethodType())); mapData.put("outerSystem", processColon(monitorDto.getOuterSystem())); mapData.put("isException", StringUtils.isBlank(monitorDto.getIsException())?"-1":processColon(monitorDto.getIsException())); mapData.put("beginTime", monitorDto.getBeginTime()); mapData.put("endTime", monitorDto.getEndTime()); mapData.put("beginUsedTime", StringUtils.isBlank(monitorDto.getBeginUsedTime())?"-1":monitorDto.getBeginUsedTime()); mapData.put("endUsedTime", StringUtils.isBlank(monitorDto.getEndUsedTime())?"-1":monitorDto.getEndUsedTime()); mapData.put("ip", monitorDto.getIp()); mapData.put("resv1", monitorDto.getResv1()); mapData.put("resv2", monitorDto.getResv2()); mapData.put("resv3", monitorDto.getResv3()); return HttpClientUtils.getWebContentByPost(url, mapData, "utf-8"); } }
record_app下的
package com.gxx.record_app.web.monitor; import java.util.List; import javax.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.gxx.record_app.base.dao.TransMonitorMapper; import com.gxx.record_app.base.vo.TransMonitorWithBLOBs; import com.gxx.record_app.dto.MonitorDto; import com.gxx.record_app.interfaces.UserInterface; /** * <dl> * <dt><b>Title:</b></dt> * <dd> * none * </dd> * <dt><b>Description:监控控制器</b></dt> * <dd> * <p>none * </dd> * </dl> * * @author Gxx * @version 1.0, 2017年06月22日 * @since record_app */ @Controller @RequestMapping("/monitor/") public class MonitorController implements UserInterface { /** * 日志处理器 */ private final Logger logger = Logger.getLogger(MonitorController.class); @Autowired private TransMonitorMapper transMonitorMapper; /** * 交易监控查询 * @param request * @param monitorDto * @return */ @RequestMapping(value = "/query",produces="application/json") public @ResponseBody MonitorDto query(HttpServletRequest request, MonitorDto monitorDto) { logger.info("交易监控查询,方法路径:[" + monitorDto.getMethodRoute() + "],方法类型:[" + monitorDto.getMethodType() + "]" + ",外部系统:[" + monitorDto.getOuterSystem() + "],是否异常发生:[" + monitorDto.getIsException() + "]" + ",开始时间:[" + monitorDto.getBeginTime() + "],结束时间:[" + monitorDto.getEndTime() + "]" + ",最小耗时(毫秒)(>=):[" + monitorDto.getBeginUsedTime() + "],最大耗时(毫秒)(<=):[" + monitorDto.getEndUsedTime() + "]" + ",机器ip:[" + monitorDto.getIp() + "]" + ",备注字段1:[" + monitorDto.getResv1() + "],备注字段2:[" + monitorDto.getResv2() + "]" + ",备注字段3:[" + monitorDto.getResv3() + "],每页个数:[" + monitorDto.getPageSize() + "]" + ",当前页数:[" + monitorDto.getActivePage() + "]"); monitorDto.setIsSuccess(true); monitorDto.setMessage("查询成功!"); List<TransMonitorWithBLOBs> list = transMonitorMapper.queryTransMonitor(monitorDto); monitorDto.setList(list); /** * 查询配置信息总数 */ long totalCount = transMonitorMapper.countTransMonitor(monitorDto); long totalPage = 0; if(monitorDto.getPageSize() > 0 && totalCount > 0){ totalPage = (totalCount-1)/monitorDto.getPageSize()+1; } monitorDto.setTotalCount(totalCount); monitorDto.setTotalPage(totalPage); return monitorDto; } /** * 交易监控统计 * @param request * @param monitorDto * @return */ @RequestMapping(value = "/count",produces="application/json") public @ResponseBody MonitorDto count(HttpServletRequest request, MonitorDto monitorDto) { logger.info("交易监控查询,方法路径:[" + monitorDto.getMethodRoute() + "],方法类型:[" + monitorDto.getMethodType() + "]" + ",外部系统:[" + monitorDto.getOuterSystem() + "],是否异常发生:[" + monitorDto.getIsException() + "]" + ",开始时间:[" + monitorDto.getBeginTime() + "],结束时间:[" + monitorDto.getEndTime() + "]" + ",最小耗时(毫秒)(>=):[" + monitorDto.getBeginUsedTime() + "],最大耗时(毫秒)(<=):[" + monitorDto.getEndUsedTime() + "]" + ",机器ip:[" + monitorDto.getIp() + "]" + ",备注字段1:[" + monitorDto.getResv1() + "],备注字段2:[" + monitorDto.getResv2() + "]" + ",备注字段3:[" + monitorDto.getResv3() + "],每页个数:[" + monitorDto.getPageSize() + "]" + ",当前页数:[" + monitorDto.getActivePage() + "]"); monitorDto.setIsSuccess(true); monitorDto.setMessage("查询成功!"); long totalCount = transMonitorMapper.countTransMonitor(monitorDto);//并发数 double avgUsedTime = 0;//平均耗时 long tps = 0;//每秒钟支持并发数 if(totalCount > 0) { avgUsedTime = transMonitorMapper.queryAvgUsedTime(monitorDto);//平均耗时 if(avgUsedTime > 0) { tps = (long)(totalCount *1000.0 / avgUsedTime); } } monitorDto.setTotalCount(totalCount); monitorDto.setAvgUsedTime(avgUsedTime); monitorDto.setTps(tps); return monitorDto; } /** * 查询所有监控方法路径 * @param request * @return */ @RequestMapping(value = "/queryAllMethodRoutes",produces="application/json") public @ResponseBody List<String> queryAllMethodRoutes(HttpServletRequest request) { return transMonitorMapper.queryAllMethodRoutes(); } }
package com.gxx.record_app.base.dao; import java.util.List; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.SelectProvider; import org.springframework.stereotype.Repository; import com.gxx.record_app.base.vo.TransMonitor; import com.gxx.record_app.base.vo.TransMonitorWithBLOBs; import com.gxx.record_app.dto.MonitorDto; @Repository public interface TransMonitorMapper { int deleteByPrimaryKey(Integer id); int insert(TransMonitorWithBLOBs record); int insertSelective(TransMonitorWithBLOBs record); TransMonitorWithBLOBs selectByPrimaryKey(Integer id); int updateByPrimaryKeySelective(TransMonitorWithBLOBs record); int updateByPrimaryKeyWithBLOBs(TransMonitorWithBLOBs record); int updateByPrimaryKey(TransMonitor record); /** * 查询交易监控 * @param monitorDto * @return */ @SelectProvider(type=TransMonitorSqlProvider.class,method="queryTransMonitor") public List<TransMonitorWithBLOBs> queryTransMonitor(MonitorDto monitorDto); /** * 查询交易监控总数 * @param monitorDto * @return */ @SelectProvider(type=TransMonitorSqlProvider.class,method="countTransMonitor") public long countTransMonitor(MonitorDto monitorDto); /** * 查询平均耗时 * @param monitorDto * @return */ @SelectProvider(type=TransMonitorSqlProvider.class,method="queryAvgUsedTime") public double queryAvgUsedTime(MonitorDto monitorDto); /** * 查询所有监控方法路径 * @return */ @Select("SELECT DISTINCT METHOD_ROUTE FROM TRANS_MONITOR") public List<String> queryAllMethodRoutes(); }
package com.gxx.record_app.base.dao; import org.apache.commons.lang3.StringUtils; import com.gxx.record_app.dto.MonitorDto; /** * <dl> * <dt><b>Title:</b></dt> * <dd> * none * </dd> * <dt><b>Description:交易监控查询SQL提供类</b></dt> * <dd> * <p>none * </dd> * </dl> * * @author Gxx * @version 1.0, 2017年06月22日 * @since record_app * */ public class TransMonitorSqlProvider { /** * 查询交易监控 * @param monitorDto * @return */ public String queryTransMonitor(MonitorDto monitorDto){ String sql = "SELECT * FROM TRANS_MONITOR WHERE 1=1"; //方法路径 if(StringUtils.isNotBlank(monitorDto.getMethodRoute())){ sql += " AND METHOD_ROUTE = '" + (monitorDto.getMethodRoute()) + "'"; } //方法类型 if(StringUtils.isNotBlank(monitorDto.getMethodType())){ sql += " AND METHOD_TYPE = '" + (monitorDto.getMethodType()) + "'"; } //外部系统 if(StringUtils.isNotBlank(monitorDto.getOuterSystem())){ sql += " AND OUTER_SYSTEM = '" + (monitorDto.getOuterSystem()) + "'"; } //是否异常发生 if(monitorDto.getIsException() >= 0){ sql += " AND IS_EXCEPTION = " + (monitorDto.getIsException()); } //开始时间 if(StringUtils.isNotBlank(monitorDto.getBeginTime())){ sql += " AND BEGIN_TIME >= '" + (monitorDto.getBeginTime()) + "'"; } //结束时间 if(StringUtils.isNotBlank(monitorDto.getEndTime())){ sql += " AND END_TIME <= '" + (monitorDto.getEndTime()) + "'"; } //最小耗时(毫秒)(>=) if(monitorDto.getBeginUsedTime() >= 0){ sql += " AND USED_TIME >= " + (monitorDto.getBeginUsedTime()); } //最大耗时(毫秒)(<=) if(monitorDto.getEndUsedTime() >= 0){ sql += " AND USED_TIME <= " + (monitorDto.getEndUsedTime()); } //机器ip if(StringUtils.isNotBlank(monitorDto.getIp())){ sql += " AND IP = '" + (monitorDto.getIp()) + "'"; } //备注字段1 if(StringUtils.isNotBlank(monitorDto.getResv1())){ sql += " AND RESV1 LIKE '%" + (monitorDto.getResv1()) + "%'"; } //备注字段2 if(StringUtils.isNotBlank(monitorDto.getResv2())){ sql += " AND RESV2 LIKE '%" + (monitorDto.getResv2()) + "%'"; } //备注字段3 if(StringUtils.isNotBlank(monitorDto.getResv3())){ sql += " AND RESV3 LIKE '%" + (monitorDto.getResv3()) + "%'"; } //id倒序 sql += " ORDER BY ID DESC"; //分页 if(monitorDto.getActivePage() > 0 && monitorDto.getPageSize() > 0){ sql += " LIMIT " + (monitorDto.getActivePage()-1)*monitorDto.getPageSize() + "," + monitorDto.getPageSize(); } return sql; } /** * 查询交易监控总数 * @param monitorDto * @return */ public String countTransMonitor(MonitorDto monitorDto){ String sql = "SELECT COUNT(1) FROM TRANS_MONITOR WHERE 1=1"; //方法路径 if(StringUtils.isNotBlank(monitorDto.getMethodRoute())){ sql += " AND METHOD_ROUTE = '" + (monitorDto.getMethodRoute()) + "'"; } //方法类型 if(StringUtils.isNotBlank(monitorDto.getMethodType())){ sql += " AND METHOD_TYPE = '" + (monitorDto.getMethodType()) + "'"; } //外部系统 if(StringUtils.isNotBlank(monitorDto.getOuterSystem())){ sql += " AND OUTER_SYSTEM = '" + (monitorDto.getOuterSystem()) + "'"; } //是否异常发生 if(monitorDto.getIsException() >= 0){ sql += " AND IS_EXCEPTION = " + (monitorDto.getIsException()); } //开始时间 if(StringUtils.isNotBlank(monitorDto.getBeginTime())){ sql += " AND BEGIN_TIME >= '" + (monitorDto.getBeginTime()) + "'"; } //结束时间 if(StringUtils.isNotBlank(monitorDto.getEndTime())){ sql += " AND END_TIME <= '" + (monitorDto.getEndTime()) + "'"; } //最小耗时(毫秒)(>=) if(monitorDto.getBeginUsedTime() >= 0){ sql += " AND USED_TIME >= " + (monitorDto.getBeginUsedTime()); } //最大耗时(毫秒)(<=) if(monitorDto.getEndUsedTime() >= 0){ sql += " AND USED_TIME <= " + (monitorDto.getEndUsedTime()); } //机器ip if(StringUtils.isNotBlank(monitorDto.getIp())){ sql += " AND IP = '" + (monitorDto.getIp()) + "'"; } //备注字段1 if(StringUtils.isNotBlank(monitorDto.getResv1())){ sql += " AND RESV1 LIKE '%" + (monitorDto.getResv1()) + "%'"; } //备注字段2 if(StringUtils.isNotBlank(monitorDto.getResv2())){ sql += " AND RESV2 LIKE '%" + (monitorDto.getResv2()) + "%'"; } //备注字段3 if(StringUtils.isNotBlank(monitorDto.getResv3())){ sql += " AND RESV3 LIKE '%" + (monitorDto.getResv3()) + "%'"; } return sql; } /** * 查询平均耗时 * @param monitorDto * @return */ public String queryAvgUsedTime(MonitorDto monitorDto){ String sql = "SELECT AVG(USED_TIME) FROM TRANS_MONITOR WHERE 1=1"; //方法路径 if(StringUtils.isNotBlank(monitorDto.getMethodRoute())){ sql += " AND METHOD_ROUTE = '" + (monitorDto.getMethodRoute()) + "'"; } //方法类型 if(StringUtils.isNotBlank(monitorDto.getMethodType())){ sql += " AND METHOD_TYPE = '" + (monitorDto.getMethodType()) + "'"; } //外部系统 if(StringUtils.isNotBlank(monitorDto.getOuterSystem())){ sql += " AND OUTER_SYSTEM = '" + (monitorDto.getOuterSystem()) + "'"; } //是否异常发生 if(monitorDto.getIsException() >= 0){ sql += " AND IS_EXCEPTION = " + (monitorDto.getIsException()); } //开始时间 if(StringUtils.isNotBlank(monitorDto.getBeginTime())){ sql += " AND BEGIN_TIME >= '" + (monitorDto.getBeginTime()) + "'"; } //结束时间 if(StringUtils.isNotBlank(monitorDto.getEndTime())){ sql += " AND END_TIME <= '" + (monitorDto.getEndTime()) + "'"; } //最小耗时(毫秒)(>=) if(monitorDto.getBeginUsedTime() >= 0){ sql += " AND USED_TIME >= " + (monitorDto.getBeginUsedTime()); } //最大耗时(毫秒)(<=) if(monitorDto.getEndUsedTime() >= 0){ sql += " AND USED_TIME <= " + (monitorDto.getEndUsedTime()); } //机器ip if(StringUtils.isNotBlank(monitorDto.getIp())){ sql += " AND IP = '" + (monitorDto.getIp()) + "'"; } //备注字段1 if(StringUtils.isNotBlank(monitorDto.getResv1())){ sql += " AND RESV1 LIKE '%" + (monitorDto.getResv1()) + "%'"; } //备注字段2 if(StringUtils.isNotBlank(monitorDto.getResv2())){ sql += " AND RESV2 LIKE '%" + (monitorDto.getResv2()) + "%'"; } //备注字段3 if(StringUtils.isNotBlank(monitorDto.getResv3())){ sql += " AND RESV3 LIKE '%" + (monitorDto.getResv3()) + "%'"; } return sql; } }
record_app下的
package com.gxx.record_app.dto; import java.util.List; import com.gxx.record_app.base.vo.TransMonitorWithBLOBs; /** * <dl> * <dt><b>Title:</b></dt> * <dd> * 交易监控对象 * </dd> * <dt><b>Description:</b></dt> * <dd> * <p>none * </dd> * </dl> * * @author Gxx * @version 1.0, 2017年6月22日 * @since config_center */ public class MonitorDto extends BaseDto { private String methodRoute;//方法路径 private String methodType;//方法类型 private String outerSystem;//外部系统 private int isException;//是否异常发生 private String beginTime;//开始时间 private String endTime;//结束时间 private int beginUsedTime;//最小耗时(毫秒)(>=) private int endUsedTime;//最大耗时(毫秒)(<=) private String ip;//机器ip private String resv1;//备注字段1 private String resv2;//备注字段2 private String resv3;//备注字段3 private int pageSize;//每页个数 private int activePage;//当前页数 private boolean isSuccess;//是否成功 private String message;//返回信息 private List<TransMonitorWithBLOBs> list;//数据集合 private long totalCount;//总条数 private long totalPage;//总页数 private double avgUsedTime;//平均耗时 private long tps;//每秒钟支持并发数 public String getMethodRoute() { return methodRoute; } public void setMethodRoute(String methodRoute) { this.methodRoute = methodRoute; } public String getMethodType() { return methodType; } public void setMethodType(String methodType) { this.methodType = methodType; } public String getOuterSystem() { return outerSystem; } public void setOuterSystem(String outerSystem) { this.outerSystem = outerSystem; } public int getIsException() { return isException; } public void setIsException(int isException) { this.isException = isException; } public String getBeginTime() { return beginTime; } public void setBeginTime(String beginTime) { this.beginTime = beginTime; } public String getEndTime() { return endTime; } public void setEndTime(String endTime) { this.endTime = endTime; } public int getBeginUsedTime() { return beginUsedTime; } public void setBeginUsedTime(int beginUsedTime) { this.beginUsedTime = beginUsedTime; } public int getEndUsedTime() { return endUsedTime; } public void setEndUsedTime(int endUsedTime) { this.endUsedTime = endUsedTime; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public String getResv1() { return resv1; } public void setResv1(String resv1) { this.resv1 = resv1; } public String getResv2() { return resv2; } public void setResv2(String resv2) { this.resv2 = resv2; } public String getResv3() { return resv3; } public void setResv3(String resv3) { this.resv3 = resv3; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public int getActivePage() { return activePage; } public void setActivePage(int activePage) { this.activePage = activePage; } public boolean isSuccess() { return isSuccess; } public void setSuccess(boolean isSuccess) { this.isSuccess = isSuccess; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public List<TransMonitorWithBLOBs> getList() { return list; } public void setList(List<TransMonitorWithBLOBs> list) { this.list = list; } public long getTotalCount() { return totalCount; } public void setTotalCount(long totalCount) { this.totalCount = totalCount; } public long getTotalPage() { return totalPage; } public void setTotalPage(long totalPage) { this.totalPage = totalPage; } public double getAvgUsedTime() { return avgUsedTime; } public void setAvgUsedTime(double avgUsedTime) { this.avgUsedTime = avgUsedTime; } public long getTps() { return tps; } public void setTps(long tps) { this.tps = tps; } }
config_center下的
package com.gxx.config_center.dto; /** * <dl> * <dt><b>Title:</b></dt> * <dd> * 交易监控对象 * </dd> * <dt><b>Description:</b></dt> * <dd> * <p>none * </dd> * </dl> * * @author Gxx * @version 1.0, 2017年6月22日 * @since config_center */ public class MonitorDto extends BaseDto { private String methodRoute;//方法路径 private String methodType;//方法类型 private String outerSystem;//外部系统 private String isException;//是否异常发生 private String beginTime;//开始时间 private String endTime;//结束时间 private String beginUsedTime;//最小耗时(毫秒)(>=) private String endUsedTime;//最大耗时(毫秒)(<=) private String ip;//机器ip private String resv1;//备注字段1 private String resv2;//备注字段2 private String resv3;//备注字段3 private int pageSize;//每页个数 private int activePage;//当前页数 public String getMethodRoute() { return methodRoute; } public void setMethodRoute(String methodRoute) { this.methodRoute = methodRoute; } public String getMethodType() { return methodType; } public void setMethodType(String methodType) { this.methodType = methodType; } public String getOuterSystem() { return outerSystem; } public void setOuterSystem(String outerSystem) { this.outerSystem = outerSystem; } public String getIsException() { return isException; } public void setIsException(String isException) { this.isException = isException; } public String getBeginTime() { return beginTime; } public void setBeginTime(String beginTime) { this.beginTime = beginTime; } public String getEndTime() { return endTime; } public void setEndTime(String endTime) { this.endTime = endTime; } public String getBeginUsedTime() { return beginUsedTime; } public void setBeginUsedTime(String beginUsedTime) { this.beginUsedTime = beginUsedTime; } public String getEndUsedTime() { return endUsedTime; } public void setEndUsedTime(String endUsedTime) { this.endUsedTime = endUsedTime; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public String getResv1() { return resv1; } public void setResv1(String resv1) { this.resv1 = resv1; } public String getResv2() { return resv2; } public void setResv2(String resv2) { this.resv2 = resv2; } public String getResv3() { return resv3; } public void setResv3(String resv3) { this.resv3 = resv3; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public int getActivePage() { return activePage; } public void setActivePage(int activePage) { this.activePage = activePage; } }