Spring Boot中Aspect实现切面(以记录日志为例)
切面Aspect是Spring的一大优势。面向切面编程往往让我们的开发更加低耦合,也大大减少了代码量,同时让我们更专注于业务模块的开发,把那些与业务无关的东西提取出去,便于后期的维护和迭代。
Maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
日志实体类和Service
@Data
public class SysLog {
private String className;
private String methodName;
private String[] methodParams;
private Object[] paramValues;
private Long execTime;
private String remark;
private String createDate;
}
@Slf4j
@Service
public class SysLogService {
public void save(SysLog sysLog) {
log.info(JSON.toJSONString(sysLog));
}
}
定义日志注解
记录日志使用注解的形式,切点表达式形式无需定义
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WithSysLog {
String value() default "";
}
声明切面,完成日志记录
这里需要对AOP有一定的了解。起码知道切点表达式、环绕通知、前置通知、后置通知等
支持注解形式和切点表达式形式
/**
* 系统日志切面
*
* @Author: yezhou
* @Date: 2019/5/9 10:40
* @Version 1.0
*/
@Slf4j
@Aspect //使用@Aspect注解声明一个切面
@Component
public class SysLogAspect {
@Autowired
private SysLogService sysLogService;
/**
* 使用注解的形式
* 也可以通过切点表达式直接指定需要拦截的package, 需要拦截的class 以及 method
* 切点表达式: execution(...)
*/
//@Pointcut("@annotation(me.yezhou.springdemo.annotation.WithSysLog)") //注解形式
@Pointcut("execution(public * me.yezhou.springdemo.controller.SysLogController.*(..))") //切点表达式形式
public void logPointCut() {
log.info("SysLogAspect.logPointCut");
}
/**
* 环绕通知 @Around, 当然也可以使用 @Before (前置通知) @After (后置通知)
*
* @param point
* @return
* @throws Throwable
*/
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
log.info("SysLogAspect.around");
long beginTime = System.currentTimeMillis();
Object result = point.proceed();
long time = System.currentTimeMillis() - beginTime;
try {
saveLog(point, time);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 保存日志
*
* @param joinPoint
* @param time
*/
private void saveLog(ProceedingJoinPoint joinPoint, long time) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
SysLog sysLog = new SysLog();
sysLog.setExecTime(time);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
sysLog.setCreateDate(dateFormat.format(new Date()));
WithSysLog withSysLog = method.getAnnotation(WithSysLog.class);
if (withSysLog != null) {
//注解上的描述
sysLog.setRemark(withSysLog.value());
}
//请求的 类名、方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
String[] parameterNames = signature.getParameterNames();
sysLog.setClassName(className);
sysLog.setMethodName(methodName);
sysLog.setMethodParams(parameterNames);
//请求的参数
Object[] args = joinPoint.getArgs();
sysLog.setParamValues(args);
sysLogService.save(sysLog);
}
}
测试Controller
@RestController
public class SysLogController {
//@WithSysLog("测试") //注解形式
@GetMapping("/test") //切点表达式形式
public String test(@RequestParam("name") String name) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
return e.getMessage();
}
return name;
}
}
访问:http://127.0.0.1:8080/test?name=Joe.Ye
返回结果:
SysLogAspect.around
{"className":"me.yezhou.springdemo.controller.SysLogController","createDate":"2019-05-09 11:30:01","execTime":1000,"methodName":"test","methodParams":["name"],"paramValues":["Joe.Ye"],"remark":"测试"}
至此,我们成功实现了使用Aspect实现切面记录日志。
版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/03/11/aspect-implementation-in-spring-boot-and-using-logging-as-an-example/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。
THE END
0
二维码
打赏
海报
Spring Boot中Aspect实现切面(以记录日志为例)
切面Aspect是Spring的一大优势。面向切面编程往往让我们的开发更加低耦合,也大大减少了代码量,同时让我们更专注于业务模块的开发,把那些与业务无关的东西提……
文章目录
关闭
共有 0 条评论