SpringBoot使用SpringAOP實現日志審計等功能


項目當中需要對用戶操作菜單的行為記錄日志,用SpringAOP寫了個大概實現,切點是采用注解的方式,用包名的方式雖然也可以達到相同的效果,但是不如注解方式靈活方便。

不多說,直接上代碼,此處只是簡單寫寫實現原理。

 

工程目錄:

 

pom.xml引入以下依賴:

<!-- 熱部署模塊 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
    <optional>true</optional> <!-- 這個需要為 true 熱部署才有效 -->
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- spring-boot aop依賴配置引入 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

 

 注解:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Action {
    String description() default "no description";
}

 

Controller類:

/**
 * @auther: gaopeng
 */
@RestController
public class AspectController {

    /**
     * 走切面
     * @return
     */
    @GetMapping("/test")
    @Action(description = "執行了test操作菜單")
    public String test(){
        return "method return";
    }

    /**
     * 不走切面
     */
    @GetMapping("/test1")
    private void test1(){
    }

    /**
     * 走切面,拋異常
     */
    @GetMapping("/throws")
    @Action(description = "執行了throws菜單但是拋了異常")
    public void throwsException(){
        throw new RuntimeException();
    }
}

 

切面類:

/**
 * @auther: gaopeng
 */
@Aspect
@Component
public class TestAspect {

    /**
     * 切入點
     */
    // 此處的切點是注解的方式,也可以用包名的方式達到相同的效果
    //@Pointcut("execution(public * com.gaopeng.springboot.mytest.controller.*.*(..))")
    @Pointcut("@annotation(com.gaopeng.springboot.mytest.annotation.Action)")
    public void execute(){
    }

    /**
     * 前置通知
     * @param joinPoint
     */
    @Before(value ="execute()")
    public void Before(JoinPoint joinPoint) {
        System.out.println("執行方法之前");
    }

    /**
     * 環繞通知
     * @param proceedingJoinPoint
     * @return
     */
    @Around(value ="execute()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) {
        System.out.println("環繞通知開始");
        try {
            System.out.println("執行方法:" + proceedingJoinPoint.getSignature().getName());
            
            MethodSignature signature =(MethodSignature) proceedingJoinPoint.getSignature();
            Action action = signature.getMethod().getAnnotation(Action.class);
            
            System.out.println("菜單="+action.description());
            
            Object object =  proceedingJoinPoint.proceed();
            System.out.println("環繞通知結束,方法返回:" + object);
            return object;
        } catch (Throwable e) {
            System.out.println("執行方法異常:" + e.getClass().getName());
            return null;
        }
    }

    /**
     * 后置通知
     * @param joinPoint
     */
    @After(value ="execute()")
    public void After(JoinPoint joinPoint) {
        System.out.println("執行方法之后");
    }

    /**
     * 后置通知,帶返回值
     * @param obj
     */
    @AfterReturning(pointcut = "execute()",returning = "obj")
    public void AfterReturning(Object obj) {
        System.out.println("執行方法之后獲取返回值:"+obj);
    }

    /**
     * 后置通知,異常時執行
     * @param e
     */
    @AfterThrowing(throwing = "e",pointcut = "execute()")
    public void doAfterThrowing(Exception e) {
        System.out.println("執行方法異常:"+e.getClass().getName());
    }
}

 

運行結果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM