今天繼續Websocket之STOMP協議,因爲其設計簡單,在開發客戶端方面使用簡便,在不少種語言上均可以見到其身影,並不是websocket「獨享」。前端
STOMP(Simple/Streaming Text Orientated Messaging Protocol),即簡單(流)文本定向消息協議。屬於消息隊列的一種協議,有點相似於jms。java
提供消息體的格式,容許STOMP客戶端(Endpoints)與任意STOMP消息代理(message broker)進行交互,實現客戶端之間進行異步消息傳送。web
圖片來源《spring in action》spring
下面使用SpringSecurity和WebSocket-STOMP實現「點對點」消息發送功能:json
@Configuration
@EnableWebSocketMessageBroker//開啓消息代理
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
/** * 創建鏈接點信息 * @param registry */
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws/ep").withSockJS();
registry.setApplicationDestinationPrefixes("/app");
}
/** * 配置消息隊列 * 基於內存的STOMP消息代理 * @param registry */
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/queue");
}
}
複製代碼
- 將 "/ws/ep" 註冊爲一個 STOMP 端點。客戶端在訂閱或發佈消息到目的地路徑前,要鏈接到該端點
- 以 /app 開頭的消息都會被路由到帶有@MessageMapping 或 @SubscribeMapping 註解的方法中;
- 以 /queue 開頭的消息都會發送到STOMP代理中,根據所選擇的STOMP代理不一樣,目的地的可選前綴也會有所限制;
- 以/user開頭的消息會將消息重路由到某個用戶獨有的目的地上。
自定義通訊協議websocket
@Controller
public class WScontroller {
@Autowired//消息發送模板
SimpMessagingTemplate simpMessagingTemplate;
@MessageMapping("/ws/chat")
public void receiveMessage(String message, Principal principal) {
String[] split = message.split(";");
HashMap<String, Object> map = new HashMap<>();
map.put("username",split[1]);
map.put("msg",split[0]);
simpMessagingTemplate.convertAndSendToUser(split[1], "/queue/msg",map);
}
複製代碼
- 接收客戶端發來的消息,參數就是消息自己
message
- @MessageMapping 或者 @SubscribeMapping 註解能夠處理客戶端發送過來的消息,並選擇方法是否有返回值。
- @MessageMapping 指定目的地是「/app/ws/chat」(「/app」前綴是隱含的,由於咱們將其配置爲應用的目的地前綴)。
- 通訊協議能夠自定義——可自定義參數的格式
- 能夠接收json格式的數據,傳遞josn數據時不須要添加額外註解@Requestbody
- 消息發送者不是從前端傳遞過來的,而是從springsecurity中獲取的,防止前端冒充
- 若是 @MessageMapping 註解的控制器方法有返回值的話,返回值會被髮送到消息代理,只不過會添加上"/topic"前綴。
- 經過爲方法添加@SendTo註解,重載目的地
客戶端代碼(UVE)app
<template>
<div>
<div>
<div v-for="(m,index) in ms">{{m.username}}:{{m.msg}}</div>
</div>
<el-input v-model="msg"></el-input>
<el-button @click="sendMsg"></el-button>
</div>
</template>
<script>
import "../../lib/sockjs"
import "../../lib/stomp"
export default {
name: "FriendChat",
data() {
return {
msg: '',
ms: [],
stomp: null
};
},
mounted() {
this.intCon();
},
methods: {
// 創建鏈接
initCon() {
let _this = this;
this.stomp = Stomp.over(new SockJS("/ws/ep"));
this.stomp.connect({},success=>{
_this.stomp.subscribe("/user/queue/msg",msg=>{
_this.ms.push(JSON.parse(msg.body));
})
},fail=>{
})
},
// 發送消息
sendMsg() {
this.stomp.send("/ws/chat",{},this.msg)
}
}
}
</script>
<style scoped>
</style>
複製代碼