两种基于AOP的日志管理方法(springboot)

xiaoxiao2021-02-28  134

AOP基于切面编程,这里的日志管理俩种分别是 不需要配置xml文件 1、切面类不做实际操作,切入点针对所有的controller类,各个需要保存日志的操作方法,分别执行日志保存的方法,更具有针对性。 2、通过自定义注解,针对方法级别,各个需要保存日志的方法上加自定义注解进行保存操作,实际相当于将日志保存方法提取出来,然后以注解方式应用在每个需要的方法上。


先把第一种介绍一下 LogAspect.java

@Aspect @Component public class LogAspect { /** * 这句话是方法切入点 * 1 execution (* com.my.blog.website.controller..*.*(..)) * 2 execution : 表示执行 * 3 第一个*号 : 表示返回值类型, *可以是任意类型 * 4 com.my.blog.website.controller : 代表扫描的包 * 5 .. : 代表其底下的子包也进行拦截 * 6 第二个*号 : 代表对哪个类进行拦截,*代表所有类 * 7 第三个*号 : 代表方法 *代表任意方法 * 8 (..) : 代表方法的参数有无都可以 */ //配置切入点,该方法无方法体,主要为方便同类中其他方法使用此处配置的切入点 @Pointcut("execution( * com.my.blog.website.controller..*.*(..))") public void webLog(){} //前置通知等可以没有JoinPoint参数 @Before("webLog()") public void doBefore(JoinPoint joinPoint) throws Throwable { // 接收到请求,记录请求内容 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); // 记录下请求内容 LOGGER.info("URL : " + request.getRequestURL().toString() + ",IP : " + request.getRemoteAddr() + ",CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName() + ",ARGS : " + Arrays.toString(joinPoint.getArgs())); } //配置后置返回通知,使用在方法webLog()上注册的切入点 @AfterReturning(returning = "object", pointcut = "webLog()") public void doAfterReturning(Object object) throws Throwable { // 处理完请求,返回内容 LOGGER.info("RESPONSE :" + object); } }

应用:

@PostMapping(value = "/profile") @ResponseBody @Transactional(rollbackFor = TipException.class) public RestResponseBo saveProfile(@RequestParam String screenName, @RequestParam String email, HttpServletRequest request, HttpSession session) { UserVo users = this.user(request); if (StringUtils.isNotBlank(screenName) && StringUtils.isNotBlank(email)) { UserVo temp = new UserVo(); temp.setUid(users.getUid()); temp.setScreenName(screenName); temp.setEmail(email); userService.updateByUid(temp); //这里需要单独保存日志信息, logService.insertLog(LogActions.UP_INFO.getAction(), GsonUtils.toJsonString(temp), request.getRemoteAddr(), this.getUid(request)); //更新session中的数据 UserVo original = (UserVo) session.getAttribute(WebConst.LOGIN_SESSION_KEY); original.setScreenName(screenName); original.setEmail(email); session.setAttribute(WebConst.LOGIN_SESSION_KEY, original); } return RestResponseBo.ok(); }

第二种 SysLogAspect.java

@Aspect //定义切面 @Component //声明组件 public class SysLogAspect { @Autowired private ILogService logService; //这里切入点是自定义注解,下面有注解的代码 @Pointcut("@annotation(com.my.blog.website.annotation.SysLog)") public void logPointCut(){ } //配置环绕通知,使用在方法logPointCut()上注册的切入点 @Around("logPointCut()") public Object around(ProceedingJoinPoint point)throws Throwable{ long beginTime=System.currentTimeMillis(); //执行方法 Object result=point.proceed(); //可以设置time,监控方法执行的时间,但是我没有去实现 long time=System.currentTimeMillis()-beginTime; saveSysLog(point,time); return result; } private void saveSysLog(ProceedingJoinPoint point, long time){ MethodSignature signature=(MethodSignature) point.getSignature(); Method method=signature.getMethod(); LogVo log=new LogVo(); SysLog sysLog=method.getAnnotation(SysLog.class); HttpServletRequest request=((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest(); //从session中获取用户 UserVo user=(UserVo) request.getSession().getAttribute(WebConst.LOGIN_SESSION_KEY); //获取请求参数 Object[] args=point.getArgs(); logService.insertLog(sysLog.value().getAction(), GsonUtils.toJsonString(args[0]), request.getRemoteAddr(), user.getUid()); } }

注解代码:

@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface SysLog { LogActions value() default LogActions.LOGIN; }

枚举类用来存放操作的名字

public enum LogActions { LOGIN("登录后台"), UP_PWD("修改密码"), UP_INFO("修改个人信息"), DEL_ARTICLE("删除文章"), DEL_PAGE("删除页面"), SYS_BACKUP("系统备份"),DEL_COMMENT("删除评论"), SYS_SETTING("保存系统设置"), INIT_SITE("初始化站点"); private String action; public String getAction() { return action; } public void setAction(String action) { this.action = action; } LogActions(String action) { this.action = action; }

应用:

@SysLog(LogActions.UP_INFO) @PostMapping(value = "/profile") @ResponseBody @Transactional(rollbackFor = TipException.class) public RestResponseBo saveProfile(@RequestParam String screenName, @RequestParam String email, HttpServletRequest request, HttpSession session) { UserVo users = this.user(request); if (StringUtils.isNotBlank(screenName) && StringUtils.isNotBlank(email)) { UserVo temp = new UserVo(); temp.setUid(users.getUid()); temp.setScreenName(screenName); temp.setEmail(email); userService.updateByUid(temp); //更新session中的数据 UserVo original = (UserVo) session.getAttribute(WebConst.LOGIN_SESSION_KEY); original.setScreenName(screenName); original.setEmail(email); session.setAttribute(WebConst.LOGIN_SESSION_KEY, original); } return RestResponseBo.ok(); }

这种只需要在你的方法上加上注解@SysLog(LogActions.UP_INFO),LogActions.UP_INFO这个是自定义的一个类型,这里可以直接放string类型的数据,不过需要修改注解定义那里。

至此,两种AOP日志管理搞定,主要是要做个记录,同时熟悉熟悉AOP这个技巧,真的很实用,希望可以帮到需要的人。

转载请注明原文地址: https://www.6miu.com/read-44676.html

最新回复(0)