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这个技巧,真的很实用,希望可以帮到需要的人。