<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
自動紀錄檔記錄的實現的兩種方式:
①通過監聽器去監聽,當存取到具體的類方法,通過aop切面去獲取存取的方法,然後將紀錄檔記錄下來
②通過攔截器,編寫一個類去繼承HandlerInterceptorAdapter,重寫preHandle,postHandle,然後在裡面進行紀錄檔記錄,編寫的類加到spring容器裡
Annotation 註解的作用:
@interface 表示這是一個註解類, 不是interface,是註解類 定義註解用的,是jdk1.5之後加入的,java沒有給它新的關鍵字,所以就用@interface 這麼個東西表示了
@Inherited //這個Annotation 可以被繼承
@Documented //這個Annotation可以被寫入javadoc
@Target:註解的作用目標
@Target(ElementType.TYPE) //介面、類、列舉、註解
@Target(ElementType.FIELD) //欄位、列舉的常數
@Target(ElementType.METHOD) //方法
@Target(ElementType.PARAMETER) //方法引數
@Target(ElementType.CONSTRUCTOR) //建構函式
@Target(ElementType.LOCAL_VARIABLE)//區域性變數
@Target(ElementType.ANNOTATION_TYPE)//註解
@Target(ElementType.PACKAGE) ///包
@Retention(RetentionPolicy.RUNTIME) //可以用來修飾註解,是註解的註解,稱為元註解。
public enum RetentionPolicy { SOURCE, // 編譯器處理完Annotation後不儲存在class中 CLASS, // 編譯器把Annotation儲存在class中,這是預設值 RUNTIME // 編譯器把Annotation儲存在class中,可以由虛擬機器器讀取,反射需要 }
建立一個註解:
default 0 相當於set和get方法,新增一個預設值
/** * 系統紀錄檔註解 * */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface AutoLog { /** * 紀錄檔內容 * * @return */ String value() default ""; * 紀錄檔型別 * @return 1:登入紀錄檔;2:操作紀錄檔;3:存取紀錄檔;4:異常紀錄檔;5:定時任務; int logType() default CommonConstant.LOG_TYPE_2; * 操作紀錄檔型別 * @return (1查詢,2新增,3修改,4刪除) int operateType() default 0; }
CommonConstant 相關的設定
public interface CommonConstant { /** * 正常狀態 */ public static final Integer STATUS_NORMAL = 0; * 禁用狀態 public static final Integer STATUS_DISABLE = -1; * 刪除標誌 public static final Integer DEL_FLAG_DELETED = 1; * 未刪除 public static final Integer DEL_FLAG_UNDELETED = 0; * 系統紀錄檔型別: 登入 public static final int LOG_TYPE_1 = 1; * 系統紀錄檔型別: 操作 public static final int LOG_TYPE_2 = 2; /** * 系統紀錄檔型別: 存取 */ public static final int LOG_TYPE_3 = 3; * 系統紀錄檔型別: 異常 public static final int LOG_TYPE_4 = 4; * 系統紀錄檔型別: 定時任務 public static final int LOG_TYPE_5 = 5; * 系統紀錄檔型別: 使用者管理 public static final int LOG_TYPE_6 = 6; * 系統登陸紀錄檔:正常賬戶密碼登入 public static final int OPERATE_TYPE_LT1_1 = 1; * 系統登陸紀錄檔:二維條碼登陸 public static final int OPERATE_TYPE_LT1_2 = 2; * 系統登陸紀錄檔:單點登陸 public static final int OPERATE_TYPE_LT1_3 = 3; * 系統登陸紀錄檔:登出 public static final int OPERATE_TYPE_LT1_4 = 4; * 系統登陸紀錄檔:模擬登陸 public static final int OPERATE_TYPE_LT1_5 = 5; * 操作紀錄檔型別: 查詢 public static final int OPERATE_TYPE_LT2_1 = 1; * 操作紀錄檔型別: 新增 public static final int OPERATE_TYPE_LT2_2 = 2; * 操作紀錄檔型別: 更新 public static final int OPERATE_TYPE_LT2_3 = 3; * 操作紀錄檔型別: 刪除 public static final int OPERATE_TYPE_LT2_4 = 4; * 操作紀錄檔型別: 匯入 public static final int OPERATE_TYPE_LT2_5 = 5; * 操作紀錄檔型別: 匯出 public static final int OPERATE_TYPE_LT2_6 = 6; * 存取紀錄檔型別: 進入 public static final int OPERATE_TYPE_LT3_1 = 1; * 異常紀錄檔型別: 普通操作即程式碼錯誤 public static final int OPERATE_TYPE_LT4_1 = 1; * 異常紀錄檔型別: 非法操作即越權操作 public static final int OPERATE_TYPE_LT4_2 = 2; public static final String CLIENT_TYPE_PC="0"; public static final String CLIENT_TYPE_MOBILE="1"; /** {@code 500 Server Error} (HTTP/1.0 - RFC 1945) */ public static final Integer SC_INTERNAL_SERVER_ERROR_500 = 500; /** {@code 200 OK} (HTTP/1.0 - RFC 1945) */ public static final Integer SC_OK_200 = 200; /**存取許可權認證未通過 510*/ public static final Integer SC_JEECG_NO_AUTHZ=510; /** 登入使用者Shiro許可權快取KEY字首 */ public static String PREFIX_USER_SHIRO_CACHE = "shiro:cache:org.jeecg.modules.shiro.authc.ShiroRealm.authorizationCache:"; /** 登入使用者Token令牌快取KEY字首 */ public static final String PREFIX_USER_TOKEN = "prefix_user_token_"; /** Token快取時間:3600秒即一小時 */ public static final int TOKEN_EXPIRE_TIME = 3600; * 0:一級選單 public static final Integer MENU_TYPE_0 = 0; /** * 1:子選單 */ public static final Integer MENU_TYPE_1 = 1; * 2:按鈕許可權 public static final Integer MENU_TYPE_2 = 2; /**通告物件型別(USER:指定使用者,ALL:全體使用者)*/ public static final String MSG_TYPE_UESR = "USER"; public static final String MSG_TYPE_ALL = "ALL"; /**釋出狀態(0未釋出,1已釋出,2已復原)*/ public static final String NO_SEND = "0"; public static final String HAS_SEND = "1"; public static final String HAS_CANCLE = "2"; /**閱讀狀態(0未讀,1已讀)*/ public static final String HAS_READ_FLAG = "1"; public static final String NO_READ_FLAG = "0"; /**優先順序(L低,M中,H高)*/ public static final String PRIORITY_L = "L"; public static final String PRIORITY_M = "M"; public static final String PRIORITY_H = "H"; * 簡訊模板方式 0 .登入模板、1.註冊模板、2.忘記密碼模板 public static final String SMS_TPL_TYPE_0 = "0"; public static final String SMS_TPL_TYPE_1 = "1"; public static final String SMS_TPL_TYPE_2 = "2"; * 狀態(0無效1有效) public static final String STATUS_0 = "0"; public static final String STATUS_1 = "1"; * 同步工作流引擎1同步0不同步 public static final String ACT_SYNC_0 = "0"; public static final String ACT_SYNC_1 = "1"; * 訊息型別1:通知公告2:系統訊息 public static final String MSG_CATEGORY_1 = "1"; public static final String MSG_CATEGORY_2 = "2"; * 是否設定選單的資料許可權 1是0否 public static final Integer RULE_FLAG_0 = 0; public static final Integer RULE_FLAG_1 = 1; * 使用者狀態 0凍結 1正常 2待定 public static final Integer USER_FREEZE = 0; public static final Integer USER_NORMAL = 1; * 使用者刪除標誌位 0未刪 1已刪 public static final Integer USER_DELETE_NO=0; public static final Integer USER_DELETE_YES=1; /**字典翻譯文字字尾*/ public static final String DICT_TEXT_SUFFIX = "_dictText"; public static final String ITEM_DISPLAY = "_display"; * 表單設計器主表型別 public static final Integer DESIGN_FORM_TYPE_MAIN = 1; * 表單設計器子表表型別 public static final Integer DESIGN_FORM_TYPE_SUB = 2; * 表單設計器URL授權通過 public static final Integer DESIGN_FORM_URL_STATUS_PASSED = 1; * 表單設計器URL授權未通過 public static final Integer DESIGN_FORM_URL_STATUS_NOT_PASSED = 2; * 表單設計器新增 Flag public static final String DESIGN_FORM_URL_TYPE_ADD = "add"; * 表單設計器修改 Flag public static final String DESIGN_FORM_URL_TYPE_EDIT = "edit"; * 表單設計器詳情 Flag public static final String DESIGN_FORM_URL_TYPE_DETAIL = "detail"; * 表單設計器複用資料 Flag public static final String DESIGN_FORM_URL_TYPE_REUSE = "reuse"; * 表單設計器編輯 Flag (已棄用) public static final String DESIGN_FORM_URL_TYPE_VIEW = "view"; * online引數值設定(是:Y, 否:N) public static final String ONLINE_PARAM_VAL_IS_TURE = "Y"; public static final String ONLINE_PARAM_VAL_IS_FALSE = "N"; * 檔案上傳型別(本地:local,Minio:minio,阿里雲:alioss) public static final String UPLOAD_TYPE_LOCAL = "local"; public static final String UPLOAD_TYPE_MINIO = "minio"; public static final String UPLOAD_TYPE_OSS = "alioss"; * 員工身份 (1:普通員工 2:上級) public static final Integer USER_IDENTITY_1 = 1; public static final Integer USER_IDENTITY_2 = 2; * 日期格式 public static final String TIME_FORMAT_YMD = "yyyy-MM-dd"; public static final String TIME_FORMAT_YMDHMS = "yyyy-MM-dd HH:mm:ss"; public static final String TIME_FORMAT_YMDHMSSZ = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; }
@Aspect 表示這是一個切面
@Component 告訴spring 這是一個bean ,注入
@annotation 獲取定義的註解
@Pointcut 切點,
@Pointcut("@annotation(xx.AutoLog)") 表示,使用了這個註解的,就是切入點
@Around的作用
既可以在目標方法之前織入增強動作,也可以在執行目標方法之後織入增強動作;
可以決定目標方法在什麼時候執行,如何執行,甚至可以完全阻止目標目標方法的執行;
可以改變執行目標方法的引數值,也可以改變執行目標方法之後的返回值; 當需要改變目標方法的返回值時,只能使用Around方法;
雖然Around功能強大,但通常需要線上程安全的環境下使用。因此,如果使用普通的Before、AfterReturing增強方法就可以解決的事情,就沒有必要使用Around增強處理了。
ProceedingJoinPoint 環繞通知,主要作用找到程式執行中的可識別的點,當aop的切入點
/** * 系統紀錄檔,切面處理類 * */ @Aspect @Component public class AutoLogAspect { @Autowired private ISysLogService sysLogService; @Pointcut("@annotation(xx.AutoLog)") public void logPointCut() { } @Around("logPointCut()") public Object around(ProceedingJoinPoint point) throws Throwable { long beginTime = System.currentTimeMillis(); //執行方法 Object result = point.proceed(); //執行時長(毫秒) long time = System.currentTimeMillis() - beginTime; //儲存紀錄檔 saveSysLog(point, time); return result; } private void saveSysLog(ProceedingJoinPoint joinPoint, long time) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); SysLog sysLog = new SysLog(); AutoLog syslog = method.getAnnotation(AutoLog.class); if (syslog != null) { //註解上的描述,操作紀錄檔內容 sysLog.setLogContent(syslog.value()); sysLog.setLogType(syslog.logType()); } //請求的方法名 String className = joinPoint.getTarget().getClass().getName(); String methodName = signature.getName(); sysLog.setMethod(className + "." + methodName + "()"); //設定操作型別 if (sysLog.getLogType() == CommonConstant.LOG_TYPE_2) { sysLog.setOperateType(getOperateType(methodName, syslog.operateType())); } //請求的引數 Object[] args = joinPoint.getArgs(); try { String params = JSONObject.toJSONString(args); sysLog.setRequestParam(params); } catch (Exception e) { } try { //獲取request HttpServletRequest request = SpringContextUtils.getHttpServletRequest(); //設定IP地址 sysLog.setIp(IPUtils.getIpAddr(request)); } catch (Exception e) { } //獲取登入使用者資訊 LoginUser sysUser = null; try { sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); } catch (Exception e) { } if (sysUser != null) { sysLog.setUserId(sysUser.getId()); sysLog.setUserName(sysUser.getUserName()); sysLog.setRealName(sysUser.getRealName()); sysLog.setOrgId(sysUser.getNowOrgId()); sysLog.setOrgName(sysUser.getNowOrgName()); } //耗時 sysLog.setCostTime(time); sysLog.setCreateTime(new Date()); //儲存系統紀錄檔 sysLogService.save(sysLog); } /** * 獲取操作型別 */ private int getOperateType(String methodName, int operateType) { if (operateType > 0) { return operateType; } if (methodName.startsWith("list")) { return CommonConstant.OPERATE_TYPE_LT2_1; } if (methodName.startsWith("add")) { return CommonConstant.OPERATE_TYPE_LT2_2; } if (methodName.startsWith("edit")) { return CommonConstant.OPERATE_TYPE_LT2_3; } if (methodName.startsWith("delete")) { return CommonConstant.OPERATE_TYPE_LT2_4; } if (methodName.startsWith("import")) { return CommonConstant.OPERATE_TYPE_LT2_5; } if (methodName.startsWith("export")) { return CommonConstant.OPERATE_TYPE_LT2_6; } return CommonConstant.OPERATE_TYPE_LT2_1; } @AfterThrowing(pointcut = "logPointCut()", throwing = "ex") public void afterThrowing(JoinPoint joinPoint, Throwable ex) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); SysLog sysLog = new SysLog(); StackTraceElement[] stackTraceElements = ex.getStackTrace(); String rootExceptionName = ex.getClass().getName(); StringBuilder resultContent = new StringBuilder("異常類:" + rootExceptionName); int count = 0; int maxTrace = 3; for (StackTraceElement stackTraceElement : stackTraceElements) { if (stackTraceElement.getClassName().contains("com.lingxu") && count < maxTrace) { resultContent.append("n出現於").append(stackTraceElement.getClassName()) .append("類中的").append(stackTraceElement.getMethodName()) .append("方法中 位於該類檔案的第").append(stackTraceElement.getLineNumber()) .append("行)"); count++; if (count == maxTrace) { break; } } } sysLog.setExceptionContent(resultContent.toString()); AutoLog syslog = method.getAnnotation(AutoLog.class); if (syslog != null) { //註解上的描述,操作紀錄檔內容 sysLog.setLogContent(syslog.value() + "出現異常"); sysLog.setLogType(CommonConstant.LOG_TYPE_4); } //請求的方法名 String className = joinPoint.getTarget().getClass().getName(); String methodName = signature.getName(); sysLog.setMethod(className + "." + methodName + "()"); //設定操作型別 sysLog.setOperateType(CommonConstant.OPERATE_TYPE_LT4_1); //請求的引數 Object[] args = joinPoint.getArgs(); try { String params = JSONObject.toJSONString(args); sysLog.setRequestParam(params); } catch (Exception e) { } try { //獲取request HttpServletRequest request = SpringContextUtils.getHttpServletRequest(); //設定IP地址 sysLog.setIp(IPUtils.getIpAddr(request)); } catch (Exception e) { } try { //獲取登入使用者資訊 LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); if (sysUser != null) { sysLog.setUserId(sysUser.getId()); sysLog.setUserName(sysUser.getUserName()); sysLog.setRealName(sysUser.getRealName()); sysLog.setOrgId(sysUser.getNowOrgId()); sysLog.setOrgName(sysUser.getNowOrgName()); } } catch (Exception e) { } //儲存系統紀錄檔 sysLogService.save(sysLog); } }
可以在controller或者實現類上進行註解的加入
@AutoLog(value = "sss",logType = CommonConstant.LOG_TYPE_3, operateType = 2) @ApiOperation(value="記錄查詢紀錄檔-分頁列表查詢", notes="記錄查詢紀錄檔-分頁列表查詢") @PostMapping(value = "/queryPage") public Result<?> queryPage(@RequestBody SysSelectLog sysSelectLog){ Page<SysSelectLog> page = new Page<>(sysSelectLog.getPageNo(),sysSelectLog.getPageSize()); IPage<SysSelectLog> sysSelectLogIPage = sysSelectLogService.queryPage(page,sysSelectLog); return Result.ok(sysSelectLogIPage); }
到此這篇關於使用Aop的方式實現自動紀錄檔記錄的文章就介紹到這了,更多相關Aop自動紀錄檔記錄內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45