使用观察者模式进行短信通知预警日志记录

Posted 朱培

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用观察者模式进行短信通知预警日志记录相关的知识,希望对你有一定的参考价值。

---------------------------------------------------------------------------------------------
[版权申明:本文系作者原创,转载请注明出处] 
文章出处:https://blog.csdn.net/sdksdk0/article/details/85061646

作者:朱培      ID:sdksdk0     
--------------------------------------------------------------------------------------------

应用场景:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象
都得到通知并被自动更新。如在舆情系统中发现有客户给出差评,就需要2小时内给相应的负责人发送短信通知,在客流系统中,人数超过预警值需要发送短信提醒相关负责人并记录到预警流水表中。

特点:一般由两个角色组成:发布者和订阅者(观察者)。观察者通常有一个回调,也可以没有。例如可以适用于监听器、日志收集、短信通知、邮件通知等场景。

在Java中通过Observable类和Observer接口实现了观察者模式。一个Observer对象监视着一个Observable对象的变化,
当Observable对象发生变化时,Observer得到通知,就可以进行相应的工作。
java.util.Observable中有两个方法对Observer特别重要,一个是setChange()方法用来设置一个内部标志位注明数据发
生了变化;一个是notifyObservers()方法会去调用一个列表中所有的Observer的update()方法,通知它们数据发生了变化。
Observer通过Observable的addObserver()方法把自己添加到这个列表中。这个列表虽然由Observable拥有,但
Observable并不知道到底有哪些Observer正在观察等待通知。Observable只提供一个方法让Observer能把自己添加进列表,
并保证会去通知Observer发生了变化。通过这种机制,可以有任意多个Observer对Observable进行观察,而不影响
Observable的实现。

 

1、预警类型

public enum WarnTypeEnum 
	COMMENT,
	KELIU;


2、订阅观察者

@Component
public class SubscriberObserver implements Observer

    private Map<String, Object> param;
    private AScenic scenic;
    private Integer count;
    private WarnTypeEnum type;

    @Autowired
    private IZNoticeWarnService noticeWarnService;

    @Override
    public void update(Observable o, Object arg) 
       
        if(o instanceof NoticeWarnSubject)
        	noticeWarnService.onSaveNoticeWarn(param,scenic,count,type);
        
        if(o instanceof SMSWarnSubject)
        	noticeWarnService.onSendSMSWarn(param,scenic,count,type);
        
        
    

	public WarnTypeEnum getType() 
		return type;
	

	public void setType(WarnTypeEnum type) 
		this.type = type;
	

	public Map<String, Object> getParam() 
		return param;
	


	public void setParam(Map<String, Object> param) 
		this.param = param;
	



	public AScenic getScenic() 
		return scenic;
	


	public void setScenic(AScenic scenic) 
		this.scenic = scenic;
	


	public Integer getCount() 
		return count;
	


	public void setCount(Integer count) 
		this.count = count;
	


	public SubscriberObserver() 
        super();
    


3、主题对象

@Component
public class SMSWarnSubject extends Observable

    public void update()
         this.setChanged();
         this.notifyObservers();
    
@Component
public class NoticeWarnSubject extends Observable

    public void update()
         this.setChanged();
         this.notifyObservers();
    

4、业务实现,进行短信发送操作(这里只是伪代码,不能直接运行),也要和增加的业务对相应的处理

public void onSendSMSWarn(Map<String, Object> c, AScenic sc, int count, WarnTypeEnum type) 
		
		try 
			if(type.equals(WarnTypeEnum.COMMENT))
				if (null!=c&&!StringUtils.isEmpty(c.get("phone").toString())) 
				    	String[] param=c.get("name").toString(),c.get("num").toString();
				    	new SmsUtils(c.get("phone").toString(), properties.getSmsCommId(), param).start();
					
			else if(type.equals(WarnTypeEnum.KELIU))
				if (null!=sc&&!StringUtils.isEmpty(sc.getPhone())) 
					String[] param=sc.getName(),count+"";
					new SmsUtils(sc.getPhone(), properties.getSmsPersonId(), param).start();
				 
			
		 catch (Exception e) 
			e.printStackTrace();
		
		
	

 

