一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Spring AOP實現復雜的日志記錄操作(自定義注解)

Spring AOP實現復雜的日志記錄操作(自定義注解)

2022-01-20 00:55小草mlc Java教程

Spring AOP實現復雜的日志記錄操作(自定義注解),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

Spring AOP復雜的日志記錄(自定義注解)

做項目中,業務邏輯要求只要對數據庫數據進行改動的都需要記錄日志(增刪改),記錄的內容有操作者、操作的表名及表名稱、具體的操作,以及操作對應的數據。

首先想到的就是Spring 的AOP功能??墒墙涍^一番了解過后,發現一般的日志記錄,只能記錄一些簡單的操作,例如表名、表名稱等記錄不到。

于是想到了自定義注解的方法,把想要記錄的內容放在注解中,通過切入點來獲取注解參數,就能獲取自己想要的數據,記錄數據庫中。順著這個思路,在網上查找了一些相關資料,最終實現功能。話不多說,以下就是實現的思路及代碼:

第一步

在代碼中添加自定義注解,并且定義兩個屬性,一個是日志的描述(description),還有個是操作表類型(tableType),屬性參數可按需求改變。代碼如下:

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;  
/**
* ClassName: SystemServiceLog <br/>
* Function: AOP日志記錄,自定義注解 <br/>
* date: 2016年6月7日 上午9:29:01 <br/>
* @author lcma
* @version 
* @since JDK 1.7
*/
@Target({ElementType.PARAMETER, ElementType.METHOD})    
@Retention(RetentionPolicy.RUNTIME)    
@Documented  
public @interface SystemServiceLog {
/**
* 日志描述
*/
String description()  default ""; 

/**
* 操作表類型
*/
int tableType() default 0; 
}

第二步

定義切面類,獲取切面參數,保存數據庫具體代碼如下:

import java.lang.reflect.Method;
import java.util.Date; 
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; 
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; 

import com.iflytek.zhbs.common.annotation.SystemServiceLog;
import com.iflytek.zhbs.common.util.JacksonUtil;
import com.iflytek.zhbs.common.util.WebUtils;
import com.iflytek.zhbs.dao.BaseDaoI;
import com.iflytek.zhbs.domain.CmsAdmin;
import com.iflytek.zhbs.domain.CmsOperationLog; 

@Aspect
@Component
@SuppressWarnings("rawtypes")
public class SystemLogAspect {

@Resource
private BaseDaoI<CmsOperationLog> logDao;

  /**
   * 日志記錄
   */
  private static final Logger LOGGER = Logger.getLogger(SystemLogAspect.class);

   /**
    * Service層切點
    */
   @Pointcut("@annotation(com.iflytek.zhbs.common.annotation.SystemServiceLog)")    
   public void serviceAspect() {         
   }
   
   /**
   * doServiceLog:獲取注解參數,記錄日志. <br/>
   * @author lcma
   * @param joinPoint 切入點參數
   * @since JDK 1.7
   */
  @After("serviceAspect()") 
   public  void doServiceLog(JoinPoint joinPoint) {
  LOGGER.info("日志記錄");
       HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
       //獲取管理員用戶信息
  CmsAdmin admin = WebUtils.getAdminInfo(request);
        try {
           //數據庫日志
           CmsOperationLog log = new CmsOperationLog();
           log.setOperationType(getServiceMthodTableType(joinPoint));
           //獲取日志描述信息
           String content = getServiceMthodDescription(joinPoint);
           log.setContent(admin.getRealName() + content);
           log.setRemarks(getServiceMthodParams(joinPoint));
           log.setAdmin(admin);
           log.setCreateTime(new Date());
           logDao.save(log);
       }  catch (Exception e) {  
           LOGGER.error("異常信息:{}", e);
       }    
   }     
   
