3.10 统一记录日志

93 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第18天,点击查看活动详情

3.10 统一记录日志

image-20220719154250916

这里日志的意思是平时不发生异常的话也记录日志。

image-20220719154720536

image-20220719155449555

image-20220719162102990

image-20220719162535840

切入点表达式:

# 切入点表达式
    切入点表达式
    execution(返回值 包.类名.方法名(参数类型))
    execution(返回值 包.类名.*(..))
        *代表类中所有方法  ..代表参数任意
        aop.*.*(..) 代表aop包下的所有类的所有方法在执行时都要加前置通知
    execution:
        第一个代表方法的返回值,*代表不关心方法的返回值
        之后空格写包名(包.类.方法名),切类中所有方法且不关心方法的参数写*(..)

以前写的关于AOP的博客:

SpringBoot中AOP切面编程和文件上传

Spring中AOP编程本质(动态代理机制)以及前置通知的开发

SpringAOP使用示例

Spring AOP 的示例

下面写一个示例体会一下 Spring Aop 的语法

写完这个示例之后将类的两个注解注释掉,防止影响记录日志时的数据观看


@Component
@Aspect
public class AlphaAspect {

    @Pointcut("execution(* com.nowcoder.community.service.*.*(..))")
    public void pointcut() {

    }
    // 前置通知
    @Before("pointcut()")
    public void before() {
        System.out.println("before");
    }
    // 后置通知
    @After("pointcut()")
    public void after() {
        System.out.println("after");
    }
    // 如果想在有了返回值以后处理一下逻辑可以使用这个注解(相当于后置通知的增强版)
    @AfterReturning("pointcut()")
    public void afterRetuning() {
        System.out.println("afterRetuning");
    }
    // 在抛异常之后置入代码
    @AfterThrowing("pointcut()")
    public void afterThrowing() {
        System.out.println("afterThrowing");
    }
    // 环绕通知
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("around before");
        Object obj = joinPoint.proceed();    // 调目标组件的方法
        System.out.println("around after");
        return obj;                         // 目标组件方法的返回值
    }
}

/*
around before
before
2022-07-19 17:00:43,555 DEBUG [http-nio-8080-exec-1] c.n.c.d.L.selectByTicket [BaseJdbcLogger.java:143] ==>  Preparing: select id, user_id, ticket, status, expired from login_ticket where ticket = ? 
2022-07-19 17:00:43,555 DEBUG [http-nio-8080-exec-1] c.n.c.d.L.selectByTicket [BaseJdbcLogger.java:143] ==> Parameters: e626e90074e84641993380de204f177e(String)
2022-07-19 17:00:43,557 DEBUG [http-nio-8080-exec-1] c.n.c.d.L.selectByTicket [BaseJdbcLogger.java:143] <==      Total: 1
afterRetuning
after
around after
*/

image-20220719170818303

对所有业务组件记录日志

@Component
@Aspect
public class ServiceLogAspect {

    // 日志
    private static final Logger logger = LoggerFactory.getLogger(ServiceLogAspect.class);
    // 切点
    @Pointcut("execution(* com.nowcoder.community.service.*.*(..))")
    public void pointcut() {
    }
    // 使用前置通知记录日志
    @Before("pointcut()")
    public void before(JoinPoint joinPoint) {    // 这个参数是为了知道访问了哪个类的哪个方法
        // 用户[1.2.3.4,ip地址],在[xx时间],访问了[com.nowcoder.community.service.xxx()].
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        // 得到request对象
        HttpServletRequest request = attributes.getRequest();
        String ip = request.getRemoteHost();        // 利用request得到ip地址
        String now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); // 时间
        String target = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
        logger.info(String.format("用户[%s],在[%s],访问了[%s].", ip, now, target));
    }

}

访问首页:

image-20220719173449969

经测试,统一记录日志功能完成