国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

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

服務(wù)器之家 - 編程語言 - Java教程 - Spring AOP + 注解實(shí)現(xiàn)統(tǒng)一注解功能

Spring AOP + 注解實(shí)現(xiàn)統(tǒng)一注解功能

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

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

1. 概述

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

2. 日志的相關(guān)類定義

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
public enum moduletype {
  default("1"), // 默認(rèn)值
  student("2"),// 學(xué)生模塊
  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. 定義日志相關(guān)的注解

3.1. @logenable

這里我們定義日志的開關(guān)量,類上只有這個值為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

這里定義日志的詳細(xì)內(nèi)容。如果此注解注解在類上,則這個參數(shù)做為類全部方法的默認(rèn)值。如果注解在方法上,則只對這個方法啟作用

?
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

此注解如果注解在方法上,則整個方法的參數(shù)以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; // 操作內(nèi)容
  private string admoptcontent; // 操作內(nèi)容
  private string desc; // 備注
  set/get略
}

4.2. ilogmanager

定義日志處理的接口類ilogmanager

我們可以將日志存入數(shù)據(jù)庫,也可以將日志發(fā)送到開中間件,如果redis, mq等等。每一種日志處理類都是此接口的實(shí)現(xiàn)類

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

4.3. dblogmanager

ilogmanager實(shí)現(xiàn)類,將日志入庫。這里只模擬入庫

?
1
2
3
4
5
6
7
@service
public class dblogmanager implements ilogmanager {
  @override
  public void deallog(logadmmodel paramlogadmbean) {
    system.out.println("將日志存入數(shù)據(jù)庫,日志內(nèi)容如下: " + 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:主方法的主要業(yè)務(wù)流程

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

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

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

4. 調(diào)用loginfogeneration的processingmanagerlogmessage填充日志中其它的參數(shù),做個方法我們后面再講

5. 執(zhí)行正常的業(yè)務(wù)調(diào)用

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

?
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做為默認(rèn)值
      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){
        // 如果方法上的值為默認(rèn)值,則使用全局的值進(jìn)行替換
        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 如果是登錄,還需要根據(jù)返回值進(jìn)行判斷是不是成功了,如果成功了,則執(zhí)行添加日志。這里判斷比較簡單
        if(returnobj != null) {
          this.logmanager.deallog(logbean);
        }
      }else {
        this.logmanager.deallog(logbean);
      }
      return returnobj;
    }
 
    /**
     * 獲取請求方法
     *
     * @param jp
     * @return
     */
    public method getinvokedmethod(joinpoint jp) {
      // 調(diào)用方法的參數(shù)
      list classlist = new arraylist();
      for (object obj : jp.getargs()) {
        classlist.add(obj.getclass());
      }
      class[] argscls = (class[]) classlist.toarray(new class[0]);
 
      // 被調(diào)用方法名稱
      string methodname = jp.getsignature().getname();
      method method = null;
      try {
        method = jp.gettarget().getclass().getmethod(methodname, argscls);
      } catch (nosuchmethodexception e) {
        e.printstacktrace();
      }
      return method;
    }
  }

6. 將以上的方案在實(shí)際中應(yīng)用的方案

這里我們模擬學(xué)生操作的業(yè)務(wù),并使用上文注解應(yīng)用到上面并攔截日志

6.1. istudentservice

業(yè)務(wù)接口類,執(zhí)行一般的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 = "刪除記錄") // 添加日志標(biāo)識
  public void deletebyid(@logkey(keyname = "id") string id, string a) {
    system.out.printf(this.getclass() + "deletebyid id = " + id);
  }
  @override
  @logevent(event = eventtype.add, desc = "保存記錄") // 添加日志標(biāo)識
  public int save(studentmodel studentmodel) {
    system.out.printf(this.getclass() + "save save = " + json.tojsonstring(studentmodel));
    return 1;
  }
  @override
  @logevent(event = eventtype.update, desc = "更新記錄") // 添加日志標(biāo)識
  public void update(studentmodel studentmodel) {
    system.out.printf(this.getclass() + "save update = " + json.tojsonstring(studentmodel));
  }
  // 沒有日志標(biāo)識
  @override
  public void querybyid(string id) {
    system.out.printf(this.getclass() + "querybyid id = " + id);
  }
}

執(zhí)行測試類,打印如下信息,說明我們?nèi)罩咀⒔馀渲脝⒆饔昧耍?/p>

將日志存入數(shù)據(jù)庫,日志內(nèi)容如下:

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

7. 代碼

以上的詳細(xì)的代碼見下面

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

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 成人精品久久久 | 91仓库| 牛牛澡牛牛爽一区二区 | 国产在线第一页 | 国产精品久久久久久吹潮 | 久久国产免费 | 国产精品一二 | 国产精品视频免费观看 | 久久精品亚洲 | 欧美一级一 | 欧美日韩在线一区二区 | 黄片毛片在线观看 | 九九福利 | 日本一区二区视频 | 国产欧美日韩综合精品一区二区 | 国产成人一区二区三区 | 久久99精品国产.久久久久 | 成人毛片在线观看视频 | 欧美国产综合 | 国产91精品一区二区绿帽 | 久久99精品久久久久久久青青日本 | 日韩成人在线一区二区 | 婷婷天堂| 中文字幕日韩欧美 | 看亚洲a级一级毛片 | 亚洲日韩欧美一区二区在线 | 精品无码三级在线观看视频 | 中文字幕在线免费 | 亚洲狼人| 女男羞羞视频网站免费 | 91丝袜| 亚洲精品久久久久久久久久吃药 | 欧美影院 | 国内精品久久久久久中文字幕 | 欧美日韩福利 | 亚洲综合色自拍一区 | 日韩亚洲在线 | av免费网址 | 国产精品久久久久久久久久东京 | 日韩中文字幕视频 | 亚洲三级在线免费观看 |