HandlerInterceptor记录系统日志

需求:
记录系统日志,要求字段有:一级菜单名,二级菜单名,进行了什么操作

实现方式:
两个注解:

package com.bshf.recipe.demo.syslog;

import java.lang.annotation.*;


/**
 * 

用于记录系统操作日志的注解 -- 类注解

*

在需要记录系统操作日志的Controller上添加该注解

* */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface CategoryLog { /** * 一级菜单名 */ String menu1(); /** * 二级菜单名 */ String menu2(); } package com.bshf.recipe.demo.syslog; import java.lang.annotation.*; /** *

用于记录系统操作日志的注解 -- 方法注解

*

在需要记录系统操作日志的Controller中待记录系统操作日志的方法上添加该注解。

* */ @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface DescLog { /** * 操作名称 */ String value(); }

注解处理器:

package com.bshf.recipe.demo.syslog;


import java.lang.reflect.Method;

import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SyslogInterceptor extends HandlerInterceptorAdapter {

    /**
     * 后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        
        if(! (handler instanceof HandlerMethod)) {
            return ;
        }
        
        HandlerMethod method = (HandlerMethod)handler;
        Class controller = method.getBean().getClass();
        //获取类上的CategoryLog注解
        CategoryLog annotation = controller.getAnnotation(CategoryLog.class);
        //若类上没注解,则不记录日志
        if(null == annotation) {
            return ;
        }
        String menu1 = annotation.menu1();
        String menu2 = annotation.menu2();
        
        Method anyMethod = method.getMethod();
        //获取所有方法上的DescLog注解
        DescLog methodLog = anyMethod.getAnnotation(DescLog.class);
        
        if (null == methodLog) {
            return ;
        }

        String value = methodLog.value();
        
        //真正开始记录日志的代码。
//      SysLog sysLog = new SysLog();
//      sysLog.setXXX();
//      sysLogService.save(sysLog);
        
    }
}

配置文件:


        
            
            
        

Demo测试:

package controller;

import annotation.CategoryLog;
import annotation.DescLog;

/**
 * @author [email protected]
 * @date 2017年4月6日
 */
@CategoryLog(firstMenu = "基本信息", secondMenu = "用户")
@Controller
@RequestMapping("/demo")
public class DemoController {

    @DescLog("HelloWorld登陆了")
    @RequestMapping("/test")
    public void test() {
        System.out.println("HelloWorld!");
    }
}

程序运行流程:
当调用test接口时,会首先会进入拦截器的preHandle方法,由于继承的HandlerInterceptorAdapter,而HandlerInterceptorAdapter 中的preHandle方法默认为true,所以进行test方法的业务逻辑,当走完逻辑(这时候只是走完了逻辑,页面并没有渲染数据),会调用postHandle方法进行记录日志,postHandle方法拿到注解上的值,就可以知道谁对某个模块操作了什么。当走完postHandle后,会调用HandlerInterceptorAdapter的afterCompletion(页面渲染完数据后会执行此方法)方法进行清理工作。

问:为什么不在afterCompletion方法进行日志记录?
答:因为如果我有多个拦截器或者就这一个,只要遇到preHandle方法返回false的,test主逻辑方法就不会在执行,就只会执行preHandle和afterCompletion方法,test主逻辑和postHandle方法都不会执行。这样就会产生我本来没有操作成功,return false了,但是还是给我记录了一条日志。而postHandle方法只要你程序抛出异常了或者preHandle返回false了,就不会执行,这样就不会记录系统日志。想要记录异常日志,可以配合logback+aop。

如对HandlerInterceptor不懂的请看我的这篇文章:http://www.jianshu.com/p/1e8d088c2be9

若有兴趣,欢迎来加入群,【Java初学者学习交流群】:458430385,此群有Java开发人员、UI设计人员和前端工程师。有问必答,共同探讨学习,一起进步!
欢迎关注我的微信公众号【Java码农社区】,会定时推送各种干货:


HandlerInterceptor记录系统日志_第1张图片
qrcode_for_gh_577b64e73701_258.jpg

你可能感兴趣的:(HandlerInterceptor记录系统日志)