激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

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

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

服務器之家 - 編程語言 - Java教程 - Spring AOP + 注解實現統一注解功能

Spring AOP + 注解實現統一注解功能

2021-04-27 14:09hry2015 Java教程

本文我們通過Spring AOP和Java的自定義注解來實現日志的插入功能,非常不錯,具有一定的參考借鑒價值,需要的朋友一起看看吧

1. 概述

在一般系統中,當我們做了一些重要的操作時,如登陸系統,添加用戶,刪除用戶等操作時,我們需要將這些行為持久化。本文我們通過spring aop和java的自定義注解來實現日志的插入。此方案對原有業務入侵較低,實現較靈活

2. 日志的相關類定義

我們將日志抽象為以下兩個類:功能模塊和操作類型

使用枚舉類定義功能模塊類型moduletype,如學生、用戶模塊

?
1
2
3
4
5
6
7
8
9
10
11
12
public enum moduletype {
  default("1"), // 默認值
  student("2"),// 學生模塊
  teacher("3"); // 用戶模塊
  private moduletype(string index){
    this.module = index;
  }
  private string module;
  public string getmodule(){
    return this.module;
  }
}

使用枚舉類定義操作的類型:eventtype。如登陸、添加、刪除、更新、刪除等

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public enum eventtype {
  default("1", "default"), add("2", "add"), update("3", "update"), delete_single("4", "delete-single"),
  login("10","login"),login_out("11","login_out");
 
  private eventtype(string index, string name){
    this.name = name;
    this.event = index;
  }
  private string event;
  private string name;
  public string getevent(){
    return this.event;
  }
 
  public string getname() {
    return name;
  }
}

3. 定義日志相關的注解

3.1. @logenable

這里我們定義日志的開關量,類上只有這個值為true,這個類中日志功能才開啟

?
1
2
3
4
5
6
7
8
9
10
@documented
@retention(retentionpolicy.runtime)
@target({elementtype.type})
public @interface logenable {
  /**
   * 如果為true,則類下面的logevent啟作用,否則忽略
   * @return
   */
  boolean logenable() default true;
}

3.2. @logevent

這里定義日志的詳細內容。如果此注解注解在類上,則這個參數做為類全部方法的默認值。如果注解在方法上,則只對這個方法啟作用

?
1
2
3
4
5
6
7
8
@documented
@retention(retentionpolicy.runtime)
@target({java.lang.annotation.elementtype.method, elementtype.type})
public @interface logevent {
  moduletype module() default moduletype.default; // 日志所屬的模塊
  eventtype event() default eventtype.default; // 日志事件類型
  string desc() default ""; // 描述信息
}

3.3. @logkey

此注解如果注解在方法上,則整個方法的參數以json的格式保存到日志中。如果此注解同時注解在方法和類上,則方法上的注解會覆蓋類上的值。

?
1
2
3
4
5
6
7
8
@target({elementtype.field,elementtype.parameter})
@retention(retentionpolicy.runtime)
@documented
public @interface logkey {
   string keyname() default ""; // key的名稱
   boolean isuserid() default false; // 此字段是否是本次操作的userid,這里略
   boolean islog() default true; // 是否加入到日志中
}

4. 定義日志處理類

4.1. logadmmodel

定義保存日志信息的類

?
1
2
3
4
5
6
7
8
9
10
11
public class logadmmodel {
  private long id;
  private string userid; // 操作用戶
  private string username;
  private string admmodel; // 模塊
  private string admevent; // 操作
  private date createdate; // 操作內容
  private string admoptcontent; // 操作內容
  private string desc; // 備注
  set/get略
}

4.2. ilogmanager

定義日志處理的接口類ilogmanager

我們可以將日志存入數據庫,也可以將日志發送到開中間件,如果redis, mq等等。每一種日志處理類都是此接口的實現類

?
1
2
3
4
5
6
7
public interface ilogmanager {
  /**
   * 日志處理模塊
   * @param paramlogadmbean
   */
  void deallog(logadmmodel paramlogadmbean);
}

4.3. dblogmanager

ilogmanager實現類,將日志入庫。這里只模擬入庫

?
1
2
3
4
5
6
7
@service
public class dblogmanager implements ilogmanager {
  @override
  public void deallog(logadmmodel paramlogadmbean) {
    system.out.println("將日志存入數據庫,日志內容如下: " + json.tojsonstring(paramlogadmbean));
  }
}

5. aop的配置

5.1. logaspect定義aop類

使用@aspect注解此類

使用@pointcut定義要攔截的包及類方法

我們使用@around定義方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@component
@aspect
public class logaspect {
  @autowired
  private loginfogeneration loginfogeneration;
 
  @autowired
  private ilogmanager logmanager;
 
  @pointcut("execution(* com.hry.spring.mvc.aop.log.service..*.*(..))")
  public void managerlogpoint() {
  }
 
  @around("managerlogpoint()")
  public object aroundmanagerlogpoint(proceedingjoinpoint jp) throws throwable {
  ….
  }
}

aroundmanagerlogpoint:主方法的主要業務流程

1. 檢查攔截方法的類是否被@logenable注解,如果是,則走日志邏輯,否則執行正常的邏輯

2. 檢查攔截方法是否被@logevent,如果是,則走日志邏輯,否則執行正常的邏輯

3. 根據獲取方法上獲取@logevent 中值,生成日志的部分參數。其中定義在類上@logevent 的值做為默認值

4. 調用loginfogeneration的processingmanagerlogmessage填充日志中其它的參數,做個方法我們后面再講

5. 執行正常的業務調用

