自定义事件学习使用

请求接口

@RestController
@RequestMapping(value = "/caching")
public class TestController {

    @RequestMapping(value = "/testFilter",method = RequestMethod.GET)
    public String testCachingFilter(HttpServletRequest request, HttpServletResponse response,String content){
    //定义事件
        DefaultDomainEvent de = new DefaultDomainEvent();
        de.addEventData("key1","value1");
        //发布事件
DomainEventPublisherFactory.getRegisteredPublisher().publishEvent(de);
        return "SUCCESS";
    }
    
}

自定义事件

public interface DomainEvent {
    /**
     * 获得事件ID
     * @return
     */
    String getEventId();
    /**
     * 获得事件事件
     * @return
     */
    Date obtainEventTime(); 
    /**
     * 获取操作信息
     * @return
     */
    OperateInfo getOperateInfo();
    /**
     * 获得事件的触发人身份
     * @return
     */
    AccessTokenUser getOperator();
    /**
     * 事件需要传递的业务数据
     * @return
     */
    <T> T getEventData();
    /**
     * 定义事件监听器的执行顺序逻辑
     * @return
     */
    ExecutePoint obtainExecutePoint();
    /**
     * 事件类型
     * @return
     */
    String getEventType();
    /**
     * 排序号  相同的排序号  按发布事件的顺序
     * @return
     */
    default int orderNo() {
        return 0;
    }
    /**
     * 异常是否抛出
     * @return
     */
    default boolean throwException() {
        return true;
    }
}

public class DefaultDomainEvent implements DomainEvent {

    //传递的数据
    private Map<String,Object> eventData;
    //TODO 也可以定义其他数据

    public DefaultDomainEvent() {
    }

    public DefaultDomainEvent(Map<String, Object> eventData) {
        this.eventData = eventData;
    }

    @Override
    public String getEventId() {
        return null;
    }

    //当前系统时间
    @Override
    public Date obtainEventTime() {
        return null;
    }

    //当前用户信息
    @Override
    public OperateInfo getOperateInfo() {
        return null;
    }
    //当前用户信息
    @Override
    public AccessTokenUser getOperator() {
        return null;
    }
    //当前事件中包含的数据
    @Override
    public <T> T getEventData() {
        return (T)this.eventData;
    }

    //事件执行时机
    @Override
    public ExecutePoint obtainExecutePoint() {
        return ExecutePoint.CURR_THREAD;
    }

    //事件类型
    @Override
    public String getEventType() {
        return DefaultDomainEvent.class.getSimpleName();
    }

    public void addEventData(String key,Object value){
        if (this.eventData == null) this.eventData = new HashMap<>();
        if (StringUtils.isBlank(key)) return;
        if (value == null){
            this.eventData.remove(key);
            return;
        }
        this.eventData.put(key, value);
    }

    public void addEventData(Map<String,Object> eventData){
        if (this.eventData == null) this.eventData = new HashMap<>();
        if (eventData == null) return;
        this.eventData.putAll(eventData);
    }
}

自定义事件监听器

@Service
public class DefaultDomainEventListener implements IDomainEventListener {

    private static Logger logger = LoggerFactory.getLogger(DefaultDomainEventListener.class);

    @Override
    public void onEvent(DomainEvent event) {
    //执行我们的业务逻辑
        Map<String,Object> eventData = event.getEventData();
        logger.info("DefaultDomainEventListener.onEvent():params:{}", JsonConverter.toJsonStr(eventData));
    }

    @Override
    public boolean listenOn(String eventType) {
        return DefaultDomainEvent.class.getName().equals(eventType);
    }
}

事件发布器

public class DomainEventPublisherFactory {
	
	private static final DomainEventPublisherFactory INSTANCE = new DomainEventPublisherFactory();
	private DomainEventPublisher domainEventPublisher = null;
	private DomainEventPublisherFactory(){
		
	}
	public static final DomainEventPublisherFactory instance(){
		return INSTANCE;
	}
	public static final DomainEventPublisher registerPublisher(DomainEventPublisher domainEventPublisher){
		instance().domainEventPublisher = domainEventPublisher;
		return domainEventPublisher;
	}
	
	public static final DomainEventPublisher getRegisteredPublisher(){
		if(instance().domainEventPublisher==null){
			throw new RuntimeException("事件发布器未注册到DomainEventPublisherFactory!");
		}
		return instance().domainEventPublisher;
	}
}

public interface DomainEventPublisher {
	void publishEvent(DomainEvent event);
}
//执行发布的事件逻辑
@Component
public class DefaultDomainEventPublisher implements DomainEventPublisher,ApplicationContextAware {
    private final Logger logger=LogManager.getLogger(this.getClass());
    
    private ApplicationContext context;
    @Override
    public void setApplicationContext(ApplicationContext context)
            throws BeansException {
        this.context = context;
        DomainEventPublisherFactory.registerPublisher(this);
    }
    @Autowired
    private AsyncTaskComponent asyncTaskComponent;
    
    
    private List<IDomainEventListener> listeners=null;
    private List<IDomainEventListener> getDomainEventListeners(){
        if(listeners!=null) return listeners;
        
        synchronized(DefaultDomainEventPublisher.class) {
            if(listeners!=null) return listeners;
            
            Map<String, IDomainEventListener> beans = context.getBeansOfType(IDomainEventListener.class);
            if(beans==null) return listeners;
            List<IDomainEventListener> listeners1=new ArrayList<>();
            Map<IDomainEventListener,Integer> los=new HashMap<>();
            int i=1;
            for (IDomainEventListener listener : beans.values()) {
                los.put(listener, i);
                listeners1.add(listener);
                i++;
            }
            Collections.sort(listeners1, (l1,l2)->{
                int rt=l1.getOrderNo()-l2.getOrderNo();
                if(rt==0) rt=los.get(l1)-los.get(l2);
                return rt;
            });
            listeners = Collections.unmodifiableList(listeners1);
        }
        
        return listeners;
    }
    @Override
    public void publishEvent(DomainEvent event) {
        //如果是事务提交后的事件  判断以经加入的事件 不再加入
        if(!ExecutePoint.CURR_THREAD.equals(event.obtainExecutePoint())
                &&!ExecutePoint.NEW_THREAD_NOW.equals(event.obtainExecutePoint())
                &&this.eventAdded(event)
                ) {
            return;
        }
        List<IDomainEventListener> listeners = this.getDomainEventListeners();
        for(IDomainEventListener listener:listeners){
            if(StringUtils.isBlank(event.getEventType())
                    ||!listener.listenOn(event.getEventType())
                    ) {
                continue;
            }
            if(ExecutePoint.CURR_THREAD.equals(event.obtainExecutePoint())){//当前线程
                try {
                    listener.onEvent(event);
                } catch (Exception e) {
                    logger.error(e);
                    if(event.throwException()) throw new RuntimeException(e);
                }
            }else if(ExecutePoint.CURR_THREAD_AFTER_COMMITTED.equals(event.obtainExecutePoint())){//事务提交后  当前线程执行
                List<WaitExecuteDomainEvent> waits=ThreadLocalCache.getCacheObject(ExecutePoint.CURR_THREAD_AFTER_COMMITTED.toString());
                if(waits==null) {
                    waits=new ArrayList<WaitExecuteDomainEvent>();
                    ThreadLocalCache.addCache(ExecutePoint.CURR_THREAD_AFTER_COMMITTED.toString(), waits);
                    //事务提交后 在线程中执行事件  避免  事务问题
                    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
                        @Override
                        public void afterCommit() {
                            run_CURR_THREAD_AFTER_COMMITTED_Events();
                        }
                        @Override
                        public int getOrder() {
                            return 0;
                        }
                    });
                }
                waits.add(new WaitExecuteDomainEvent(listener,event));
            }else if(ExecutePoint.NEW_THREAD_NOW.equals(event.obtainExecutePoint())){//立即 启动一个线程
                asyncTaskComponent.runTaskInThreadPool(new AsyncTaskComponent.IAsyncTask<String>() {
                    @Override
                    public String execute(Map<String, Object> data) {
                        IDomainEventListener listener=(IDomainEventListener) data.get("listener");
                        DomainEvent event=(DomainEvent) data.get("event");
                        try {
                            listener.onEvent(event);
                        } catch (Exception e) {
                            logger.error(e);
                        }
                        return null;
                    }
                }, Utils.buildMap("listener",listener,"event",event));
            }else if(ExecutePoint.NEW_THREAD_AFTER_COMMITTED.equals(event.obtainExecutePoint())){//事务提交后 启动一个线程
                TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
                    @Override
                    public void afterCommit() {
                        asyncTaskComponent.runTaskInThreadPool(new AsyncTaskComponent.IAsyncTask<String>() {
                            @Override
                            public String execute(Map<String, Object> data) {
                                IDomainEventListener listener=(IDomainEventListener) data.get("listener");
                                DomainEvent event=(DomainEvent) data.get("event");
                                try {
                                    listener.onEvent(event);
                                } catch (Exception e) {
                                    logger.error(e);
                                }
                                return null;
                            }
                        }, Utils.buildMap("listener",listener,"event",event));
                    }
                    @Override
                    public int getOrder() {
                        return listener.getOrderNo()+1;
                    }
                });
            }else if(ExecutePoint.NEW_THREAD_AFTER_COMPLETIONED.equals(event.obtainExecutePoint())){//事务完成(提交/回滚)后 启动一个线程
                TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
                    @Override
                    public void afterCompletion(int status) {//status 见TransactionSynchronization.STATUS_
                        asyncTaskComponent.runTaskInThreadPool(new AsyncTaskComponent.IAsyncTask<String>() {
                            @Override
                            public String execute(Map<String, Object> data) {
                                IDomainEventListener listener=(IDomainEventListener) data.get("listener");
                                DomainEvent event=(DomainEvent) data.get("event");
                                try {
                                    listener.onEvent(event);
                                } catch (Exception e) {
                                    logger.error(e);
                                }
                                return null;
                            }
                        }, Utils.buildMap("listener",listener,"event",event));
                    }
                    @Override
                    public int getOrder() {
                        return listener.getOrderNo()+1;
                    }
                });
            }
        }
    }
    //运行事务提交后事件
    public void run_CURR_THREAD_AFTER_COMMITTED_Events() {
        List<WaitExecuteDomainEvent> waits=ThreadLocalCache.removeCache(ExecutePoint.CURR_THREAD_AFTER_COMMITTED.toString());
        if(CollectionUtils.isEmpty(waits)) return;
        Map<WaitExecuteDomainEvent,Integer> waitToIndex=new HashMap<WaitExecuteDomainEvent,Integer>();
        int i=0;
        for (WaitExecuteDomainEvent wait : waits) {
            waitToIndex.put(wait, i);
            i++;
        }
        waits.sort(Comparator.comparingInt(WaitExecuteDomainEvent::getOrderNo).thenComparingInt(waitToIndex::get));
        Future<String> f=asyncTaskComponent.runTaskInThreadPool(data -> {
            for (WaitExecuteDomainEvent wait : waits) {
                wait.execute();
            }
            return null;
        }, null);
        //Boolean isyc = Boolean.valueOf(BaseConstants.getProperty("prefetchingRecordNo", "false"));
        //if(isyc) return;
        //等待10s
        String name=waits.toString();
        try {
            f.get(10,TimeUnit.SECONDS);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(name+".run_CURR_THREAD_AFTER_COMMITTED_Events 运行超时10s");
        }
        for (WaitExecuteDomainEvent wait : waits) {
            if(wait.getError()!=null) {
                logger.error(name+".run_CURR_THREAD_AFTER_COMMITTED_Events."+wait.getListenerClassName()+"运行出错:",wait.getError());
            }
            if(wait.isExecuted()) {
                logger.info(name+".run_CURR_THREAD_AFTER_COMMITTED_Events."+wait.getListenerClassName()+"运行耗时:"+wait.getCost()+"ms");
                continue;
            }
            if(wait.isExecuting()) {
                logger.warn(name+".run_CURR_THREAD_AFTER_COMMITTED_Events."+wait.getListenerClassName()+"正在运行,参数"+JsonConverter.toJsonStr(wait.getEvent())+",已耗时:"+wait.getCost()+"ms");
            }
            else {
                logger.warn(name+".run_CURR_THREAD_AFTER_COMMITTED_Events."+wait.getListenerClassName()+"还未运行,参数"+JsonConverter.toJsonStr(wait.getEvent()));
            }
        }
    }
    //判断事件是否已经 加入到 队列中
    private boolean eventAdded(DomainEvent event) {
        if(ThreadLocalCache.getCacheObject(ThreadLocalCache.REQUEST_ID)==null) {
            return false;
        }
        synchronized (ThreadLocalCache.getCacheObject(ThreadLocalCache.REQUEST_ID)) {
            Map<String,Boolean> addedKeys=ThreadLocalCache.getCacheObject("addedEventKeys");
            if(addedKeys==null) {
                addedKeys=new HashMap<String,Boolean>();
            }
            String eventKey=event.getEventType()+event.getEventId();
            if(addedKeys.containsKey(eventKey)) {
                return true;
            }
            addedKeys.put(eventKey, true);
        }
        return false;
    }
}

