(已於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.結果
這樣一來還可以記錄操作前,操作后的值了