Spring的两大核心是控制反转(Ioc)和面向切面编程(Aop);今天就聊聊,在以往的项目中是如果通过Aop来实现系统日志的,并将重要的记录结果进行入库。

日志实体类:

/**
* 日志记录类
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Alias("logRecord")
public class LogRecord {
private Long id;// 主键
private String operator;//操作者
private String operateDesc;//操作描述
private Date operateDate;//操作日期
private String result;//操作结果
private String remark;//日志备注
}

说明:日志实体对应的xml文件,Dao,Service,ServiceImpl以及Controller这里就不再贴代码了。

日志记录表结构:

CREATE TABLE `logrecord` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`operator` varchar(255) DEFAULT NULL COMMENT '操作人',
`operateDesc` varchar(255) DEFAULT NULL COMMENT '操作描述',
`operateDate` datetime DEFAULT NULL COMMENT '操作时间',
`result` varchar(255) DEFAULT NULL COMMENT '操作结果',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

日志注解:

/**
* 日志注解
*/
@Target(ElementType.METHOD)//注解使用在方法上
@Retention(RetentionPolicy.RUNTIME)//注解运行有效
public @interface LogAnno {
String operateDesc();//操作描述
}

提示:日志注解可以使用在Controller或serviceImpl上,这里选择用在serviceImpl上,见下面代码。

@Service
public class UserServiceImpl implements UserService {
@Autowired
UserMapper userMapper;

@Override
public PageInfo queryUserList(Map<String, Object> queryMap,Integer pageSize,Integer pageNum) {
PageHelper.startPage(pageNum,pageSize);//分页
List<User> users = userMapper.queryUserList();
PageInfo pageInfo = new PageInfo(users);
return pageInfo;
}

@Override
public List<User> queryByCondition(Map<String, Object> map) {
return userMapper.queryByCondition(map);
}

@LogAnno(operateDesc = "添加用户信息")
@Override
public Integer insert(User user) {
return userMapper.insert(user);
}

@LogAnno(operateDesc = "更新用户信息")
@Override
public Integer update(User user) {
return userMapper.update(user);
}

@LogAnno(operateDesc = "删除用户信息")
@Override
public boolean delete(Integer id) {
return userMapper.delete(id);
}
}

切面类:

/**
* 创建切面类
* 并添加到容器中
*/
@Aspect
@Component
public class LogAopAspect {

@Autowired
LogRecordService logRecordService;//注入日志Service

/**
* 环绕通知记录日志通过注解匹配到需要增加日志功能的方法
* @param pjp
* @return
* @throws Throwable
*/
@Around("@annotation(com.spb.utils.LogAnno)")
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable{
//1.方法执行前的处理,相当于前置通知
//获取方法
MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
//获取方法
Method method = methodSignature.getMethod();
//获取方法上面的注解
LogAnno logAnno = method.getAnnotation(LogAnno.class);
//获取操作描述的属性
String operateDesc = logAnno.operateDesc();

ServletRequestAttributes arr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
HttpSession session = arr.getRequest().getSession(true);
User user = (User)session.getAttribute("loginUser");

//实例化日志记录对象
LogRecord logRecord = new LogRecord();
logRecord.setOperateDesc(operateDesc);//操作描述
if (user != null) {
logRecord.setOperator(user.getName());//操作人
}

Object result = null;

try {
//通过代理方法执行
result = pjp.proceed();
//2.相当于后置通知
logRecord.setResult("正常");
}catch (Exception e){
logRecord.setResult("失败");
}finally {
logRecord.setOperateDate(new Date());//设置日志记录日期
logRecordService.insert(logRecord);//日志信息入库
}

return result;
}
}

这里仅对用户的添加、修改、删除的方法做了日志注解,运行程序 ,查看数据库日志数据:

Springboot AOP 之系统操作日志注解形式实现_aop