使用AOP以及自定义注解实现业务日志的收集
Posted 吹灭读书灯 一身都是月
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用AOP以及自定义注解实现业务日志的收集相关的知识,希望对你有一定的参考价值。
直接上代码
自定义注解:MyLog
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
String value() default ""; //value值是说明,会被记录到数据库里面
}
自定义日志的实体类SysLog
@Data
@TableName("sys_log")
public class SysLog {
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
@TableField(value = "visit_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date visitTime;
@TableField(value = "execution_time")
private Long executionTime;
@TableField(value = "email")
private String email;
private String ip;
private String url;
private String method;
/**
* 日志标题
*/
private String title;
private String params;
/**
* 请求类型
*/
private String type;
}
编写的切面类:LogAspect
@Aspect
@Order(5)
@Component
public class LogAspect {
private final Logger logger = LoggerFactory.getLogger(LogAspect.class);
@Autowired
SysLogService sysLogService;
//可以直接注入HttpServletRequest 来获取当前的请求
@Autowired
HttpServletRequest request;
private Date visitTime;
private Class<?> clazz;
private Method method;
private String myLogValue;
@Pointcut("@annotation(com.example.controller.sys.MyLog)")
public void pointcut() {
}
/**
* 前置通知,在Controller层操作前拦截
*
* @param joinPoint 切入点
*/
@Before("pointcut()")
public void doBefore(JoinPoint joinPoint) throws NoSuchMethodException {
// 获取当前调用时间
visitTime = new Date();
clazz = joinPoint.getTarget().getClass();
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
if (methodSignature == null || methodSignature.getMethod().getAnnotation(MyLog.class) == null) {
return;
}
MyLog myLog = methodSignature.getMethod().getAnnotation(MyLog.class);
myLogValue = myLog.value();
String methodName = methodSignature.getName();
Object[] args = joinPoint.getArgs();
//获取具体执行的方法的Method对象
if (args == null || args.length == 0) {
//只能获取无参数的方法
this.method = clazz.getMethod(methodName);
} else {
Class<?>[] classArgs = new Class<?>[args.length];
for (int i = 0; i < args.length; i++) {
classArgs[i] = args[i].getClass();
}
this.method = clazz.getMethod(methodName, classArgs);
}
}
@After("pointcut()")
public void doAfter(JoinPoint jp) throws Exception {
long time = System.currentTimeMillis() - visitTime.getTime();
String url = "";
/*获取url*/
if (clazz != null && method != null && clazz != LogAspect.class) {
Subject currentUser = SecurityUtils.getSubject();
String username = (String) currentUser.getPrincipal();
SysLog sysLog = new SysLog();
sysLog.setVisitTime(visitTime);
sysLog.setEmail(username);
sysLog.setUrl(request.getRequestURL().toString());
sysLog.setExecutionTime(System.currentTimeMillis() - visitTime.getTime());
//什么类的什么方法
sysLog.setMethod("[类名]:" + clazz.
getName() + ", [方法名]:" + method.getName());
sysLog.setTitle(myLogValue);
Object[] args = jp.getArgs();
if (args == null || args.length == 0) {
sysLog.setParams("无参数");
}
//设置不能超过500长度,防止插入数据库抛异常
String s = Arrays.toString(args);
if (s.length() > 485) {
s = s.substring(0, 480);
}
sysLog.setParams(s);
sysLog.setType(request.getMethod());
sysLog.setIp(request.getRemoteAddr());
System.out.println(sysLog);
//调用Service完成操作,调用dao将sysLog insert数据库
sysLogService.save(sysLog);
}
}
}
ServiceImpl
类:
@Service
public class SysLogServiceImpl implements SysLogService {
@Autowired
SysLogMapper sysLogMapper;
@Override
public void save(SysLog sysLog) {
sysLogMapper.insert(sysLog);
}
/**
* 这里就是一个简单的分页查询了。PageResultDTO是自定义的分页返回类
*/
@Override
public PageResultDTO<SysLog> pageSysLogs(Long pageNum, Long pageSize) {
Page<SysLog> page = new Page<>(pageNum, pageSize);
Page<SysLog> sysLogPage = sysLogMapper.selectPage(page, null);
return PageUtil.convertToPageResult(sysLogPage);
}
}
使用时,只要把@MyLog
注解标在自己想要记录日志的方法上,就可以了。
例如:
@MyLog("测试aaa接口的日志输出")
@PostMapping("/aaa")
public RetJson<Object> aaa(@RequestBody User user){
return RetJson.success(user);
}
不过,当我使用AOP之后,发现我代码中使用了Shiro的controller全都404了,很奇怪,后面看别人的博客,改了配置才好了
在ShiroConfig
中加入配置:
@Bean
public static DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setUsePrefix(true);
return defaultAdvisorAutoProxyCreator;
}
同时我也在application.yml
中加入了配置:
aop:
auto: true
proxy-target-class: true
以上是关于使用AOP以及自定义注解实现业务日志的收集的主要内容,如果未能解决你的问题,请参考以下文章
SpringCloud Alibaba微服务实战三十一 - 业务日志组件