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

服務(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教程 - java使用觀察者模式異步短信/郵箱提醒用戶群

java使用觀察者模式異步短信/郵箱提醒用戶群

2021-06-14 14:21沒有不憂傷的故事 Java教程

這篇文章主要為大家詳細(xì)介紹了java使用觀察者模式異步短信和郵箱提醒用戶群,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

需求

用戶中有人設(shè)置了賬戶余額達(dá)到閾值時(shí),短信/郵箱進(jìn)行提醒的服務(wù)。我們將需要在他賬戶余額閾值達(dá)到指定數(shù)值的時(shí)候進(jìn)行短信/郵箱消息通知,允許賬戶余額閾值出現(xiàn)偏差的時(shí)候通知,如果某個(gè)用戶48小時(shí)內(nèi)已經(jīng)短信/郵箱進(jìn)行過通知了,那么將不再進(jìn)行通知。

剖析

  • 存在兩個(gè)主題:短信通知和郵箱通知
  • 存在兩種觀察者:設(shè)置了短信通知且賬戶余額到達(dá)閾值的用戶,設(shè)置了郵箱通知且賬戶余額到達(dá)閾值的用戶。
  • 用spring的定時(shí)器,每10分鐘去數(shù)據(jù)庫獲取某個(gè)主題已經(jīng)達(dá)到閾值且開始了該主題的提醒功能的用戶
  • 用spring的@asycn注解異步短信通知,郵箱通知的相關(guān)方法
  • 用redis設(shè)置用戶短信/郵箱為鍵名,設(shè)置過期時(shí)間為48小時(shí)。如果獲取不到該鍵值對,說明其在觀察者行列

代碼

觀察者父類

 

?
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
/**
 * 訂閱觀察者
 * @author administrator
 *
 */
@component
//標(biāo)志為多例
@scope(value=configurablebeanfactory.scope_prototype)
public class subscriberobserver implements observer{
 
  private string email;
  private string phone;
  private string username;
  @autowired
  userfunctionservice userfunctionservice;
 
 
  @override
  public void update(observable o, object arg) {
    if(o instanceof emailalertsubject){
      userfunctionservice.alertuseremail(email,username);
    }
    if(o instanceof phonealertsubject){
      userfunctionservice.alertuserphone(phone,username);
    }
  }
 
  public string getemail() {
    return email;
  }
 
  public void setemail(string email) {
    this.email = email;
  }
 
  public string getphone() {
    return phone;
  }
 
  public void setphone(string phone) {
    this.phone = phone;
  }
 
  public string getusername() {
    return username;
  }
 
  public void setusername(string username) {
    this.username = username;
  }
 
  public subscriberobserver() {
    super();
    // todo auto-generated constructor stub
  }
 
 
}

主題

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
 * email提醒主題
 * @author administrator
 *
 */
@component
public class emailalertsubject extends observable{
 
  public void alert(){
     this.setchanged();
     //如果用拉的方式,這么調(diào)用
     this.notifyobservers();
  }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
 * 短信提醒主題
 * @author administrator
 *
 */
@component
public class phonealertsubject extends observable{
 
  public void alert(){
     this.setchanged();
     //如果用拉的方式,這么調(diào)用
     this.notifyobservers();
  }
}

定時(shí)器

 

?
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/**
 * 定時(shí)給訂閱了短信提醒和email提醒的用戶服務(wù)
 * @author administrator
 *
 */
@component
public class timealerttaskutil {
 
  @autowired
  commonuserservice commonuserservice;
  @autowired
  jedisconnectionfactory factory;
  @autowired
  emailalertsubject emailsubject;
  @autowired
  phonealertsubject phonesubject;
 
 
  private static final string emailkeyname = "emailalert:";
  private static final string phonekeyname = "phonealert:";
 
  /**
   * 定時(shí)獲取需要email提醒的用戶,每10分鐘調(diào)用一次
   */
  @scheduled(fixeddelay = 1000 * 60 * 10)
  public void alertemailtask() {
    // 1.獲取數(shù)據(jù)庫中達(dá)到了閾值的用戶
    list<user> emails = commonuserservice.getuseralertemailandname();
    // 2.查看redis中是否有達(dá)到閾值,且48小時(shí)已經(jīng)通知的用戶,將其排除在觀察者行列,最終得出觀察者隊(duì)伍
    list<subscriberobserver> informemail = getinformobserver(emails);
    // 3.創(chuàng)建主題,添加觀察者
    addobservers(emailsubject, informemail);
    // 4.通知
    emailsubject.alert();
 
    // 5.將已經(jīng)通知的觀察者信息存儲(chǔ)到reids內(nèi),設(shè)置過期時(shí)間為一天
    setrediscache(emails);
    // 6.將觀察者從主題中移除
    deleteobservers(emailsubject, informemail);
  }
 
  /**
   * 定時(shí)獲取需要短信提醒的用戶,每10分鐘調(diào)用一次
   *
   */
  @scheduled(fixeddelay = 1000 * 60 * 10)
  public void alertphonetask() {
    // 1.獲取數(shù)據(jù)庫中達(dá)到了閾值的用戶
    list<user> phones = commonuserservice.getuseralertphoneandname();
    // 2.查看redis中是否有達(dá)到閾值,且今天已經(jīng)通知的用戶,將其排除在觀察者行列,最終得出觀察者隊(duì)伍
    list<subscriberobserver> informphones = getinformobserver(phones);
 
    // 3.創(chuàng)建主題,添加觀察者
    addobservers(phonesubject, informphones);
    // 4.通知
    phonesubject.alert();
    // 5.將已經(jīng)通知的觀察者信息存儲(chǔ)到reids內(nèi),設(shè)置過期時(shí)間為一天
    setrediscache(phones);
    // 6.將觀察者從主題中移除
    deleteobservers(phonesubject, informphones);
  }
 
  /**
   * ------------------------------------------------------------------------
   * -----------------------------------------------------
   **/
  /**
   * 過濾掉今天已經(jīng)email提醒的用戶,返回真正需要提醒的觀察者列表
   *
   * @param emails
   * @return
   */
  private list<subscriberobserver> getinformobserver(
      list<user> users) {
    list<subscriberobserver> obs = new arraylist<subscriberobserver>();
    jedis jedis = factory.getconnection().getnativeconnection();
    for (user user : users) {
      string value;
      subscriberobserver observer = (subscriberobserver) springconfigtool
          .getbean("subscriberobserver");
      if (user.getemail()!=null) {
        value = jedis.get(emailkeyname + user.getemail());
        if (value == null || !value.equals("success")) {
          observer.setemail(user.getemail());
          observer.setusername(user.getname());
          obs.add(observer);
        }
      } else {
        value = jedis.get(phonekeyname + user.getphone());
        if (value == null || !value.equals("success")) {
          observer.setphone(user.getphone());
          observer.setusername(user.getname());
          obs.add(observer);
        }
      }
    }
    return obs;
  }
 
  /**
   * 將指定的觀察者列表添加到指定的主題
   *
   * @param subject
   * @param list
   */
  private void addobservers(observable subject, list<subscriberobserver> list) {
    for (subscriberobserver obs : list) {
      subject.addobserver(obs);
    }
  }
 
  private void deleteobservers(observable subject,
      list<subscriberobserver> list) {
    for (subscriberobserver obs : list) {
      subject.deleteobserver(obs);
    }
  }
 
  /**
   * 將列表的值作為鍵,存入redis,過期時(shí)間為48小時(shí)
   *
   * @param list
   */
  private void setrediscache(list<user> users) {
    jedis jedis = factory.getconnection().getnativeconnection();
    for (user user : users) {
      if (user.getemail()!=null) {
        jedis.set(emailkeyname + user.getemail(), "success", "nx", "ex",
            60 * 60 * 24 * 2);
      } else {
        jedis.set(phonekeyname + user.getphone(), "success", "nx", "ex",
            60 * 60 * 24 * 2);
      }
    }
  }
}

總結(jié)

代碼是不全面的,只是個(gè)示例而已。關(guān)于短信通知和郵箱通知的服務(wù)類和工具類并沒有給出,因?yàn)槔锩嫔婕暗揭恍╇[私參數(shù)。所以關(guān)于異步通知示例代碼沒有,但使用spring管理的@async注解和在spring進(jìn)行一定的配置即可,可以在我的另外一篇博客找到關(guān)于異步通知的示例代碼。

事實(shí)上根據(jù)需求,可以使用redis的發(fā)布訂閱,或者消息隊(duì)列mq來實(shí)現(xiàn)類似的功能。但為了加深對設(shè)計(jì)模式的理解,所以寫了一個(gè)不是很純正的觀察者模式來模仿發(fā)布訂閱的操作。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

原文鏈接:https://blog.csdn.net/qq_32020035/article/details/81204374

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 波多洁野衣一二区三区 | 色天天综合网色鬼综合 | 色婷婷六月丁香在线观看 | 色cccwww| 九九99热久久999精品 | 涩涩屋在线播放 | 精品久久洲久久久久护士免费 | 性关系免费视频 | 亚洲精品www久久久久久久软件 | 成人在线av视频 | 美女黄金大片视频免费看 | 美女大乳被捏羞羞漫画 | 久久亚洲精品AV成人无 | 久久久无码精品亚洲欧美 | 国产日韩欧美在线一区二区三区 | 亚洲国产一区 | 人阁色第四影院在线观看 | 欧美爽妇| 视频一区二区国产无限在线观看 | 天天操夜夜操狠狠操 | 成人毛片高清视频观看 | 欧美日韩中文国产一区二区三区 | 欧美一区二区三区成人看不卡 | 轻轻色在线视频中文字幕 | 希望影院高清免费观看视频 | 色就色欧美综合偷拍区a | 免费看www| 国产三级精品播放 | 亚洲国产精品久久精品怡红院 | 暖暖的韩国免费观看 | 国产精品久久久久无毒 | 日韩一区二区在线视频 | 欧美同性猛男野外gay免费 | 天天澡夜夜澡狠狠澡 | 小鸟酱在线看 | 丁香网五月天 | 91tm视频 | 2019中文字幕| 国内精品国语自产拍在线观看55 | 四虎四虎| 成人性生交小说免费看 |