目录
前言
使用AOP + 自定义注解,实现日志管理系统,特点是灵活方便。该模块比较简单,直接上Demo。
自定义注解相关知识可参考阅读:https://blog.csdn.net/u013045971/article/details/53433874
AOP相关知识可参考阅读:https://blog.csdn.net/qq_36095679/article/details/91979400
1、导入依赖
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.1.5.RELEASE</version>
</dependency>
2、自定义注解Log
package com.demo.aopdemo.commom;
import java.lang.annotation.*;
/**
* 自定义:日志记录注解
* @author MouFangCai
* @date 2019/9/26 11:54
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
/**
* 操作者
* @return
*/
String operator();
/**
* 操作信息
* @return
*/
String operation();
}
3、切面LogAspect(使用自定义注解动态传参)
package com.demo.aopdemo.aspect;
import com.demo.aopdemo.commom.Log;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
/**
* @author MouFangCai
* @date 2019/9/26 12:47
*/
@Aspect
// 如果有多个切面配置,可设置切面起作用的顺序
@Order(1)
// 必须交给spring管理
@Component
public class LogAspect {
@Autowired
HttpServletRequest request;
// 用于解析自定义注解中的动态参数
ExpressionParser parser = new SpelExpressionParser();
// 该通知类型为后置通知
@AfterReturning("@annotation(log)")
public void after(JoinPoint point, Log log){
// 访问的方法名
String methodName = point.getSignature().getName();
// 将该方法的参数名和参数值设置到context中,用于解析自定义注解中的动态参数
Object[] args = point.getArgs();
String[] parameterNames = ((MethodSignature) point.getSignature()).getParameterNames();
EvaluationContext context = new StandardEvaluationContext();
for (int len = 0; len < parameterNames.length; len++) {
context.setVariable(parameterNames[len], args[len]);
}
// 得到自定义注解中的动态参数
String operator = parser.parseExpression(log.operator()).getValue(context, String.class);
String requestURI = request.getRequestURI();
System.out.println("LogAspect生成的日志:" +
"\n uri--:" + requestURI +
"\n method--:" + methodName);
System.out.println("LogAspect生成的日志:\n" +
" operator--:" + operator +
"\n operation--:" + log.operation());
}
}
此次使用自定义注解:
4、AopTestController
package com.demo.aopdemo.controller;
import com.demo.aopdemo.commom.Log;
import org.springframework.web.bind.annotation.*;
/**
* @author MouFangCai
* @date 2019/9/26 11:52
*/
@RestController
@RequestMapping("aop")
public class AopTestController {
// operator使用动态传参
@PostMapping("addUser")
@Log(operator = "#operator",operation = "添加了用户")
public boolean addUser(@RequestParam("operator") String operator){
System.out.println("这是addUser接口参数:");
System.out.println("operator = " + operator);
System.out.println();
return true;
}
@GetMapping("testUrl")
@Log(operator = "#operator",operation = "测试了testUrl接口")
public boolean testMethod(@RequestParam("operator") String operator){
System.out.println("这是testUrl接口:");
System.out.println("operator = " + operator);
System.out.println();
return true;
}
}
5、功能测试
localhost:8080/aop/addUser?operator=operator
这是addUser接口参数:
operator = operator
LogAspect生成的日志:
uri--:/aop/addUser
method--:addUser
LogAspect生成的日志:
operator--:operator
operation--:添加了用户
localhost:8080/aop/testUrl?operator=操作者
这是testUrl接口:
operator = 操作者
LogAspect生成的日志:
uri--:/aop/testUrl
method--:testMethod
LogAspect生成的日志:
operator--:操作者
operation--:测试了testUrl接口