spring-boot-route 使用aop记录操作日志


spring-boot-route 使用aop记录操作日志

文章插图
 
一 日志记录表日志记录表主要包含几个字段 , 业务模块 , 操作类型 , 接口地址 , 处理状态 , 错误信息以及操作时间 。数据库设计如下:
CREATE TABLE `sys_oper_log` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '日志主键',`title` varchar(50) CHARACTER SET utf8 DEFAULT '' COMMENT '模块标题',`business_type` int(2) DEFAULT '0' COMMENT '业务类型(0其它 1新增 2修改 3删除)',`method` varchar(255) CHARACTER SET utf8 DEFAULT '' COMMENT '方法名称',`status` int(1) DEFAULT '0' COMMENT '操作状态(0正常 1异常)',`error_msg` varchar(2000) CHARACTER SET utf8 DEFAULT '' COMMENT '错误消息',`oper_time` datetime DEFAULT NULL COMMENT '操作时间',PRIMARY KEY (`id`) ) ENGINE=InnoDB CHARSET=utf8mb4 CHECKSUM=1 COMMENT='操作日志记录'对应的实体类如下:
@Data@NoArgsConstructor@AllArgsConstructorpublic class SysOperLog implements Serializable {private static final long serialVersionUID = 1L;/** 日志主键 */private Long id;/** 操作模块 */private String title;/** 业务类型(0其它 1新增 2修改 3删除) */private Integer businessType;/** 请求方法 */private String method;/** 错误消息 */private String errorMsg;private Integer status;/** 操作时间 */private Date operTime;}二 自定义注解及处理自定义注解包含两个属性 , 一个是业务模块 title  , 另一个是操作类型 businessType  。
@Target({ ElementType.PARAMETER, ElementType.METHOD })@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Log {/*** 模块*/String title() default "";/*** 功能*/BusinessType businessType() default BusinessType.OTHER;}使用aop对自定义的注解进行处理
@Aspect@Component@Slf4jpublic class LogAspect {@Autowiredprivate AsyncLogService asyncLogService;// 配置织入点@Pointcut("@annotation(com.JAVAtrip.aop.annotation.Log)")public void logPointCut() {}/*** 处理完请求后执行** @param joinPoint 切点*/@AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) {handleLog(joinPoint, null, jsonResult);}/*** 拦截异常操作** @param joinPoint 切点* @param e 异常*/@AfterThrowing(value = https://www.isolves.com/it/cxkf/kj/2020-10-19/"logPointCut()", throwing = "e")public void doAfterThrowing(JoinPoint joinPoint, Exception e) {handleLog(joinPoint, e, null);}protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult) {try {// 获得注解Log controllerLog = getAnnotationLog(joinPoint);if (controllerLog == null) {return;}SysOperLog operLog = new SysOperLog();operLog.setStatus(0);if (e != null) {operLog.setStatus(1);operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));}// 设置方法名称String className = joinPoint.getTarget().getClass().getName();String methodName = joinPoint.getSignature().getName();operLog.setMethod(className + "." + methodName + "()");// 处理设置注解上的参数getControllerMethodDescription(joinPoint, controllerLog, operLog);// 保存数据库asyncLogService.saveSysLog(operLog);} catch (Exception exp) {log.error("==前置通知异常==");log.error("日志异常信息 {}", exp);}}/*** 获取注解中对方法的描述信息 用于Controller层注解** @param log 日志* @param operLog 操作日志* @throws Exception*/public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog) {// 设置action动作operLog.setBusinessType(log.businessType().ordinal());// 设置标题operLog.setTitle(log.title());}/*** 是否存在注解 , 如果存在就获取*/private Log getAnnotationLog(JoinPoint joinPoint) {Signature signature = joinPoint.getSignature();MethodSignature methodSignature = (MethodSignature) signature;Method method = methodSignature.getMethod();if (method != null) {return method.getAnnotation(Log.class);}return null;}}操作类型的枚举类:
public enum BusinessType {/*** 其它*/OTHER,/*** 新增*/INSERT,/*** 修改*/UPDATE,/*** 删除*/DELETE,}使用 异步 方法将操作日志存库 , 为了方便我直接使用jdbcTemplate在service中进行存库操作 。
@Servicepublic class AsyncLogService {@Autowiredprivate JdbcTemplate jdbcTemplate;/*** 保存系统日志记录*/@Asyncpublic void saveSysLog(SysOperLog log) {String sql = "INSERT INTO sys_oper_log(title,business_type,method,STATUS,error_msg,oper_time) VALUES(?,?,?,?,?,?)";jdbcTemplate.update(sql,new Object[]{log.getTitle(),log.getBusinessType(),log.getMethod(),log.getStatus(),log.getErrorMsg(),new Date()});}}三 编写接口测试将自定义注解写在业务方法上 , 测试效果


推荐阅读