0
点赞
收藏
分享

微信扫一扫

基于自定义注解、AOP和Spring事件发布实现日志记录


实现过程

自定义操作日志注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {

/**
* 描述
* @return {String}
*/
String value();

}

基于AOP定义切面

操作日志使用​​spring event​​异步入库

@Slf4j
@Aspect
@RequiredArgsConstructor
public class SysLogAspect {

// 先拿到事件发布器
private final ApplicationEventPublisher publisher;

private final KeyStrResolver tenantKeyStrResolver;

@Value("${spring.application.name:}")
private String serverName;

@SneakyThrows
//Pointcut 切点接口提供了丰富的实现,基于注解的、基于Aspect表达式的等
@Around("@annotation(sysLog)")
public Object around(ProceedingJoinPoint point, SysLog sysLog) {
// ProceedingJoinPoint 中获取信息
String strClassName = point.getTarget().getClass().getName();
String strMethodName = point.getSignature().getName();
log.debug("[类名]:{},[方法]:{}", strClassName, strMethodName);

GapSysLog syslog = SysLogUtils.getSysLog(serverName);


syslog.setTitle(sysLog.value());
// 发送异步日志事件
Long startTime = System.currentTimeMillis();
Object obj;
try {
obj = point.proceed();
}
catch (Exception e) {
syslog.setType(LogTypeEnum.ERROR.getType());
syslog.setException(e.getMessage());
throw e;
}
finally {
Long endTime = System.currentTimeMillis();
syslog.setEraTime(endTime - startTime);
syslog.setParams(JSONUtil.parseArray(point.getArgs()).toString());

// 发布事件
// 事件是SysLogEvent,发送者是syslog
// 不关心处理者,比如处理者可以是短信验证也可以是邮件验证。实现了解耦。
// 简历修改为:基于AOP和发布事件(封装要记录的日志信息,面试官问日志信息包含哪些)以及基于监听器异步监听记录操作日志
// 记录的主要信息有:服务名(读取配置文件)、类名、方法名
publisher.publishEvent(new SysLogEvent(syslog));
}
return obj;
}

}

监听器(异步监听)接收事件进行处理

@Slf4j
@Component
public class SysLogListener {

//方法调用
@Autowired
private ISysLogController serviceTransfer;

// //FeignClient远程调用
// private final RemoteLogService serviceTransfer;

//在Spring中,基于@Async标注的方法,称之为异步方法
//这些方法将在执行的时候,将会在独立的线程中被执行,调用者无需等待它的完成,即可继续其他的操作。
@Async
@Order
// 接收事件,用此注解声明这是一个监听事件的方法
@EventListener(SysLogEvent.class)
public void saveSysLog(SysLogEvent event) {
// 以下是业务逻辑
GapSysLog sysLog = event.getSysLog();
serviceTransfer.insert(sysLog);
}

}


日志实体类如下

/**
* @Description: 日志查询传输对象
* (GapSysLog)实体类
* @Author: GdlSky
* @Date 下午5:19 2021/8/31
*/
@Data
@ApiModel(value = "日志实体对象展示")
public class GapSysLog implements Serializable {
private static final long serialVersionUID = -78769795229339921L;
/**
* 编号
*/
@ApiModelProperty(value = "id")
private String id;
/**
* 日志类型
*/
@ApiModelProperty(value = "请求结果0:成功9:失败")
@NotBlank(message = "日志类型不能为空")
private String type;
/**
* 日志标题
*/
@ApiModelProperty(value = "日志标题")
@NotBlank(message = "日志标题不能为空")
private String title;
/**
* 应用标识
*/
@ApiModelProperty(value = "应用标识")
private String serviceId;
/**
* 操作人
*/
@ApiModelProperty(value = "操作人")
private String createBy;
/**
* 用户类型
*/
@ApiModelProperty(value = "用户类型")
private Long userType;
/**
* 用户代理
*/
@ApiModelProperty(value = "用户代理")
private String userAgent;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd")
@ApiModelProperty(value = "创建时间", dataType = "LocalDate", example = "2020-12-07")
private Date createTime;
/**
* 操作IP地址
*/
@ApiModelProperty(value = "操作IP地址")
private String remoteAddr;
/**
* 请求URI
*/
@ApiModelProperty(value = "请求URI")
private String requestUri;
/**
* 操作方式
*/
@ApiModelProperty(value = "操作方式")
private String method;
/**
* 提交数据
*/
@ApiModelProperty(value = "提交数据")
private String params;
/**
* 方法执行时间
*/
@ApiModelProperty(value = "方法执行时间")
private Long eraTime;
/**
* 删除标记
*/
@ApiModelProperty(value = "删除标记:1、是 2、否")
private Long delFlag;
/**
* 异常信息
*/
@ApiModelProperty(value = "异常信息")
private String exception;
/**
* 所属租户
*/
@ApiModelProperty(value = "所属租户")
private Integer tenantId;

}






举报

相关推荐

0 条评论