5、在定时器中使用,因为我这里使用了一个int类型的count这个参数,所以不能为空,默认可以加个0,例如observer.setCount(0);否则会就报空指针异常

    @Autowired
	private SubscriberObserver observer;
	@Autowired
	private NoticeWarnSubject noticeWarnSubject;
	@Autowired
	private SMSWarnSubject  smsWarnSubject;


	//景区舆情预警,观察者模式
	@Scheduled(cron="0 */20 * * * ?")
	public void scenicCommentWarn() throws NoSuchMethodException, SecurityException 
		log.info("舆情预警V2  start......");
		List<SubscriberObserver> warnInfo = getCommentInformObserver();
		addObservers(noticeWarnSubject, warnInfo); //保存到未读通知中
		addObservers(smsWarnSubject, warnInfo);//发送舆情预警短信通知
		noticeWarnSubject.update();
		smsWarnSubject.update();
	    deleteObservers(noticeWarnSubject, warnInfo);
	    deleteObservers(smsWarnSubject, warnInfo);
		log.info("舆情预警V2  end......");
	
	
	 //客流预警
	@Scheduled(cron="0 */20 * * * ?")//20分钟一次客流预警
	public void scenicPersonWarn() 
		log.info("客流预警V2  start......");
		List<SubscriberObserver> warnInfo = getKeliutInformObserver();
		addObservers(noticeWarnSubject, warnInfo); //保存到未读通知中
		addObservers(smsWarnSubject, warnInfo);//发送客流预警短信通知
		noticeWarnSubject.update();
		smsWarnSubject.update();
	    deleteObservers(noticeWarnSubject, warnInfo);
	    deleteObservers(smsWarnSubject, warnInfo);
		log.info("客流预警V2  end......");
	

	  
	private List<SubscriberObserver> getKeliutInformObserver() 
		 List<SubscriberObserver> obs = new ArrayList<SubscriberObserver>();
		 Calendar cal = Calendar.getInstance(); 
			List<AScenic> list=mapper.selectListByType(1);
			String endTime = DateUtil.format(cal.getTime(), "yyyy-MM-dd HH:mm:ss");
			cal.add(Calendar.MINUTE, -20);
			String beginTime = DateUtil.format(cal.getTime(), "yyyy-MM-dd HH:mm:ss");
			for (AScenic sc : list)  
				int count = passengerCountMapper.selectMaxCountBySecond(sc.getName(),beginTime,endTime);
				if(count>=sc.getWarnNum())
					//触发预警
					observer.setCount(count);
					observer.setScenic(sc);
					observer.setType(WarnTypeEnum.KELIU);
		            obs.add(observer);
				
					
		return obs;
	

	private List<SubscriberObserver> getCommentInformObserver() 
        List<SubscriberObserver> obs = new ArrayList<SubscriberObserver>();
        Calendar cal = Calendar.getInstance();
		String endTime = DateUtil.format(cal.getTime(), "yyyy-MM-dd HH:mm:ss");
		cal.add(Calendar.HOUR, -2);
		String beginTime = DateUtil.format(cal.getTime(), "yyyy-MM-dd HH:mm:ss");
        //查询这两个小时新产生的差评条数
		List<Map<String,Object>> selectCommentListTask = commentMapper.selectCommentListWarnTask(null,null,null, null, beginTime, endTime, 0, 2, null);
		for(Map<String,Object> c:selectCommentListTask)
			observer.setParam(c);
			observer.setCount(0);
			observer.setType(WarnTypeEnum.COMMENT);
            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);
        
    

以上就是观察者模式来实现短信通知和预警日志记录的操作步骤了。

 

 

 

以上是关于使用观察者模式进行短信通知预警日志记录的主要内容,如果未能解决你的问题,请参考以下文章

数据源监控与预警

设计模式-观察者模式JAVA实现

观察者模式解析

基于来信码的短信通知平台

js设计模式---观察者模式

观察者模式和发布订阅模式