2019獨角獸企業重金招聘Python工程師標準>>>
? ? ? ? ?首先我們為什么需要做日志管理,在現實的上線中我們經常會遇到系統出現異常或者問題。這個時候就馬上打開CRT或者SSH連上服務器拿日子來分析。受網絡的各種限制。于是我們就想為什么不能直接在管理后臺查看報錯的信息呢。于是日志管理就出現了。
? ? ? ? ?其次個人覺得做日志管理最好的是Aop,有的人也喜歡用攔截器。都可以,在此我重點介紹我的實現方式。
? ? ? ? ?Aop有的人說攔截不到Controller。有的人說想攔AnnotationMethodHandlerAdapter截到Controller必須得攔截org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter。
首先Aop可以攔截到Controller的,這個是毋容置疑的其次須攔截AnnotationMethodHandlerAdapter也不是必須的。最起碼我沒有驗證成功過這個。我的Spring版本是4.0.3。
? ? ? ? ?Aop之所以有的人說攔截不到Controller是因為Controller被jdk代理了。我們只要把它交給cglib代理就可以了。
第一步定義兩個注解:
package?com.annotation;??import?java.lang.annotation.*;??/**?*自定義注解?攔截Controller?*/??@Target({ElementType.PARAMETER,?ElementType.METHOD})??
@Retention(RetentionPolicy.RUNTIME)??
@Documented??
public??@interface?SystemControllerLog?{??String?description()??default?"";??}??package?com.annotation;??import?java.lang.annotation.*;??/**?*自定義注解?攔截service?*/??@Target({ElementType.PARAMETER,?ElementType.METHOD})??
@Retention(RetentionPolicy.RUNTIME)??
@Documented??
public??@interface?SystemServiceLog?{??String?description()??default?"";??}
第二步創建一個切點類:
package?com.annotation;??import?com.model.Log;??
import?com.model.User;??
import?com.service.LogService;??
import?com.util.DateUtil;??
import?com.util.JSONUtil;??
import?com.util.SpringContextHolder;??
import?com.util.WebConstants;??
import?org.aspectj.lang.JoinPoint;??
import?org.aspectj.lang.annotation.*;??
import?org.slf4j.Logger;??
import?org.slf4j.LoggerFactory;??
import?org.springframework.stereotype.Component;??
import?org.springframework.web.context.request.RequestContextHolder;??
import?org.springframework.web.context.request.ServletRequestAttributes;??
import?javax.annotation.Resource;??
import?javax.servlet.http.HttpServletRequest;??
import?javax.servlet.http.HttpSession;??
import?java.lang.reflect.Method;??/**?*?切點類?*?@author?tiangai?*?@since?2014-08-05?Pm?20:35?*?@version?1.0?*/??
@Aspect??
@Component??
public??class?SystemLogAspect?{??//注入Service用于把日志保存數據庫??@Resource??private?LogService?logService;??//本地異常日志記錄對象??private??static??final?Logger?logger?=?LoggerFactory.getLogger(SystemLogAspect.?class);??//Service層切點??@Pointcut("@annotation(com.annotation.SystemServiceLog)")??public??void?serviceAspect()?{??}??//Controller層切點??@Pointcut("@annotation(com.annotation.SystemControllerLog)")??public??void?controllerAspect()?{??}??/**?*?前置通知?用于攔截Controller層記錄用戶的操作?*?*?@param?joinPoint?切點?*/??@Before("controllerAspect()")??public??void?doBefore(JoinPoint?joinPoint)?{??HttpServletRequest?request?=?((ServletRequestAttributes)?RequestContextHolder.getRequestAttributes()).getRequest();??HttpSession?session?=?request.getSession();??//讀取session中的用戶??User?user?=?(User)?session.getAttribute(WebConstants.CURRENT_USER);??//請求的IP??String?ip?=?request.getRemoteAddr();??try?{??//*========控制臺輸出=========*//??System.out.println("=====前置通知開始=====");??System.out.println("請求方法:"?+?(joinPoint.getTarget().getClass().getName()?+?"."?+?joinPoint.getSignature().getName()?+?"()"));??System.out.println("方法描述:"?+?getControllerMethodDescription(joinPoint));??System.out.println("請求人:"?+?user.getName());??System.out.println("請求IP:"?+?ip);??//*========數據庫日志=========*//??Log?log?=?SpringContextHolder.getBean("logxx");??log.setDescription(getControllerMethodDescription(joinPoint));??log.setMethod((joinPoint.getTarget().getClass().getName()?+?"."?+?joinPoint.getSignature().getName()?+?"()"));??log.setType("0");??log.setRequestIp(ip);??log.setExceptionCode(?null);??log.setExceptionDetail(?null);??log.setParams(?null);??log.setCreateBy(user);??log.setCreateDate(DateUtil.getCurrentDate());??//保存數據庫??logService.add(log);??System.out.println("=====前置通知結束=====");??}??catch?(Exception?e)?{??//記錄本地異常日志??logger.error("==前置通知異常==");??logger.error("異常信息:{}",?e.getMessage());??}??}??/**?*?異常通知?用于攔截service層記錄異常日志?*?*?@param?joinPoint?*?@param?e?*/??@AfterThrowing(pointcut?=?"serviceAspect()",?throwing?=?"e")??public??void?doAfterThrowing(JoinPoint?joinPoint,?Throwable?e)?{??HttpServletRequest?request?=?((ServletRequestAttributes)?RequestContextHolder.getRequestAttributes()).getRequest();??HttpSession?session?=?request.getSession();??//讀取session中的用戶??User?user?=?(User)?session.getAttribute(WebConstants.CURRENT_USER);??//獲取請求ip??String?ip?=?request.getRemoteAddr();??//獲取用戶請求方法的參數并序列化為JSON格式字符串??String?params?=?"";??if?(joinPoint.getArgs()?!=??null?&&?joinPoint.getArgs().length?>?0)?{??for?(?int?i?=?0;?i?<?joinPoint.getArgs().length;?i++)?{??params?+=?JSONUtil.toJsonString(joinPoint.getArgs()[i])?+?";";??}??}??try?{??/*========控制臺輸出=========*/??System.out.println("=====異常通知開始=====");??System.out.println("異常代碼:"?+?e.getClass().getName());??System.out.println("異常信息:"?+?e.getMessage());??System.out.println("異常方法:"?+?(joinPoint.getTarget().getClass().getName()?+?"."?+?joinPoint.getSignature().getName()?+?"()"));??System.out.println("方法描述:"?+?getServiceMthodDescription(joinPoint));??System.out.println("請求人:"?+?user.getName());??System.out.println("請求IP:"?+?ip);??System.out.println("請求參數:"?+?params);??/*==========數據庫日志=========*/??Log?log?=?SpringContextHolder.getBean("logxx");??log.setDescription(getServiceMthodDescription(joinPoint));??log.setExceptionCode(e.getClass().getName());??log.setType("1");??log.setExceptionDetail(e.getMessage());??log.setMethod((joinPoint.getTarget().getClass().getName()?+?"."?+?joinPoint.getSignature().getName()?+?"()"));??log.setParams(params);??log.setCreateBy(user);??log.setCreateDate(DateUtil.getCurrentDate());??log.setRequestIp(ip);??//保存數據庫??logService.add(log);??System.out.println("=====異常通知結束=====");??}??catch?(Exception?ex)?{??//記錄本地異常日志??logger.error("==異常通知異常==");??logger.error("異常信息:{}",?ex.getMessage());??}??/*==========記錄本地異常日志==========*/??logger.error("異常方法:{}異常代碼:{}異常信息:{}參數:{}",?joinPoint.getTarget().getClass().getName()?+?joinPoint.getSignature().getName(),?e.getClass().getName(),?e.getMessage(),?params);??}??/**?*?獲取注解中對方法的描述信息?用于service層注解?*?*?@param?joinPoint?切點?*?@return?方法描述?*?@throws?Exception?*/??public??static?String?getServiceMthodDescription(JoinPoint?joinPoint)??throws?Exception?{??String?targetName?=?joinPoint.getTarget().getClass().getName();??String?methodName?=?joinPoint.getSignature().getName();??Object[]?arguments?=?joinPoint.getArgs();??Class?targetClass?=?Class.forName(targetName);??Method[]?methods?=?targetClass.getMethods();??String?description?=?"";??for?(Method?method?:?methods)?{??if?(method.getName().equals(methodName))?{??Class[]?clazzs?=?method.getParameterTypes();??if?(clazzs.length?==?arguments.length)?{??description?=?method.getAnnotation(SystemServiceLog.?class).description();??break;??}??}??}??return?description;??}??/**?*?獲取注解中對方法的描述信息?用于Controller層注解?*?*?@param?joinPoint?切點?*?@return?方法描述?*?@throws?Exception?*/??public??static?String?getControllerMethodDescription(JoinPoint?joinPoint)??throws?Exception?{??String?targetName?=?joinPoint.getTarget().getClass().getName();??String?methodName?=?joinPoint.getSignature().getName();??Object[]?arguments?=?joinPoint.getArgs();??Class?targetClass?=?Class.forName(targetName);??Method[]?methods?=?targetClass.getMethods();??String?description?=?"";??for?(Method?method?:?methods)?{??if?(method.getName().equals(methodName))?{??Class[]?clazzs?=?method.getParameterTypes();??if?(clazzs.length?==?arguments.length)?{??description?=?method.getAnnotation(SystemControllerLog.?class).description();??break;??}??}??}??return?description;??}??
}
?第三步把Controller的代理權交給cglib
在實例化ApplicationContext的時候需要加上
Xml代碼?
<!--?啟動對@AspectJ注解的支持?-->??
<aop:aspectj-autoproxy/>??
?在調用Controller的時候AOP發揮作用所以在SpringMVC的配置文件里加上
Xml代碼?
<!--通知spring使用cglib而不是jdk的來生成代理方法?AOP可以攔截到Controller->??
<aop:aspectj-autoproxy?proxy-target-class="true"?/>??
?第四步使用
?
Controller層的使用
Java代碼
/**?*?刪除用戶?*?*?@param?criteria?條件?*?@param?id???????id?*?@param?model????模型?*?@return?數據列表?*/??@RequestMapping(value?=?"/delete")??//此處為記錄AOP攔截Controller記錄用戶操作??@SystemControllerLog(description?=?"刪除用戶")??public?String?del(Criteria?criteria,?String?id,?Model?model,?HttpSession?session)?{??try?{??User?user?=?(User)?session.getAttribute(WebConstants.CURRENT_USER);??if?(?null?!=?user)?{??if?(user.getId().equals(id))?{??msg?=?"您不可以刪除自己!";??criteria?=?userService.selectByCriteriaPagination(criteria);??}??else?{??//刪除數據并查詢出數據??criteria?=?userService.delete(id,?criteria);??msg?=?"刪除成功!";??}??}??}??catch?(Exception?e)?{??msg?=?"刪除失敗!";??}??finally?{??model.addAttribute("msg",?msg);??model.addAttribute("criteria",?criteria);??}??//跳轉列表頁??return?"user/list";??}
?Service層的使用
/**?*?按照分頁查詢?*?@param?criteria?*?@return?*/??//此處為AOP攔截Service記錄異常信息。方法不需要加try-catch??@SystemServiceLog(description?=?"查詢用戶")??public?Criteria<User>?selectByCriteriaPagination(Criteria<User>?criteria)??{??criteria.getList().get(0).getAccount();??//查詢總數??long?total=userMapper.countByCriteria(criteria);??//設置總數??criteria.setRowCount(total);??criteria.setList(userMapper.selectByCriteriaPagination(criteria));??return??criteria;??}
效果圖
?
用戶操作:
?異常
文章來源http://blog.csdn.net/czmchen/article/details/42392985
轉載于:https://my.oschina.net/91jason/blog/611211
總結
以上是生活随笔為你收集整理的SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。