请求接口
@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 {
String getEventId();
Date obtainEventTime();
OperateInfo getOperateInfo();
AccessTokenUser getOperator();
<T> T getEventData();
ExecutePoint obtainExecutePoint();
String getEventType();
default int orderNo() {
return 0;
}
default boolean throwException() {
return true;
}
}
public class DefaultDomainEvent implements DomainEvent {
private Map<String,Object> eventData;
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) {
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);
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 {
@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));
}
}