aop怎么实现日志记录,aop记录操作日志

  aop怎么实现日志记录,aop记录操作日志

  00-1010 34.使用Aop实现自动日志记录采用第一种方法:1 .第一步是定义一个注释;2.第二步,写一段;3.使用自定义注释。

  00-1010实现自动记录的两种方式:

  通过听者倾听。当访问一个特定的类方法时,通过aop部分获取访问方法,然后记录日志。写一个类通过拦截器继承HandlerInterceptorAdapter,重写preHandle和postHandle,然后登录进去。编写的类被添加到spring容器中。

  

目录

 

  

34、使用Aop的方式实现自动日志记录

注释的功能:

 

  @interface表示这是一个注释类,而不是一个接口,由注释类用来定义注释。是在jdk1.5之后加的,java没有给它新的关键字,所以用@interface这种东西来表示。

  @Inherited//This的注释是可以继承的。

  @Documented//This注释可以写入javadoc

  @Target3360注解的目标

  @Target(ElementType。TYPE) //接口,类,枚举,comment @Target(ElementType。FIELD) //field,枚举@Target的常量(ElementType。METHOD)//METHOD @ target(element type . parameter)//METHOD @ target(element type . constructor)//constructor @ target(element type . local _ variable)//局部变量@ target(element type . annotation _ type)//annotation @ target(element type . package)//package

  @Retention(保留政策。runtime)//可以用来修改注释,注释是注释的注释,称为元注释。

  public enum retention policy { source,//编译器在处理完批注后不在类中存储批注。class,//编译器在CLASS中存储批注,这是默认值。运行时//编译器在类中存储注释,可以被虚拟机读取。反射需要创建一个注释:

  0相当于set和get方法,增加了一个默认值。

  /* * *系统日志注释* */@ target(element type . method)@ retention(retention policy . runtime)@ Documented public @ interface自动日志{/* * *日志内容* * @ return */string value()default“”;*日志类型* @返回1:登录日志;23360操作日志;访问日志;43360异常日志;53360定时任务;int logType()默认CommonConstant。LOG _ TYPE _ 2;*操作日志类型* @return (1查询,2添加,3修改,4删除)int operateType()默认为0;}公共常数相关配置

  接口公共常数{/* * *正常状态*/公共静态最终整数status _ normal=0;*禁用状态公共静态最终整数status _ disable=-1;*删除标志公共静态最终整数del _ flag _ deleted=1;* public static final integer del _ flag _ undeleted=0不被删除;*系统日志类型:log in public static final int log _ type _ 1=1;*系统日志类型:operation public static final int log _ type _ 2=2;/* * *系统日志类型:access */public static final int log _ type _ 3=3;*系统日志类型:异常公共静态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-ddTHH:mm:ss.SSSZ";}

 

  

2、第二步、编写一个切面

@Aspect 表示这是一个切面

 

  @Component 告诉spring 这是一个bean ,注入

  @annotation 获取定义的注解

  @Pointcut 切点,

  @Pointcut("@annotation(xx.AutoLog)") 表示,使用了这个注解的,就是切入点

  @Around的作用

  既可以在目标方法之前织入增强动作,也可以在执行目标方法之后织入增强动作;可以决定目标方法在什么时候执行,如何执行,甚至可以完全阻止目标目标方法的执行;可以改变执行目标方法的参数值,也可以改变执行目标方法之后的返回值; 当需要改变目标方法的返回值时,只能使用Around方法;虽然Around功能强大,但通常需要在线程安全的环境下使用。因此,如果使用普通的Before、AfterReturing增强方法就可以解决的事情,就没有必要使用Around增强处理了。

  ProceedingJoinPoint 环绕通知,主要作用找到程序执行中的可识别的点,当aop的切入点

  环绕通知 ProceedingJoinPoint 执行proceed方法的作用是让目标方法执行,这也是环绕通知和前置、后置通知方法的一个最大区别。简单理解,环绕通知=前置+目标方法执行+后置通知,proceed方法就是用于启动目标方法执行的.

/** * 系统日志,切面处理类 * */@Aspect@Componentpublic 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); }}

 

  

3、使用自定义注解

可以在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自动日志记录内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!

 

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: