背景
公司的項目以前代碼里面有存在使用spring自帶發(fā)布訂閱的代碼,因此稍微學習一下如何使用,并了解一下這種實現(xiàn)方式的優(yōu)缺點。
優(yōu)點
- 實現(xiàn)方便,代碼方面基本只需要定義消息體和消費者,適用于小型應用程序。
- 不依賴外部中間件,因而不需要復雜的配置、部署。
缺點
- 無法提供消息持久性,項目一旦重啟,消息就會丟失,因而不適合實現(xiàn)延遲隊列。
- 對比消息隊列,無法實現(xiàn)復雜的消息過濾、路由過濾。
- 無法實現(xiàn)跨應用程序的事件通信。不同應用程序之間的事件發(fā)布和訂閱更為容易。
發(fā)布訂閱模式的優(yōu)缺點我就不說了,就說說不同實現(xiàn)方式之間的優(yōu)缺點。
一、創(chuàng)建消息類
消息類需要繼承ApplicationEvent類。因為java調(diào)用構造函數(shù)的機制就是默認會調(diào)用父類的構造函數(shù),而ApplicationEvent類只有一個單參數(shù)的構造函數(shù),無法自動調(diào)用,每個構造函數(shù)都需要顯式調(diào)用父類的構造函數(shù)。也就是super(source);
package org.jeecg.modules.test.testPublic;
import org.springframework.context.ApplicationEvent;
import java.util.Objects;
/**
* @ClassName: MyEvent
* @Author: zjc
* @Date: 2023/8/30 18:22
* @Description:
**/
public class MyEvent extends ApplicationEvent {
private String taskId;
private Integer sourceType;
public MyEvent(Object source) {
super(source);
}
/**
*
* @param source 觸發(fā)事件的對象,可隨便傳,不過建議傳自己可能用得到的對象。好像在調(diào)用放直接this的挺多
* @param taskId 任務id,自己定義的事件要處理的內(nèi)容
* @param sourceType 自己定義的源類型,用來在多場景觸發(fā)情況下區(qū)分不同場景的標志
* @return: null
**/
public MyEvent(Object source,String taskId,Integer sourceType) {
super(source);
this.taskId=taskId;
this.sourceType=sourceType;
}
public String getTaskId() {
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
public Integer getSourceType() {
return sourceType;
}
public void setSourceType(Integer sourceType) {
this.sourceType = sourceType;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyEvent myEvent = (MyEvent) o;
return Objects.equals(taskId, myEvent.taskId) && Objects.equals(sourceType, myEvent.sourceType);
}
@Override
public int hashCode() {
return Objects.hash(taskId, sourceType);
}
@Override
public String toString() {
return "MyEvent{" +
"taskId='" + taskId + '\'' +
", sourceType=" + sourceType +
'}';
}
}
二、發(fā)布消息
發(fā)布消息可以直接使用ApplicationContext對象調(diào)用publishEvent方法。因為ApplicationContext接口繼承了ApplicationEventPublisher接口。注意消息類必須要繼承ApplicationEvent類才能作為參數(shù)發(fā)布消息。
package org.jeecg.modules.test.testPublic;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @ClassName: EventController
* @Author:
* @Date: 2023/8/31 17:53
* @Description:
**/
@RestController
@Api("test")
@RequestMapping("/test")
public class EventController {
@Autowired
private ApplicationContext applicationContext;
@ApiOperation("testEvent")
@GetMapping("/testEvent")
public void testEvent(){
MyEvent myEvent=new MyEvent(this,"123456",1);
applicationContext.publishEvent(myEvent);
}
@ApiOperation("testEvent1")
@GetMapping("/testEvent1")
public void testEvent1(){
MyEvent myEvent=new MyEvent(this,"123456",2);
applicationContext.publishEvent(myEvent);
}
}
三、監(jiān)聽消息
監(jiān)聽消息類需要實現(xiàn)ApplicationListener接口,并通過泛型傳入要監(jiān)聽的消息類,并重寫onApplicationEvent方法。spring內(nèi)的同一個消息可以有多個監(jiān)聽類,一旦監(jiān)聽到消息,監(jiān)聽該消息的全部監(jiān)聽類都會執(zhí)行。
監(jiān)聽類1:
package org.jeecg.modules.test.testPublic;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* @ClassName: MyEventListener
* @Author:
* @Date: 2023/8/31 17:50
* @Description:
**/
@Component
public class MyEventListener implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
System.out.println("消費者開始消費"+event.toString()+event.getSource().toString());
}
}
消費者2
package org.jeecg.modules.test.testPublic;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* @ClassName: MyEventListener
* @Author:
* @Date: 2023/8/31 17:50
* @Description:
**/
@Component
public class MyEventListener1 implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
System.out.println("消費者1開始消費"+event.toString()+event.getSource().toString());
}
}
四、測試
調(diào)用testEvent接口
調(diào)用testEvent1接口
文章來源:http://www.zghlxwxcb.cn/news/detail-686898.html
結果均符合預期,可以通過在消息體里面加一個字段來區(qū)分消息來著不同的觸發(fā)場景。
即使沒有在結構體加上區(qū)分消息來源的標識,也可以用消息一開始傳入的源對象來大概定位到是哪一個類里面觸發(fā)的消息。文章來源地址http://www.zghlxwxcb.cn/news/detail-686898.html
到了這里,關于使用spring自帶的發(fā)布訂閱來實現(xiàn)發(fā)布訂閱的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!