简介
主要记录一下项目中的日志拦截和异常拦截,由于之前公司项目为单体项目,所使用的日志拦截较为简单,只是用拦截器进行前后对日志的拦截,异常拦截直接使用@ExceptionHandler,而现在公司接口使用的dubbo协议通信,一个网关将http协议转为dubbo协议调用,属于分布式项目,日志记录我觉得有点意思,是我之前所没有想到的。
主要流程
前提是公司所有的请求参数都封装到一个对象中,然后该类继承自一个DefaultRequest类,该类中有统一的封装参数,如requestId等等。
首先请求到了网关,网关分派一个唯一requestId存储到请求对象中,然后转发到对应的服务中,如果对应的服务继续调用其他的服务则继续将该requestId传递下去,这样通过requestId就可以找到所有的相关日志了。
而在日志的拦截上使用的是aop环绕通知拦截的,顺带把异常信息也拦截了,但是大家注意只要拦截接口层,不要拦截业务层,否则声明式事务将会失效
aop代码
这里我就不贴公司代码了,我自己模拟一下
1@Component
2@Aspect
3@Slf4j
4public class LogAop {
5
6 @Pointcut("execution(public * com.xiaoguo.web.controller.*.*(..))")
7 public void point() {
8 }
9
10
11 @Around("point()")
12 public Object doAroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
13 long startTime = System.currentTimeMillis();
14 //对参数进行分析
15 Object firstArg = proceedingJoinPoint.getArgs()[0];
16 String requestId = "test";
17 if (firstArg instanceof DefaultRequest) {
18 requestId = ((DefaultRequest) firstArg).getRequestId();
19 }
20 log.info("{}请求开始: {}", requestId, startTime);
21 Object obj = null;
22 try {
23 obj = proceedingJoinPoint.proceed();
24 }
25 //自定义异常拦截(这里用 RuntimeException 暂时代替一下明白意思就行)
26 catch (RuntimeException r) {
27 long endTime = System.currentTimeMillis();
28 log.info("{}xxx{}: {}", requestId, r.getMessage(), endTime - startTime, r);
29 return r.getMessage();
30 }
31 //未知异常拦截
32 catch (Exception e) {
33 long endTime = System.currentTimeMillis();
34 log.info("{}异常结束: {}", requestId, endTime - startTime, e);
35 return "fail";
36 }
37 long endTime = System.currentTimeMillis();
38 log.info("{}请求结束: {}", requestId, endTime - startTime);
39 return obj;
40 }
41
42 @Data
43 class DefaultRequest {
44 private String requestId;
45 }
46
47}