  /**
   * getServiceMthodDescription:獲取注解中對方法的描述信息 用于service層注解  . <br/>
   * @author lcma
   * @param joinPoint 切點 
   * @return 方法描述
   * @throws Exception 
   * @since JDK 1.7
   */
  private 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;
    }
  
  /**
   * getServiceMthodTableType:獲取注解中對方法的數據表類型 用于service層注解 . <br/>
   * @author lcma
   * @param joinPoint
   * @return
   * @throws Exception
   * @since JDK 1.7
   */
  private nt getServiceMthodTableType(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();
     int tableType = 0;
      for (Method method : methods) {
          if (method.getName().equals(methodName)) {
             Class[] clazzs = method.getParameterTypes();
              if (clazzs.length == arguments.length) {
              tableType = method.getAnnotation(SystemServiceLog.class).tableType();
                  break;
             }
         }
     }
      return tableType;
 }
  
  /**
   * getServiceMthodParams:獲取json格式的參數. <br/>
   * @author lcma
   * @param joinPoint
   * @return
   * @throws Exception
   * @since JDK 1.7
   */
  private String getServiceMthodParams(JoinPoint joinPoint)
          throws Exception {
     Object[] arguments = joinPoint.getArgs();
     String params = JacksonUtil.toJSon(arguments);
     return params;
 } 
}

需要注意的是,定義切點的時候,@Pointcut里面是自定義注解的路徑

每個切面傳遞的數據的都不一樣,最終決定,獲取切面的所有參數,轉成json字符串,保存到數據庫中。

第三步

在service需要記錄日志的地方進行注解,代碼如下:

@SystemServiceLog(description=Constants.ADMIN_SAVE_OPTIONS,tableType=Constants.ADMIM_TABLE_TYPE)

代碼圖片:

Spring AOP實現復雜的日志記錄操作(自定義注解)

在常量類里面配置自定義注解的參數內容:

Spring AOP實現復雜的日志記錄操作(自定義注解)Spring AOP實現復雜的日志記錄操作(自定義注解)

第四步

把切面類所在的包路徑添加到Spring注解自動掃描路徑下,并且啟動對@AspectJ注解的支持,代碼如下:

<!-- 啟動對@AspectJ注解的支持  --> 
<aop:aspectj-autoproxy proxy-target-class="true" />
<!-- 自動掃描包路徑  --> 
<context:component-scan base-package="com.iflytek.zhbs.common.aoplog" />
<context:component-scan base-package="com.iflytek.zhbs.service" />

最后數據庫記錄數據的效果如圖:

Spring AOP實現復雜的日志記錄操作(自定義注解)

OK,功能已經實現,初次寫博客,寫的不好的地方請諒解。

 

多個注解可以合并成一個,包括自定義注解

spring中有時候一個類上面標記很多注解。

實際上Java注解可以進行繼承(也就是把多個注解合并成1個)

比如說SpringMVC的注解

@RestController
@RequestMapping("/person")

可以合并為一個

@PathRestController("/user")

實現是:

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;
import org.springframework.core.annotation.AliasFor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RestController
@RequestMapping
public @interface PathRestController {
@AliasFor("path")
String[] value() default {};
@AliasFor("value")
String[] path() default {};
}

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/mlc1218559742/article/details/51778224

延伸 · 閱讀

精彩推薦
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數據的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網2942020-09-17
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩中求8032021-07-12
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經有好久沒有升過級了。升級完畢重啟之后,突然發現好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發現了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7482021-02-04
主站蜘蛛池模板: 4hu影院永久在线播放 | 久久无码AV亚洲精品色午夜麻豆 | 欧美摸胸 | 日日摸夜夜爽色婷婷91 | 国产精品人人视频 | 亚洲视频在线一区二区 | 99影视在线视频免费观看 | 亚洲精品在线免费观看视频 | 国产欧美va欧美va香蕉在线观 | 国产成人高清亚洲一区91 | 国产男女性特黄录像 | 成人精品亚洲 | 国产性片在线观看 | 免费看男人狂躁女人 | 古装一级毛片 | 小早川怜子息梦精在线播放 | 免费人成在线观看69式小视频 | 亚洲精品一区二区三区在线观看 | 色婷婷天天综合在线 | 饱满奶大30p | 欧美性欲 | 性啪啪chinese东北女人 | 欧美日韩国产一区二区三区伦 | 2020韩国r级理论片在线观看 | juliaann大战两个黑人 | 日韩在线观看网址 | 91精品国产一区 | 插入肥臀 | 国产宅男 | 精品久久久久免费极品大片 | 免费观看视频在线播放 | 亚洲精品一区制服丝袜 | 福利视频一区二区思瑞 | 美女被草哭 | 五月天淫| 日本mv精品中文字幕 | 99热这里只有精品国产在热久久 | 996热精品视频在线观看 | 喜马拉雅听书免费版 | 国产一区二区三区毛片 | 国产99精品|