Springboot AOP 自定義註解實現系統日誌
一、新增AOP依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
二、AOP切點類
@Slf4j
@Component
@Aspect
@AllArgsConstructor
public class SysLogAspect implements Ordered {
private final SysLogRepository sysLogRepository;
private final SmUserQuery smUserQuery;
private static final ThreadLocal<SysLog> SYS_LOG_THREAD_LOCAL = ThreadLocal.withInitial(SysLog::new);
/**
* 通過AOP方式,攔截註解的日誌
**/
@Pointcut(value = "@annotation(com.huiju.piccre.lfxy.system.annotation.SysLogging)")
public void logAspect() {
}
/**
* 環繞增強,相當於MethodInterceptor
**/
@Around("logAspect()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
Object res = null;
long time = System.currentTimeMillis();
SysLog sysLog = SYS_LOG_THREAD_LOCAL.get();
try {
res = joinPoint.proceed();
time = System.currentTimeMillis() - time;
return res;
} catch (Exception ex) {
sysLog.setOperationStatus("FAILED");
sysLog.setReturnMsg("操作失敗!異常資訊:——> " + ex.getMessage());
throw ex;
} finally {
try {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
sysLog.setOperator(smUserQuery.currentUserCode());
sysLog.setMethodName(signature.getDeclaringTypeName() + "." + signature.getName());
sysLog.setMethodArgs(JSON.toJSONString(joinPoint.getArgs()));
sysLog.setReturnValue(JSON.toJSONString(res));
sysLog.setRunningTime(time);
sysLog.setRequestUrl(request.getRequestURL().toString());
sysLog.setIpAddr(request.getRemoteAddr());
sysLog.setOperationTime(DateUtil.getNowDate());
SysLogging annotation = signature.getMethod().getAnnotation(SysLogging.class);
if (annotation != null) {
sysLog.setOperationType(annotation.operationType().getValue());
sysLog.setOperateContent(annotation.operateContent());
sysLog.setModuleName(annotation.moduleName());
}
} catch (Exception ex) {
log.error("LogAspect 操作失敗:" + ex.getMessage());
ex.printStackTrace();
}
}
}
/**
* 持久化日誌資料
**/
private void saveSysLog(SysLog sysLog) {
log.info("記錄日誌:" + sysLog.toString());
//持久化日誌資料
sysLogRepository.saveAndFlush(sysLog);
}
@Before("logAspect()")
public void doBeforeAdvice(JoinPoint joinPoint) {
log.info("進入方法前執行.....");
SysLog sysLog = SYS_LOG_THREAD_LOCAL.get();
sysLog.setGid(IdUtils.uuid32());
sysLog.setOperationStatus("SUCCESS");
sysLog.setReturnMsg("操作成功!");
}
/**
* 處理完請求,返回內容
*
* @param ret
*/
@AfterReturning(returning = "ret", pointcut = "logAspect()")
public void doAfterReturning(Object ret) {
log.info("方法的返回值 : " + ret);
}
/**
* 後置異常通知
*/
@AfterThrowing("logAspect()")
public void doAfterThrowing(JoinPoint joinPoint) {
log.info("方法異常時執行.....");
}
/**
* 後置最終通知,final增強,不管是丟擲異常或者正常退出都會執行
*/
@After("logAspect()")
public void doAfterAll(JoinPoint joinPoint) {
log.info("方法最後執行.....");
//方法執行完成後增加日誌
saveSysLog(SYS_LOG_THREAD_LOCAL.get());
}
@Override
public int getOrder() {
return 1;
}
}
三、自定義註解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLogging {
/**
* 操作型別
**/
OperationTypeEnum operationType() default OperationTypeEnum.UNDEFINE;
/**
* 執行模組
**/
String moduleName() default "";
/**
* 操作內容描述
**/
String operateContent() default "";
}
四、實體類
@Builder
@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
public class SysLog implements Serializable {
@Id
@ApiModelProperty(value = "操作日誌id")
private String gid;
@ApiModelProperty(value = "操作人")
private String operator;
@ApiModelProperty(value = "操作型別")
private String operationType;
@ApiModelProperty(value = "執行模組")
private String moduleName;
@ApiModelProperty(value = "執行方法")
private String methodName;
@ApiModelProperty(value = "執行引數")
private String methodArgs;
@ApiModelProperty(value = "返回值")
private String returnValue;
@ApiModelProperty(value = "返回訊息")
private String returnMsg;
@ApiModelProperty(value = "執行時長")
private long runningTime;
@ApiModelProperty(value = "操作內容")
private String operateContent;
@ApiModelProperty(value = "請求路徑")
private String requestUrl;
@ApiModelProperty(value = "IP地址")
private String ipAddr;
@ApiModelProperty(value = "操作時間")
private Date operationTime;
@ApiModelProperty(value = "執行描述(1:執行成功、2:執行失敗)")
private String operationStatus;
}
五、操作型別列舉
public enum OperationTypeEnum {
/**
* 操作型別
*/
UNDEFINE("undefine"),
DELETE("delete"),
SELECT("select"),
UPDATE("update"),
INSERT("insert");
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
OperationTypeEnum(String s) {
this.value = s;
}
}
六、日誌表設計
CREATE TABLE `sys_log` (
`gid` varchar(32) NOT NULL COMMENT '操作日誌id',
`operator` varchar(32) DEFAULT NULL COMMENT '操作人',
`operation_type` varchar(10) DEFAULT '' COMMENT '操作型別',
`running_time` bigint(20) DEFAULT NULL COMMENT '方法執行時間',
`module_name` varchar(32) DEFAULT NULL COMMENT '執行模組',
`method_name` varchar(200) DEFAULT NULL COMMENT '執行方法',
`method_args` text COMMENT '執行引數',
`return_value` text COMMENT '返回值',
`return_msg` varchar(640) DEFAULT NULL COMMENT '返回訊息',
`operate_content` varchar(480) DEFAULT NULL COMMENT '操作內容',
`request_url` varchar(360) DEFAULT NULL COMMENT '請求路徑',
`ip_addr` varchar(200) DEFAULT NULL COMMENT 'IP地址',
`operation_time` datetime DEFAULT NULL COMMENT '操作時間',
`operation_status` char(10) DEFAULT NULL COMMENT '執行描述(1:執行成功、2:執行失敗)',
PRIMARY KEY (`gid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
相關文章
- SpringBoot自定義註解、AOP列印日誌Spring Boot
- SpringBoot中搭配AOP實現自定義註解Spring Boot
- SpringBoot專案使用AOP及自定義註解儲存操作日誌Spring Boot
- 基於SpringBoot 、AOP與自定義註解轉義字典值Spring Boot
- Aop+自定義註解實現資料字典翻譯
- 使用C++和QT實現Log自定義日誌系統C++QT
- 運用Spring Aop,一個註解實現日誌記錄Spring
- Spring Boot中自定義註解+AOP實現主備庫切換Spring Boot
- springboot+MDCAdapter自定義starter實現日誌全鏈路追蹤Spring BootAPT
- Net 實現自定義Aop
- java 日誌脫敏框架 sensitive-v0.0.4 系統內建常見註解,支援自定義註解Java框架
- SpringBoot自定義註解+AOP+redis實現防介面冪等性重複提交,從概念到實戰Spring BootRedis
- SpringBoot自定義校驗註解Spring Boot
- springBoot自定義註解的使用Spring Boot
- SpringBoot2 整合日誌,複雜業務下的自定義實現Spring Boot
- redis分散式鎖-spring boot aop+自定義註解實現分散式鎖Redis分散式Spring Boot
- SpringBoot日誌實現Spring Boot
- Spring AOP實現統一日誌輸出Spring
- Springboot+Aop註解的方式實現分散式鎖Spring Boot分散式
- SpringBoot入門(二):日誌及自定義屬性Spring Boot
- 什麼是AOP,以及在Springboot中自定義AOPSpring Boot
- 筆記3:自定義註解的實現筆記
- Spring Boot系列十八 Spring AOP + 註解實現統一註解Spring Boot
- 自定義註解+反射 實現給註解新增功能的效果反射
- Lumen 日誌自定義
- gunicorn 自定義日誌
- 如何優雅地在 Spring Boot 中使用自定義註解,AOP 切面統一列印出入參日誌 | 修訂版Spring Boot
- SpringBoot | 第二十四章:日誌管理之AOP統一日誌Spring Boot
- SpringBoot | SpringBoot 是如何實現日誌的?Spring Boot
- 巧用自定義註解,一行程式碼搞定審計日誌行程
- 安卓自定義註解支援和示例實現安卓
- 自定義Nginx日誌格式Nginx
- 自定義註解
- Feign通過自定義註解實現路徑的轉義
- Flutter實戰之自定義日誌列印元件Flutter元件
- 自定義註解例項實現SQL語句生成SQL
- 使用自定義註解透過BeanPostProcessor實現策略模式Bean模式
- Spring 實現策略模式--自定義註解方式解耦if...elseSpring模式解耦