牛客网后端项目实战(二十四):统一记录日志

https://blog.csdn.net/weixin_42700635/article/details/106629583
统一记录日志,可能会想到封装一个记日志的组件,在每个业务中调用,但是这样实现不利于维护,这里就需要AOP技术。

Spring AOP语法

package com.nowcoder.community.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class AlphaAspect {

    @Pointcut("execution(* com.nowcoder.community.service.*.*(..))") // 意思连接点是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;
    }

}

1、使用@Component和@Aspect注解修饰类,表明是切面Bean
@Component注解表明一个类会作为组件类,并告知Spring要为这个类创建bean。

2、使用@Pointcut定义连接点,execution固定关键字,*表示任何方法返回值都行,com.neu.langsam.community.service.*表示service包下所有类,再.*表示所有方法,(…)表示所有的参数都要处理,也可以指定明确的方法

3、五种注解实现五种通知,前四个实现大同小异,around表示前后都执行,实现方法就是传入joinPoint,调用joinPoint的proceed方法,也就是业务方法,在调用前后写需要织入的逻辑。

统一处理日志

//@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],在[xxx],访问了[com.nowcoder.community.service.xxx()].
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) {
            return;
        }  // 1. 获取request
        HttpServletRequest request = attributes.getRequest();
        String ip = request.getRemoteHost();  // 2. 获取IP
        String now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());  // 3. 获取当前日期,并进行格式化
        // 4. 获取访问的类与对象
        // joinPoint 是要织入的方法,所以通过它可以获取所在的类,以及方法名
        String target = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
        logger.info(String.format("用户[%s],在[%s],访问了[%s].", ip, now, target));
    }
}

你可能感兴趣的:(Java学习)