版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zc_ad/article/details/83306123
来现在公司的缘故,公司大佬使用的AOP比较多,本来在校时候对AOP只是一知半解,在现在公司呆了半年,用到了各种拦截器,对AOP有了许多新的认识。此处用统一日志处理就是使用的是Spring AOP实现的。
定义统一日志表,用在将所有请求都记录在表中,方便以后查阅。
CREATE TABLE `t_union_log` (
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
`dev_mac` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '设备MAC',
`user_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户身份',
`level` int(11) NULL DEFAULT 0 COMMENT '日志级别,0-最高级别',
`method` varchar(25) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '操作方式',
`remote_host` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '操作IP地址',
`request_uri` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '请求URI',
`user_agent` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户代理',
`module_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '模块名称',
`param` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '请求参数',
`result` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '结果',
`spent` bigint(20) NULL DEFAULT NULL COMMENT '耗费时间-毫秒',
`ctime` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`) USING BTREE
)
定义实体类与DAO,此处使用的是mybatis-plus,使用其他的也可以,自行选择,这些都不重要,重要的是后面的aop拦截器。
@TableName("t_union_log")
public class UnionLogEntity {
@TableId(value = "id",type = IdType.AUTO)
private Long id;
private String devMac;
private String userId;
private Integer level;
private String method;
private String remoteHost;
private String requestUri;
private String userAgent;
private String moduleName;
private String param;
private String result;
private Long spent;
private Date ctime;
Getter...
Setter...
}
@Mapper
public interface UnionLogMapper extends BaseMapper<UnionLogEntity>{
}
实现统一日志的拦截。原理很简单,只要懂得一些AOP方面的知识,看代码很容易看的懂。特别注意的是,在不需要拦截的URI,一定不能进行日志打印(如:文件下载接口,会报内存溢出错误,以前写文件下载的时候遇到,再次铭记)
/**统一日志处理*/
@Aspect
@Component
public class GlobalLogAspect {
private Logger logger = LoggerFactory.getLogger(GlobalLogAspect.class);
private static final String POINTCUT = "execution(* com.xichuan.wechat.*.controller.*.*(..)) ";
private static final ThreadLocal<Map<Object,Object>> paramLocal = new ThreadLocal<>();
private static final ThreadLocal<Map<Object,Object>> resultsLocal = new ThreadLocal<>();
private static final ThreadLocal<Long> start = new ThreadLocal<>();
private static final ThreadLocal<Long> end = new ThreadLocal<>();
private static final ThreadLocal<HttpServletRequest> httpRequest = new ThreadLocal<>();
@Autowired
UnionLogMapper unionLogMapper;
@Before(POINTCUT)
public void beforeAspectHandler(){
start.set(System.currentTimeMillis());
}
@After(POINTCUT)
public void afterAspectHandler(){
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String uri = request.getRequestURI();
if(uri.equals("")){ /**不进行日志拦截的URI*/
logger.info("global log Aspect untreated uri:"+uri);
}else{
end.set(System.currentTimeMillis());
this.tracer();
}
}
@Around(POINTCUT)
public Object aroundAspectHandler(ProceedingJoinPoint joinPoint)throws Throwable{
Object[] param = joinPoint.getArgs();
Map<Object,Object> argMap = new LinkedHashMap<>();
argMap.put("params",param);
paramLocal.set(argMap);
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
httpRequest.set(request);
Object result = joinPoint.proceed();
Map<Object,Object> resMap = new LinkedHashMap<>();
resMap.put("results",result);
resultsLocal.set(resMap);
return result;
}
public void tracer(){
try {
HttpServletRequest request = httpRequest.get();
Gson gson = new Gson();
logger.info("Request PATH: {}, Time: {}, Consumed: {}ms, Param: {}, Result: {}\n",
"["+request.getRequestURI()+"]",
new SimpleDateFormat("yyyy-MM-dd HH:mm:s").format(start.get()),
(end.get()-start.get()),
gson.toJson(paramLocal.get()),
gson.toJson(resultsLocal.get()));
UnionLogEntity unionLog = new UnionLogEntity();
unionLog.setCtime(new Date());
unionLog.setMethod(request.getMethod());
unionLog.setRequestUri(request.getRequestURI());
unionLog.setRemoteHost(request.getRemoteHost());
unionLog.setUserAgent(request.getHeader("User-Agent"));
unionLog.setParam(gson.toJson(paramLocal.get()));
unionLog.setResult(gson.toJson(resultsLocal.get()));
unionLog.setSpent(end.get()-start.get());
unionLog.setUserId(request.getHeader(("account_id")));
unionLog.setDevMac(request.getHeader(("dev_mac")));
unionLog.setModuleName("cmd");
unionLogMapper.insert(unionLog);
}finally {
httpRequest.remove();
paramLocal.remove();
resultsLocal.remove();
start.remove();
end.remove();
}
}
}