aop注解方式實現(xiàn)全局日志管理方法
1:日志實體類
public class SysLog {
/** */
private Integer id;
/** 日志描述*/
private String description;
/** 執(zhí)行的方法*/
private String method;
/** 日志類型 0:操作日志;1:異常日志*/
private Integer logType;
/** 客戶端請求的ip地址*/
private String requestIp;
/** 異常代碼*/
private String exceptionCode;
/** 異常詳細信息*/
private String exceptionDetail;
/** 請求參數(shù)*/
private String params;
/** 操作人*/
private String createBy;
/** 操作時間*/
private String createDate;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public Integer getLogType() {
return logType;
}
public void setLogType(Integer logType) {
this.logType = logType;
}
public String getRequestIp() {
return requestIp;
}
public void setRequestIp(String requestIp) {
this.requestIp = requestIp;
}
public String getExceptionCode() {
return exceptionCode;
}
public void setExceptionCode(String exceptionCode) {
this.exceptionCode = exceptionCode;
}
public String getExceptionDetail() {
return exceptionDetail;
}
public void setExceptionDetail(String exceptionDetail) {
this.exceptionDetail = exceptionDetail;
}
public String getParams() {
return params;
}
public void setParams(String params) {
this.params = params;
}
public String getCreateBy() {
return createBy;
}
public void setCreateBy(String createBy) {
this.createBy = createBy;
}
public String getCreateDate() {
return createDate;
}
public void setCreateDate(String createDate) {
this.createDate = createDate;
}
}
2:maven需要的jar
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.7.4</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.7.4</version> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.1_3</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.2.5.RELEASE</version> </dependency>
這里要求項目使用的是jdk1.7
3:springServlet-mvc.xml
<!--proxy-target-class="true"強制使用cglib代理 如果為false則spring會自動選擇--> <aop:aspectj-autoproxy proxy-target-class="true"/>
加上proxy-target-class="true"是為了可以攔截controller里面的方法
4:定義切面,我這里主要寫前置通知和異常通知
下面開始自定義注解
import java.lang.annotation.*;
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
/** 要執(zhí)行的操作類型比如:add操作 **/
public String operationType() default "";
/** 要執(zhí)行的具體操作比如:添加用戶 **/
public String operationName() default "";
}
切面類
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
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 com.gtcity.user.model.SysLog;
import com.gtcity.user.model.SysUser;
import com.gtcity.user.service.SysLogService;
/**
* @author panliang
* @version 創(chuàng)建時間:2017-3-31
* @desc 切點類
*
*/
@Aspect
@Component
public class SystemLogAspect {
//注入Service用于把日志保存數(shù)據(jù)庫
@Resource
private SysLogService systemLogService;
private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect. class);
//Controller層切點
//第一個*代表所有的返回值類型
//第二個*代表所有的類
//第三個*代表類所有方法
//最后一個..代表所有的參數(shù)。
@Pointcut("execution (* com.gtcity.web.controller..*.*(..))")
public void controllerAspect() {
}
/**
*
* @author: panliang
* @time:2017-3-31 下午2:22:16
* @param joinPoint 切點
* @describtion:前置通知 用于攔截Controller層記錄用戶的操作
*/
@Before("controllerAspect()")
public void doBefore(JoinPoint joinPoint) {
/* System.out.println("==========執(zhí)行controller前置通知===============");
if(logger.isInfoEnabled()){
logger.info("before " + joinPoint);
}*/
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
HttpSession session = request.getSession();
//讀取session中的用戶
SysUser user = (SysUser) session.getAttribute("user");
if(user==null){
user=new SysUser();
user.setUserName("非注冊用戶");
}
//請求的IP
String ip = request.getRemoteAddr();
try {
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 operationType = "";
String operationName = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
operationType = method.getAnnotation(Log.class).operationType();
operationName = method.getAnnotation(Log.class).operationName();
break;
}
}
}
//*========控制臺輸出=========*//
System.out.println("=====controller前置通知開始=====");
System.out.println("請求方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")+"."+operationType);
System.out.println("方法描述:" + operationName);
System.out.println("請求人:" + user.getUserName());
System.out.println("請求IP:" + ip);
//*========數(shù)據(jù)庫日志=========*//
SysLog log = new SysLog();
log.setDescription(operationName);
log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")+"."+operationType);
log.setLogType(0);
log.setRequestIp(ip);
log.setExceptionCode(null);
log.setExceptionDetail( null);
log.setParams( null);
log.setCreateBy(user.getUserName());
log.setCreateDate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
log.setRequestIp(ip);
//保存數(shù)據(jù)庫
systemLogService.insert(log);
System.out.println("=====controller前置通知結(jié)束=====");
} catch (Exception e) {
//記錄本地異常日志
logger.error("==前置通知異常==");
logger.error("異常信息:{}", e.getMessage());
}
}
/**
*
* @author: panliang
* @time:2017-3-31 下午2:24:36
* @param joinPoint 切點
* @describtion:異常通知 用于攔截記錄異常日志
*/
@AfterThrowing(pointcut = "controllerAspect()", throwing="e")
public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
HttpSession session = request.getSession();
//讀取session中的用戶
SysUser user = (SysUser) session.getAttribute("user");
if(user==null){
user=new SysUser();
user.setUserName("非注冊用戶");
}
//請求的IP
String ip = request.getRemoteAddr();
String params = "";
if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) {
params=Arrays.toString(joinPoint.getArgs());
}
try {
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 operationType = "";
String operationName = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
operationType = method.getAnnotation(Log.class).operationType();
operationName = method.getAnnotation(Log.class).operationName();
break;
}
}
}
/*========控制臺輸出=========*/
System.out.println("=====異常通知開始=====");
System.out.println("異常代碼:" + e.getClass().getName());
System.out.println("異常信息:" + e.getMessage());
System.out.println("異常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")+"."+operationType);
System.out.println("方法描述:" + operationName);
System.out.println("請求人:" + user.getUserName());
System.out.println("請求IP:" + ip);
System.out.println("請求參數(shù):" + params);
//==========數(shù)據(jù)庫日志=========
SysLog log = new SysLog();
log.setDescription(operationName);
log.setExceptionCode(e.getClass().getName());
log.setLogType(1);
log.setExceptionDetail(e.getMessage());
log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));
log.setParams(params);
log.setCreateBy(user.getUserName());
log.setCreateDate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
log.setRequestIp(ip);
//保存數(shù)據(jù)庫
systemLogService.insert(log);
System.out.println("=====異常通知結(jié)束=====");
} catch (Exception ex) {
//記錄本地異常日志
logger.error("==異常通知異常==");
logger.error("異常信息:{}", ex.getMessage());
}
//==========記錄本地異常日志==========
logger.error("異常方法:{}異常代碼:{}異常信息:{}參數(shù):{}", joinPoint.getTarget().getClass().getName() + joinPoint.getSignature().getName(), e.getClass().getName(), e.getMessage(), params);
}
}
5:在controller里面
/**
* 根據(jù)用戶名去找密碼 判斷用戶名和密碼是否正確
* @author panliang
* @param request
* @param response
* @throws IOException
*/
@RequestMapping("/skipPage.do")
@Log(operationType="select操作:",operationName="用戶登錄")//注意:這個不加的話,這個方法的日志記錄不會被插入
public ModelAndView skipPage(HttpServletRequest request,HttpServletResponse response) throws IOException{
ModelAndView result=null;
String username = request.getParameter("email");
String password = request.getParameter("password");
int flag = sysUserService.login(request, username, password);
if(flag==1){//登錄成功
result=new ModelAndView("redirect:/login/dispacher_main.do");
}else if(flag==2){//用戶名不存在
result=new ModelAndView("redirect:/login/login.do?errorCode=1");
} else{//密碼不正確
result=new ModelAndView("redirect:/login/login.do?errorCode=2");
}
return result;
}
對于想要了解其他三種通知的可以參考這篇博文:點擊打開鏈接
這樣用戶在訪問后臺時,不管是正常訪問還是出現(xiàn)bug數(shù)據(jù)庫都有記錄

以上這篇aop注解方式實現(xiàn)全局日志管理方法就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java中優(yōu)先隊列PriorityQueue常用方法示例
這篇文章主要介紹了Java中優(yōu)先隊列PriorityQueue常用方法示例,PriorityQueue是一種特殊的隊列,滿足隊列的“隊尾進、隊頭出”條件,但是每次插入或刪除元素后,都對隊列進行調(diào)整,使得隊列始終構(gòu)成最小堆(或最大堆),需要的朋友可以參考下2023-09-09
Spring Boot+Jpa多數(shù)據(jù)源配置的完整步驟
這篇文章主要給大家介紹了關(guān)于Spring Boot+Jpa多數(shù)據(jù)源配置的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-01-01
Prometheus監(jiān)控Springboot程序的實現(xiàn)方法
這篇文章主要介紹了Prometheus監(jiān)控Springboot程序的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-03-03
如何利用Spring?Boot?監(jiān)控?SQL?運行情況
這篇文章主要介紹了如何利用Spring?Boot監(jiān)控SQL運行情況,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-07-07

