Spring aop 记录操作日志 Aspect

已于2018年01月04日更新了一个优化版,里面附带源码,地址为:http://www.cnblogs.com/leifei/p/8194644.html )

前几天做系统日志记录的功能,一个操作调一次记录方法,每次还得去收集参数等等,太尼玛烦了。在程序员的世界里,当你的一个功能重复出现多次,就应该想想肯定有更简单的实现方法。于是果断搜索各种资料,终于搞定了,现在上代码

环境: SpringMvc + myBatis

jar包 :      (aspect.jar也行,我原来项目中有,便没有替换了)

1.自定义注解类   ArchivesLog.java(获取Controller描述用的)

package com.noahwm.uomp.archives.common;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.PARAMETER, ElementType.METHOD})  
@Retention(RetentionPolicy.RUNTIME)  
@Documented  
public @interface ArchivesLog {

    /** 要执行的操作类型比如:add操作 **/  
    public String operationType() default "";  

    /** 要执行的具体操作比如:添加用户 **/  
    public String operationName() default ""; 
    
}

2.日志处理类  ArchivesLogAspect.java(业务处理)

package com.noahwm.uomp.archives.common;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.noahwm.uomp.base.security.SecurityConstant;
import com.noahwm.uomp.system.bo.User;

public class ArchivesLogAspect {
    private final Logger logger = Logger.getLogger(this.getClass());  

    private String requestPath = null ; // 请求地址  
    private String userName = "" ; // 用户名  
    private Map<?,?> inputParamMap = null ; // 传入参数  
    private Map<String, Object> outputParamMap = null; // 存放输出结果  
    private long startTimeMillis = 0; // 开始时间  
    private long endTimeMillis = 0; // 结束时间  
    private User user = null;
    private HttpServletRequest request = null;

    /** 
     *  
     * @Description: 方法调用前触发   记录开始时间  
     * @author fei.lei  
     * @date 2016年11月23日 下午5:10 
     * @param joinPoint 
     */ 
    public void before(JoinPoint joinPoint){  
        //System.out.println("被拦截方法调用之后调用此方法,输出此语句");  
        request = getHttpServletRequest();  
        //fileName  为例子
        Object obj =request.getParameter("fileName");
        System.out.println("方法调用前: " + obj);
        user = (User)request.getSession().getAttribute(SecurityConstant.CURRENT_LOGIN_USER);
        startTimeMillis = System.currentTimeMillis(); //记录方法开始执行的时间  
    }  
    
    /** 
     *  
     * @Description: 方法调用后触发   记录结束时间  
     * @author fei.lei  
     * @date 2016年11月23日 下午5:10 
     * @param joinPoint 
     */
    public  void after(JoinPoint joinPoint) { 
        request = getHttpServletRequest(); 
        String targetName = joinPoint.getTarget().getClass().getName();  
        String methodName = joinPoint.getSignature().getName();  
        Object[] arguments = joinPoint.getArgs();  
        Class targetClass = null;
        try {
            targetClass = Class.forName(targetName);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }  
        Method[] methods = targetClass.getMethods();
        String operationName = "";
        for (Method method : methods) {  
            if (method.getName().equals(methodName)) {  
                Class[] clazzs = method.getParameterTypes();  
                if (clazzs!=null&&clazzs.length == arguments.length&&method.getAnnotation(ArchivesLog.class)!=null) {  
                    operationName = method.getAnnotation(ArchivesLog.class).operationName();
                    break;  
                }  
            }  
        }
        endTimeMillis = System.currentTimeMillis();
        //格式化开始时间
        String startTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(startTimeMillis);
        //格式化结束时间
        String endTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(endTimeMillis);
        
        Object obj =request.getParameter("fileName");
        System.out.println("方法调用后: " + obj);
        System.out.println(" 操作人: "+user.getName()+" 操作方法: "+operationName+" 操作开始时间: "+startTime +" 操作结束时间: "+endTime);
        
    }
    /**
     * @Description: 获取request  
     * @author fei.lei  
     * @date 2016年11月23日 下午5:10 
     * @param  
     * @return HttpServletRequest
     */
    public HttpServletRequest getHttpServletRequest(){
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();  
        ServletRequestAttributes sra = (ServletRequestAttributes)ra;  
        HttpServletRequest request = sra.getRequest();
        return request;
    }
  
    /** 
     *  
     * @Title:around 
     * @Description: 环绕触发  
     * @author fei.lei  
     * @date 2016年11月23日 下午5:10 
     * @param joinPoint 
     * @return Object
     * @throws Throwable 
     */  
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {  

        return null;  
    }  

    /** 
     *  
     * @Title:printOptLog 
     * @Description: 输出日志  
     * @author fei.lei 
     * @date 2016年11月23日 下午5:10
     */  
    /*private void printOptLog() {  
        Gson gson = new Gson(); // 需要用到google的gson解析包  
        String startTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(startTimeMillis);
        String endTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(endTimeMillis);  
        logger.info("user :" +user.getName()+ " start_time: " +  startTime +" end_time: "+endTime);  
    }  */
    
    
}


3.spring 注入

   
   

   <!--指定扫描目录-->
   <
context:component-scan base-package="com.noahwm" /> <aop:aspectj-autoproxy proxy-target-class="true" /> <!--将日志类注入到bean中。--> <bean id="logAspect" class="com.noahwm.uomp.archives.common.ArchivesLogAspect"></bean> <aop:config> <!--调用日志类--> <aop:aspect id="LogAspect" ref="logAspect"> <!--配置在controller包下所有的类在调用之前都会被拦截--> <aop:pointcut id="log" expression="execution(* com.noahwm.uomp.archives.controller.*.*(..))"/> <!-- 方法前触发 --><aop:before pointcut-ref="log" method="before"/> <!-- 方法后触发 --><aop:after pointcut-ref="log" method="after"/> <!-- 环绕触发 <aop:around pointcut-ref="log" method="around"/> --> </aop:aspect> </aop:config>

3.调用(设置Controller描述)

    @RequestMapping(value="/fileQuery")
    @ArchivesLog(operationType="查询操作:",operationName="查询文件") 
    public ModelAndView fileQuery(HttpServletRequest request,HttpServletResponse response){

        return new ModelAndView("archives/fileQuery");
       }    

4.结果

这样一来还可以记录操作前,操作后的值了

原文地址:https://www.cnblogs.com/leifei/p/6094673.html