6. 如果執行成功,則logmanager執行日志的處理(我們這里只記錄執行成功的日志,你也可以定義記錄失敗的日志)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
@around("managerlogpoint()")
    public object aroundmanagerlogpoint(proceedingjoinpoint jp) throws throwable {
 
      class target = jp.gettarget().getclass();
      // 獲取logenable
      logenable logenable = (logenable) target.getannotation(logenable.class);
      if(logenable == null || !logenable.logenable()){
        return jp.proceed();
      }
 
      // 獲取類上的logevent做為默認值
      logevent logeventclass = (logevent) target.getannotation(logevent.class);
      method method = getinvokedmethod(jp);
      if(method == null){
        return jp.proceed();
      }
 
      // 獲取方法上的logevent
      logevent logeventmethod = method.getannotation(logevent.class);
      if(logeventmethod == null){
        return jp.proceed();
      }
 
      string optevent = logeventmethod.event().getevent();
      string optmodel = logeventmethod.module().getmodule();
      string desc = logeventmethod.desc();
 
      if(logeventclass != null){
        // 如果方法上的值為默認值,則使用全局的值進行替換
        optevent = optevent.equals(eventtype.default) ? logeventclass.event().getevent() : optevent;
        optmodel = optmodel.equals(moduletype.default) ? logeventclass.module().getmodule() : optmodel;
      }
 
      logadmmodel logbean = new logadmmodel();
      logbean.setadmmodel(optmodel);
      logbean.setadmevent(optevent);
      logbean.setdesc(desc);
      logbean.setcreatedate(new date());
      loginfogeneration.processingmanagerlogmessage(jp,
          logbean, method);
      object returnobj = jp.proceed();
 
      if(optevent.equals(eventtype.login)){
        //todo 如果是登錄,還需要根據返回值進行判斷是不是成功了,如果成功了,則執行添加日志。這里判斷比較簡單
        if(returnobj != null) {
          this.logmanager.deallog(logbean);
        }
      }else {
        this.logmanager.deallog(logbean);
      }
      return returnobj;
    }
 
    /**
     * 獲取請求方法
     *
     * @param jp
     * @return
     */
    public method getinvokedmethod(joinpoint jp) {
      // 調用方法的參數
      list classlist = new arraylist();
      for (object obj : jp.getargs()) {
        classlist.add(obj.getclass());
      }
      class[] argscls = (class[]) classlist.toarray(new class[0]);
 
      // 被調用方法名稱
      string methodname = jp.getsignature().getname();
      method method = null;
      try {
        method = jp.gettarget().getclass().getmethod(methodname, argscls);
      } catch (nosuchmethodexception e) {
        e.printstacktrace();
      }
      return method;
    }
  }

6. 將以上的方案在實際中應用的方案

這里我們模擬學生操作的業務,并使用上文注解應用到上面并攔截日志

6.1. istudentservice

業務接口類,執行一般的crud

?
1
2
3
4
5
6
public interface istudentservice {
  void deletebyid(string id, string a);
  int save(studentmodel studentmodel);
  void update(studentmodel studentmodel);
  void querybyid(string id);
}

6.2. studentserviceimpl:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@logenable : 啟動日志攔截
類上@logevent定義所有的模塊
方法上@logeven定義日志的其它的信息
@service
@logenable // 啟動日志攔截
@logevent(module = moduletype.student)
public class studentserviceimpl implements istudentservice {
  @override
  @logevent(event = eventtype.delete_single, desc = "刪除記錄") // 添加日志標識
  public void deletebyid(@logkey(keyname = "id") string id, string a) {
    system.out.printf(this.getclass() + "deletebyid id = " + id);
  }
  @override
  @logevent(event = eventtype.add, desc = "保存記錄") // 添加日志標識
  public int save(studentmodel studentmodel) {
    system.out.printf(this.getclass() + "save save = " + json.tojsonstring(studentmodel));
    return 1;
  }
  @override
  @logevent(event = eventtype.update, desc = "更新記錄") // 添加日志標識
  public void update(studentmodel studentmodel) {
    system.out.printf(this.getclass() + "save update = " + json.tojsonstring(studentmodel));
  }
  // 沒有日志標識
  @override
  public void querybyid(string id) {
    system.out.printf(this.getclass() + "querybyid id = " + id);
  }
}

執行測試類,打印如下信息,說明我們日志注解配置啟作用了:

將日志存入數據庫,日志內容如下:

?
1
{"admevent":"4","admmodel":"1","admoptcontent":"{\"id\":\"1\"}","createdate":1525779738111,"desc":"刪除記錄"}

7. 代碼

以上的詳細的代碼見下面

原文鏈接:https://blog.csdn.net/hry2015/article/details/80244765

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 成人免费毛片明星色大师 | 中国洗澡偷拍在线播放 | 爱看久久 | 久久综合婷婷香五月 | 亚洲小视频在线 | 在线看日本 | 久久97超碰 | 精品黑人一区二区三区国语馆 | 国产无遮挡成人免费视频 | 欧美a级在线免费观看 | 91高清免费 | 色淫影院 | 国产在线精品一区二区三区 | 一级大片视频 | 本站只有精品 | 国产精品热 | 精品久久久久久久久久 | 国产自在自线午夜精品视频在 | 久久久在线 | 国产精品久久久久久影院8一贰佰 | 亚洲免费高清 | 国av在线 | 国产精品一二三区在线观看 | 国产亚洲欧美日韩在线观看不卡 | h网站在线观看 | 一级做a爱视频 | 天天天干夜夜夜操 | 欧美久久久久久久久 | 天天色宗合 | 美女黄影院 | 国内精品免费一区二区2001 | www69xxxxx| 手机免费看一级片 | 欧美一级黄色录像片 | 日本高清黄色片 | 一区二区三区无码高清视频 | 一级黄色国产视频 | 亚洲免费片 | 99最新地址| 性 毛片| 久久久久久免费免费 |