在業(yè)務(wù)開發(fā)中,可能會(huì)跟第三方平臺(tái)做對(duì)接败富,比如我們使用了騰訊云的第三方的功能。這個(gè)時(shí)候很多功能需要業(yè)務(wù)方自己處理事件回調(diào)赖临。騰訊云的實(shí)時(shí)音視頻會(huì)給我們業(yè)務(wù)后臺(tái)發(fā)送事件回調(diào)星立,比如包含了退出房間爽茴,進(jìn)入房間等等。這個(gè)時(shí)候绰垂,有人會(huì)用if到底的方式室奏,比如
@PostMapping("xxx")
public void callback(Event e) {
if (e.eventType == 1) {
//todo something
}
else if (e.eventType == 2) {
//todo something
}
}
這么寫也沒問(wèn)題,很多小公司小團(tuán)隊(duì)的要求就是能跑通劲装,需求方能看到結(jié)果胧沫。但如果這么寫的話,后面突然改版的話占业,需要處理其他事件绒怨,那么就需要繼續(xù)加if else,從代碼的質(zhì)量上看很難看纺酸,可擴(kuò)展性也很糟糕窖逗。其實(shí)這個(gè)時(shí)候可以通過(guò)加入設(shè)計(jì)模式處理各種不同事件。
1餐蔬、先定義一個(gè)抽象的事件處理器
public abstract class AbstractEventHandler<T extends TrtcEventParam> {
/**
* 獲取事件類型
*
* @return
*/
public abstract Integer getEventType();
/**
* 處理事件
*
* @param t
*/
public abstract void HandlerEvent(T t);
}
2碎紊、實(shí)現(xiàn)一個(gè)具體的事件處理器,這里比如處理退出房間事件
@Slf4j
@Component
public class ExitRoomEventHandler extends AbstractEventHandler<TrtcEventParam> {
@Override
public Integer getEventType() {
return RoomEvent.EventType.EVENT_TYPE_EXIT_ROOM;
}
@Autowired
private ApplicationContext applicationContext;
@Override
public void HandlerEvent(TrtcEventParam param) {
if (StringUtils.startsWith(param.getEventInfo().getUserId(), properties.getUserIdPrefix())) {
//這里使用了spring的事件發(fā)布機(jī)制樊诺,用來(lái)進(jìn)一步增加可擴(kuò)展性
applicationContext.publishEvent(new ExitRoomEvent(this, param));
}
}
事件定義
public class ExitRoomEvent extends ApplicationEvent {
@Getter
private TrtcEventParam param;
public ExitRoomEvent(Object source, TrtcEventParam param) {
super(source);
this.param = param;
}
}
3仗考、定義一個(gè)簡(jiǎn)單工廠,當(dāng)初始化bean時(shí)把bean放入一個(gè)map中词爬,并對(duì)外提供根據(jù)事件碼獲取對(duì)應(yīng)處理器的的方法
@Component
public class EventHandlerFactory implements InitializingBean, ApplicationContextAware {
private static final Map<Integer, AbstractEventHandler<TrtcEventParam>> EVENT_HANDLER_MAP = new HashMap<>();
private ApplicationContext applicationContext;
public AbstractEventHandler<TrtcEventParam> getHandler(Integer eventType) {
return EVENT_HANDLER_MAP.get(eventType);
}
@Override
public void afterPropertiesSet() throws Exception {
applicationContext.getBeansOfType(AbstractEventHandler.class).values()
.forEach(handler -> EVENT_HANDLER_MAP.put(handler.getEventType(), handler));
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
4秃嗜、在處理回調(diào)的controller中調(diào)用
@PostMapping("/room/event/callback")
R execute(@RequestBody String body) {
...
AbstractEventHandler handler = eventHandlerFactory.getHandler(param.getEventType());
Optional.ofNullable(handler).ifPresent(h -> h.HandlerEvent(param));
...
}
5、在Observer中中監(jiān)聽事件通知
@Slf4j
@Component
public class ExitRoomEventObservers {
//程序員1自己的業(yè)務(wù)
@Order(1)
@EventListener(ExitRoomEvent.class)
public void method1(ExitRoomEvent event) {
...
}
//程序員2自己的業(yè)務(wù)
@Order(2)
@EventListener(ExitRoomEvent.class)
public void method2(ExitRoomEvent event) {
...
}
//后來(lái)新增的業(yè)務(wù)處理
@Order(3)
@EventListener(ExitRoomEvent.class)
public void method3(ExitRoomEvent event) {
...
}
}
通過(guò)上述改造,如果后面需要增加新的事件處理時(shí)锅锨,加入新的事件處理器叽赊,并且發(fā)布事件就可以實(shí)現(xiàn)處理新增業(yè)務(wù)。當(dāng)然必搞,如果需要處理的業(yè)務(wù)跨了服務(wù)或者比較多的時(shí)候必指,還是建議使用mq,結(jié)合上面部分思路自行改造