1. 程式人生 > >使用Spring AOP 來記錄使用者操作日誌並存儲到資料庫中

使用Spring AOP 來記錄使用者操作日誌並存儲到資料庫中

之前要做一個記錄使用者操作的日誌記錄,找了很多方法,最後選擇使用spring AOP來實現。由於是要記錄使用者操作的日誌,所以我使用的是返回通知(@AfterReturning),只有在前端呼叫了我後端的介面併成功返回,才呼叫我的切面方法記錄使用者的操作儲存到資料庫中。

LogAnnotation.java

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

import org.springframework.data.mongodb.core.mapping.Document; 

/**
 * 日誌
 * @author **
 *
 */
@Target({ElementType.PARAMETER,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Document
public @interface LogAnnotation {
	
    /** 日誌描述 */
    String description() default "";
 
    /** 業務型別 */
    int bizID();
} 

切面類

LogAspect.java

@Aspect
@Component
@SuppressWarnings({ "unchecked", "unused", "rawtypes" })
public class LogAspect {
	// 注入service,用來將日誌資訊儲存在資料庫 這是我的service,你只需要注入你自己的service就行
	@Resource
	private OprLogDaoService oprLogDaoService;

    //在**處填入你的LogAnnotation所在的包
    //此程式碼是攔截所有使用了LogAnnotation註解的介面
	@Pointcut("@annotation(**.LogAnnotation)")
	// 定義一個切點
	private void accAspect() {
	}

    //返回通知
    @AfterReturning(pointcut= "accAspect()",returning="result")
	public void around(JoinPoint joinPoint, Object result) throws Throwable {

		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		String classType = joinPoint.getTarget().getClass().getName();
		Class<?> clazz = Class.forName(classType);
		String clazzName = clazz.getName();
		// 攔截的方法名稱。當前正在執行的方法
		String methodName = joinPoint.getSignature().getName();
		// 獲取方法的引數
		Object[] args = joinPoint.getArgs();
		

		// 獲取傳入引數的鍵值對
		Map<String, Object> map = (Map<String, Object>)         
        LogUtil.getFieldsName(this.getClass(), clazzName, methodName,
				args);
		// 將request中的引數轉化為鍵值對,方便取出
		Map<String, Object> map2 = (Map<String, Object>) map.get("request");
		String resultArgs = result.toString();
		// 獲取返回方法的引數
		JSONObject jasonObject = JSONObject.fromObject(resultArgs);
		Map mapResult = (Map) jasonObject;
		//將返回的result引數取出
		Map<String, Object> res = (Map<String, Object>) mapResult.get("result");
        //這樣傳入的引數和返回的引數都已變成Map物件
        //通過直接 .get("欄位名")的方式將對應的欄位值取出
        //比如取出使用者的使用者名稱ID
        Integer userID = (Integer) mapResult.get("userID");
		
			// 常見日誌實體物件
			OprLog oprLog = new OprLog();
            
            //根據自己定義的實體類的屬性將資料填入
            OprLog.setUserID(userID);
            OprLog.set...();        
			// 儲存進資料庫
            //開頭定義的service,這邊使用你自己的service就行了
			oprLogDaoService.addLog(oprLog);
		
	}

接下來就是在controller上添加註解了

只需要在介面上添加註解@LogAnnotation(description = "日誌記錄", bizID = 1)  bizID是我自己定義的你也可以定義成String型別,寫上方法名。

@LogAnnotation(description = "日誌記錄", bizID = 1)
@RequestMapping(value = "/Test", method = RequestMethod.POST)

獲取自定義註解內容的方法

可以直接在註解上寫使用者的操作內容(修改、新增之類的)

/**
	 * 獲取註解內容
	 * @param joinPoint
	 * @return
	 * @throws Exception
	 */
	public static Integer getMthodRemark(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[] method = targetClass.getMethods();
		Integer bizId = null;//此處可以根據你想要的型別來修改
		for (Method m : method) {  
            if (m.getName().equals(methodName)) {  
                Class[] tmpCs = m.getParameterTypes();  
                if (tmpCs.length == arguments.length) {  
                    ControllerLogAnnotation cla = m.getAnnotation(ControllerLogAnnotation.class);  
                    if (cla != null) {  
                        bizId = cla.bizID();  
                    }  
                    break;  
                }  
            }  
        }  
        return bizId;  
    }  
}

另外還有一些工具類的方法

這個是轉換成map物件的方法

	public static Map<String, Object> getFieldsName(Class cls, String clazzName, String methodName, Object[] args)throws Exception {
		Map<String, Object> map = new HashMap<String, Object>();

		ClassPool pool = ClassPool.getDefault();
		ClassClassPath classPath = new ClassClassPath(cls);
		pool.insertClassPath(classPath);

		CtClass cc = pool.get(clazzName);
		CtMethod cm = cc.getDeclaredMethod(methodName);
		MethodInfo methodInfo = cm.getMethodInfo();
		CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
		LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
		if (attr == null) {
			// exception
		}
		int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
		for (int i = 0; i < cm.getParameterTypes().length; i++) {
			map.put(attr.variableName(i + pos), args[i]);// paramNames即引數名
		}
		return map;
	}

最後在springMVCxml中加入

<context:component-scan
        //LogAspect 在aop中
		base-package="切面所在的包例如(a.b.aop)"></context:component-scan>

	<aop:aspectj-autoproxy expose-proxy="true"></aop:aspectj-autoproxy>

另外還有一些依賴的jar包,需要的jar包都可以在百度中搜索到,用的時候沒有可以在百度查詢jar包依賴,放在maven專案中的pom.xml檔案中。

相關推薦

使用Spring AOP 記錄使用者操作日誌並存資料庫

之前要做一個記錄使用者操作的日誌記錄,找了很多方法,最後選擇使用spring AOP來實現。由於是要記錄使用者操作的日誌,所以我使用的是返回通知(@AfterReturning),只有在前端呼叫了我後端的介面併成功返回,才呼叫我的切面方法記錄使用者的操作儲存到資料庫中。 L

自定義註解+Spring AOP實現記錄使用者操作日誌

一、背景     專案中需要對使用者的各種操作做詳細的操作日誌記錄,需要記錄使用者操作的操作模組、具體操作以及操作的資料記錄ID等。     若寫一個方法去儲存操作,則需要每次手動去呼叫。由於是非業務性的操作,並且大量的重複操作,Spring AOP就能很好的解決這個問題。

spring boot log4j2 自定義級別日誌並存,超詳細

由於需要一些業務日誌,本來是用的註解,然後用spring aop獲取註解的形式來記錄,但是由於最開始的時候沒有統一controller 方法的引數,引數資料,細緻到id不太好記錄。於是想到了log4j的形式儲存資料庫,但log4j的形式記錄會記錄所有級別的日誌,即使指定日誌級

[轉]spring boot 攔截器 或 Spring AOP 方式記錄請求日誌

選擇使用攔截器實現,在實現中遇到兩個個問題: a. POST請求 @RequestBody 傳的引數不知怎麼獲取? b. 返回結果如何獲取? c.攔截器中service 無法注入;(已解決) 不知道有沒有人遇到這種情況,攔截器沒有解決上述問題,後來使用 spring

Spring AOP面向切面程式設計之日誌記錄

實際專案中我們往往需要將一些重要的操作,以日誌的形式進行儲存,當機器宕機的時候,可以通過查詢日誌,定位出錯位置,方便恢復。 1:首先匯入spring支援的AOP架包 2:編寫將要進行切面工作的類 /** * */ package com.zhiyou100.aspect; i

spring aop切點記錄日誌到mongodb 註解版

package com.jk.aspectj; import java.util.Date; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtil

spring aop實現(使用者操作記錄,一場記錄

第一步定義兩個註解: Java程式碼 複製程式碼 package com.annotation; import java.lang.annotation.*; /** *自定義註解 攔截Controller */ @Target({ElementType.PA

Spring Boot 使用攔截器記錄使用者操作日誌

前言 上篇檔案主要是講了如何使用aop記錄使用者操作日誌,這篇檔案將介紹如何使用攔截器記錄操作日誌 匯入依賴 在處理請求引數時需要用到Json,其他依賴請檢視原始碼 <!-- Json解析 --> <dependency> <

Spring Boot從入門到實戰:整合AOPLog記錄介面訪問日誌

日誌是一個Web專案中必不可少的部分,藉助它我們可以做許多事情,比如問題排查、訪問統計、監控告警等。一般通過引入slf4j的一些實現框架來做日誌功能,如log4j,logback,log4j2,其效能也是依次增強。在springboot中,預設使用的框架是logback。我們經常需要在方法開頭或結尾加日誌記錄

javaWEB SSM AOP+註解保存操作日誌

java aop aop保存日誌 aop異步保存日誌 javaweb 本篇文章的誕生離不開這篇文章的作者:http://blog.csdn.net/czmchen/article/details/42392985。前言操作日誌在javaWeb的業務系統中是在是太常見的功能了,主要記錄用戶再

MySQL記錄使用者操作日誌

有時,我們想追蹤某個資料庫操作記錄,如想找出是誰操作了某個表(比如誰將欄位名改了)。 二進位制日誌記錄了操作記錄,執行緒號等資訊,但是卻沒有記錄使用者資訊,因此需要結合init-connect來實現追蹤。 init-connect,在每次連線的初始化階段,記錄下這個連線的使用者,和conne

Spring AOP 自定義註解實現日誌管理

目錄 一、配置檔案 二、新建一個日誌實體類Log 三、編寫 service 層 四、編寫 service 層的實現 serviceimpl 五、自定義註解類 六、編寫切面類 七、spring + aop 需要的 jar 包 部落格的程式碼是基於 SSM 環境編寫的

spring-AOP+自定義註解實現日誌管理(註解方式實現)

一、場景 後臺管理系統中,管理員作業系統時生成日誌儲存在資料庫中。 二、實現 1、jar包依賴 <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop --> <dependency&

關於系統記錄使用者操作日誌及物件變更問題

mysql匯入出錯懷疑是特殊字元導致一道白光回到白雲城看看經驗149級54的經驗只要能找到類似的精英怪聚集點相信一天時間就能升到150級到時候裝備上我的仙器烈魂劍哈哈哈簡直拉風到了極點啊mysql匯入出錯懷疑是特殊字元導

利用Spring AOP自定義註解解決日誌和簽名校驗

一、需解決的問題 部分API有簽名引數(signature),Passport首先對簽名進行校驗,校驗通過才會執行實現方法。     第一種實現方式(Origin):在需要簽名校驗的接口裡寫校驗的程式碼,例如: boolean isValid = accountService.val

PHP記錄使用者操作日誌記錄

<?php header("Content-type: text/html; charset=utf-8"); error_reporting(0);//關閉所有的錯誤資訊,不會顯示,如果

log4j用儲存使用者操作日誌

開發條件:log4j.properties 配置檔案  +sqlserver資料庫所做功能:能夠儲存使用者在登入狀態下所做的操作準備步驟:1.log4j.properties配置檔案中的資訊:log4j.rootLogger=debug,DB,console#log4j.lo

使用Spring MVC攔截器管理操作日誌

通過攔截器記錄操作日誌,將操作日誌儲存到資料庫中,實現這個功能需要我們將curd操作的URL規範化,比如:新增是以add或者insert開始,修改是update開頭,刪除則是delete開頭。 第一步:編寫攔截器類,程式碼如下: package com.

基於Springboot的Spring AOP學習記錄

前段時間各種面試,aop問到就蒙逼,所以結合新學的springboot重新理一下這玩意兒,很重要啊 一、AOP概述 AOP(面對切面程式設計)是對OOP(面向物件程式設計)的補充,總體來說,程式設計正規化包含:面向過程程式設計、面向物件程式設計、函數語言

JAVA記錄使用者操作日誌

import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io