spring事件驱动封装

spring事件驱动用于单体架构解耦时很好的方式,下面看如何使用

首先创建事件基类BaseEvent.java,内容如下:

package org.demo.event;

import org.springframework.context.ApplicationEvent;

import java.lang.reflect.Constructor;
import java.util.UUID;

/**
 * 事件驱动基类Event
 */
public class BaseEvent<T> extends ApplicationEvent{

    private String eventId;

    private T body;

    public BaseEvent(Object source, T body) {
        super(source);
        this.eventId = UUID.randomUUID().toString().replace("-","");
        this.body = body;
    }

    public String getEventId() {
        return eventId;
    }

    public T getBody() {
        return body;
    }

    public static <P extends BaseEvent<T>,T>P builder(Class<P> clazz, Object source, T body) {
        try {
            Constructor<P> constructor = clazz.getConstructor(Object.class, body.getClass());
            return constructor.newInstance(source, body);
        } catch (Exception e) {
            throw new RuntimeException("BaseEvent Failed to create instance of " + clazz.getName(), e);
        }
    }
}

继续创建事件监听基类BaseEventListener.java,内容如下:

package org.demo.event.listener;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.demo.event.BaseEvent;
import org.springframework.context.ApplicationListener;

/**
 * 事件监听基类EventListener
 */
@Slf4j
public abstract class BaseEventListener<T extends BaseEvent<P>,P> implements ApplicationListener<T> {

    @Override
    public void onApplicationEvent(T event) {
        String simpleName = event.getClass().getSimpleName();
        log.info("Event:{} start.",simpleName);
        log.info("Event:{}[eventId:{}]",simpleName,event.getEventId());
        long startTime = System.currentTimeMillis();
        try {
            if (!preProcess(event)) {
                return;
            }
            if (this.execute(event.getBody(),event)){
                log.info("Event success[eventId:{}],body:{}",event.getEventId(),JSON.toJSONString(event.getBody()));
            }else {
                this.failHandler(event);
            }
        } catch (Exception e) {
            this.exceptionHandler(event,e);
        }
        long time = System.currentTimeMillis() - startTime;
        log.info("Event:{}[eventId:{}] end. {}ms",simpleName,event.getEventId(),time);
    }

    /**
     * 事件异常(可重写)
     * @param event
     * @param e
     */
    protected void exceptionHandler(T event,Exception e){
        log.info("Event exception[eventId:{}],body:{},{}",event.getEventId(),JSON.toJSONString(event.getBody()),e);
    }

    /**
     * 事件失败(可重写)
     * @param event
     */
    protected void failHandler(T event){
        log.info("Event fail[eventId:{}],body:{}",event.getEventId(),JSON.toJSONString(event.getBody()));
    }

    /**
     * 事件前置处理(可重写)
     * @param event
     * @return
     */
    protected boolean preProcess(T event) {
        if (event.getEventId() == null || event.getBody() == null) {
            log.info("Event unknown error,Event:{}[eventId:{}]", event.getClass().getSimpleName(),event.getEventId());
            return Boolean.FALSE;
        }
        if (!isCheck(event.getBody(),event)) {
            log.info("Event body verify,[eventId:{}],body:{} ", event.getEventId(),JSON.toJSONString(event.getBody()));
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }

    /**
     * 是否校验(可重写)
     * @param body
     * @param event
     * @return
     */
    protected boolean isCheck(P body,T event) {
        return true;
    }

    /**
     * 执行逻辑(必须实现)
     * @param body
     * @param event
     * @return
     */
    protected abstract boolean execute(P body, T event);
}

接着创建一个事件发布的工具类EventPubUtil.java,内容如下:

  package org.demo.event.util;

import lombok.extern.slf4j.Slf4j;
import org.demo.event.BaseEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

/**
 * 事件发布工具
 */
@Slf4j
@Component
public class EventPubUtil {

    private static ApplicationEventPublisher applicationEventPusher;

    @Autowired
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        EventPubUtil.applicationEventPusher = applicationEventPublisher;
    }

    /**
     * 发布事件
     * @param event
     */
    public static <T>void publish(BaseEvent<T> event) {
        log.info("publish event:{}",event.getClass().getSimpleName());
        applicationEventPusher.publishEvent(event);
    }
}

到此基本完成,接下来就是写测试测试一下,创建测试实体对象pojoTestPojo.java,内容如下:

package org.demo.event.pojo;

import lombok.Data;

@Data
public class TestPojo {

    private String name;

    private Integer age;
}

继续创建测试事件TestEvent.java,内容如下:

package org.demo.event;

import org.demo.event.pojo.TestPojo;

/**
 * 测试事件
 */
public class TestEvent extends BaseEvent<TestPojo>{

    public TestEvent(Object source, TestPojo testPojo){
        super(source, testPojo);
    }
}

继续创建测试事件监听TestEventListener.java,内容如下:

package org.demo.event.listener;

import com.alibaba.fastjson.JSON;
import org.demo.event.TestEvent;
import org.demo.event.pojo.TestPojo;
import org.springframework.stereotype.Component;

/**
 * 测试事件监听
 */
@Component
public class TestEventListener extends BaseEventListener<TestEvent, TestPojo> {

    @Override
    public boolean execute(TestPojo body, TestEvent event) {
        System.out.println("TestEventListener execute:body="+ JSON.toJSONString( body));
        return true;
    }
}

接下来就是创建一个接口发布一下测试事件,内容如下:

@GetMapping("/event")
public String event() {
    TestPojo testPojo = new TestPojo();
    testPojo.setName("测试一下");
    testPojo.setAge(18);
    TestEvent builder = TestEvent.builder(TestEvent.class, this, testPojo);
    EventPubUtil.publish(builder);
    return "event";
}

到此完成,访问一下接口,可以看到控制台事件监听打印了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。