异步执行发布的事件

@Component
public class AsyncTaskComponent {
    /**
     * 启动监听线程
     * @param <T>
     * @param task
     * @param data
     */
    @Async("taskExecutor")//使用线程池 启动
    public <T> Future<T> runTaskInThreadPool(IAsyncTask<T> task, Map<String,Object> data){
        return new AsyncResult<T>(task.execute(data));
    }
    
    //异步任务接口
    public interface IAsyncTask<T> {
        T execute(Map<String,Object> data);
    }
    
}

定义事件执行的时机

public enum ExecutePoint {
    NEW_THREAD_NOW,//立即启动一个新线程执行
    NEW_THREAD_AFTER_COMMITTED, //在事务提交后启动一个新线程执行
    NEW_THREAD_AFTER_COMPLETIONED, //在事务完成(提交/回滚)后启动一个新线程执行
    CURR_THREAD, //在当前线程执行
    CURR_THREAD_AFTER_COMMITTED, //在事务提交后的当前线程执行
}

Spring事件的学习使用

@Component
public class CustomApplicationListener implements ApplicationListener<ApplicationContextEvent>{

	@Override
	public void onApplicationEvent(ApplicationContextEvent event) {
		SpringUtil.setApplicationContext(event.getApplicationContext());
	}

}
public class SpringUtil {
	private static ApplicationContext applicationContext = null ;
	private static Environment  environment = null ;
	public static void setApplicationContext(ApplicationContext applicationContext){
		if(SpringUtil.applicationContext==null){
			SpringUtil.applicationContext=applicationContext;
			SpringUtil.environment=applicationContext.getEnvironment();
		}
	}
	public static ApplicationContext getApplicationContext() {
		return applicationContext;
	}
	public static Environment getEnvironment() {
		return environment;
	}
	
	public static Object getBean(String name){
		return getApplicationContext().getBean(name);
	}
	public static <T> T getBean(Class<T> clazz){
		return getApplicationContext().getBean(clazz);
	}
	public static <T> T getBean(String name,Class<T> clazz){
		return getApplicationContext().getBean(name,clazz);
	}
	
	public static String getString(String key){
		return getEnvironment().getProperty(key);
	}
	public static int getInt(String key){
		return NumberUtil.parseInt(getEnvironment().getProperty(key));
	}
	public static long getLong(String key){
		return NumberUtil.parseLong(getEnvironment().getProperty(key));
	}
	public static boolean getBoolean(String key){
		return BooleanUtil.toBoolean(getEnvironment().getProperty(key));
	}
}

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值