aop註解方式實現全域性日誌管理方法

aop註解方式實現全域性日誌管理方法

1:日誌實體類


public class SysLog {
/** */
private Integer id;
/** 日誌描述*/
private String description;
/** 執行的方法*/
private String method;
/** 日誌型別 0:操作日誌;1:異常日誌*/
private Integer logType;
/** 客戶端請求的ip地址*/
private String requestIp;
/** 異常程式碼*/
private String exceptionCode;
/** 異常詳細資訊*/
private String exceptionDetail;
/** 請求引數*/
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 {
/** 要執行的操作型別比如:add操作 **/ 
public String operationType() default ""; 
/** 要執行的具體操作比如:新增使用者 **/ 
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 建立時間:2017-3-31 
* @desc 切點類 
*
*/
@Aspect
@Component
public class SystemLogAspect {
//注入Service用於把日誌儲存資料庫 
@Resource 
private SysLogService systemLogService;
private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect. class); 
//Controller層切點 
//第一個*代表所有的返回值型別
//第二個*代表所有的類
//第三個*代表類所有方法
//最後一個..代表所有的引數。
@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("==========執行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); 
//*========資料庫日誌=========*// 
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);
//儲存資料庫 
systemLogService.insert(log); 
System.out.println("=====controller前置通知結束====="); 
} 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("請求引數:"   params); 
//==========資料庫日誌========= 
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); 
//儲存資料庫 
systemLogService.insert(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); 
} 
}

5:在controller裡面


/**
* 根據使用者名稱去找密碼 判斷使用者名稱和密碼是否正確
* @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;
}

對於想要了解其他三種通知的可以參考這篇博文:點選開啟連結

這樣使用者在訪問後臺時,不管是正常訪問還是出現bug資料庫都有記錄

以上這篇aop註解方式實現全域性日誌管理方法就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援指令碼之家。

您可能感興趣的文章:

springMVC自定義註解,用AOP來實現日誌記錄的方法Spring AOP 自定義註解的實現程式碼使用Spring的註解方式實現AOP例項spring中AOP 註解開發示例詳解關於spring中aop的註解實現方法例項詳解spring自定義註解實現攔截器的實現方法spring AOP自定義註解方式實現日誌管理的例項講解