入口類配置
@SpringBootApplication
@EnableWebSocketMessageBroker//開啓Stomp協議來傳輸基於代理(messagebroker)的消息,這時控制器支持使用@MessageMapping(同@RequestMapping)
public class Websocket3Application implements WebSocketMessageBrokerConfigurer {//AbstractWebSocketMessageBrokerConfigurer類在springboot2.x中已過時,新寫法改爲實現接口
public static void main(String[] args) {
SpringApplication.run(Websocket3Application.class, args);
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {//註冊Stomp協議的節點,並映射指定的URL
registry.addEndpoint("/endPointWisely").withSockJS();//註冊一個Stomp協議節點並指定使用SockJS協議
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {//配置消息代理MessageBroker
registry.enableSimpleBroker("/topic");//廣播式應配置一個/topic消息代理
//registry.setUserDestinationPrefix("/user");
}
}
mvc配置---頁面靜態資源訪問題和頁面訪問設置
此配置springboot會自動加載
// .js .css 等的靜態文件放置的目錄 因爲這兩個目錄是我手動建在resource下的,所以必須寫成"/目錄/**"
// 之前寫過springmvc配置有些類似配置,maven根據創建工程自動創建了static和templates兩個目錄也是默認爲項目根目錄下
所以配置爲"/**",根據書中寫的時候就出現了靜態資源訪問不到的錯誤
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {//spring5後 WebMvcConfigurerAdapter已過世
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
System.out.println("---------------1-------------------");
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
registry.addResourceHandler("/templates/**").addResourceLocations("classpath:/templates/");
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
System.out.println("---------------2-------------------");
registry.addViewController("websocket").setViewName("websocket");
registry.addViewController("test").setViewName("test");
}
}
瀏覽器向服務端發送消息類
由於前端sockjs向後臺發送的消息需通過反射機制實例化消息類對象,調用相應的get/set方法去實現,這裏必須要在類裏定義一個空構造方法,書籍中只寫了一個帶參的構造方法(寫了帶參的構造方法,空構造方法不再默認給出),導致服務端解析消息類時無法實例化類的對象,繼而無法執行Controller相應的方法(參數解析)
/**
* 瀏覽器向服務端發送消息類
*/
public class WiselyMessage {
private String name;
public WiselyMessage(){}
public WiselyMessage(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
瀏覽器向服務端發送消息類
/**
* 服務端向瀏覽器發送消息類
*/
public class WiselyResponse {
private String responseMessage;
public WiselyResponse(String responseMessage) {
this.responseMessage = responseMessage;
}
public String getResponseMessage() {
return responseMessage;
}
public void setResponseMessage(String responseMessage) {
this.responseMessage = responseMessage;
}
}
Controller
@Controller
public class WiselyController {
@MessageMapping("/welcome")//類似於RequestMapping
@SendTo("/topicgetResponse")//服務端有消息時,會對訂閱了@SendTo中的路徑的瀏覽器發送消息
public WiselyResponse say(WiselyMessage wiselyMessage) throws Exception{
Thread.sleep(3000);
System.out.println("--------------------ssss---------------");
return new WiselyResponse("Welcome,"+wiselyMessage.getName()+"!");
}
}
頁面(可不用模板),引入sockjs.js和stomp.js腳本文件(jquery也可用原生寫法替代)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Spring Boot+WebSocket 廣播式</title>
<script th:src="@{/js_ss/stomp.js}" type="text/javascript" ></script>
<script th:src="@{/js_ss/sockjs.js}" type="text/javascript"></script>
<script th:src="@{/js/jquery-1.7.1.js}" type="text/javascript"></script>
<script type="text/javascript">
var stompClient = null;
function setConnected(connected) {
//$("#connect").attr("disabled",connected)
// $("#disconnect").attr("disabled",!connected);
document.getElementById("connect").disabled=connected;
document.getElementById("disconnect").disabled=!connected;
if(connected){
document.getElementById("conversationDiv").style.display="";
}else{
document.getElementById("conversationDiv").style.display="none";
}
$("#response").html();
}
function connect() {
var socket= new SockJS('/endPointWisely');//連接SocketJS的endpoint名稱
stompClient =Stomp.over(socket);//2使用stomp協議的WebSocket客戶端
stompClient.connect({},function (frame) {//3連接webSocket客戶端
setConnected(true);
console.log('開始進行連接Connected:'+frame);
//接收消息
stompClient.subscribe('/topicgetResponse',function (response) {//4通過stompClient.subscribe訂閱topicgetResponse目標發送的消息(@SendTo中定義)
showResponse(JSON.parse(response.body).responseMessage);
});
});
}
function disconnect() {
if (stompClient!=null){
stompClient.disconnect();
}
setConnected(false);
console.log('Disconnected');
}
function showResponse(message) {
var response=$("#response");
response.html(message);
}
function sendName() {
var name= $("#name").val();
//發送消息
stompClient.send("/welcome",{},JSON.stringify({'name':name}));
}
</script>
</head>
<body onload="disconnect()">
<noscript>
<h2>貌似你的瀏覽器不支持WebSocket</h2>
</noscript>
<div>
<div>
<input id="connect" onclick="connect()" type="button" value="連接">
<input id="disconnect" disabled="disabled" onclick="disconnect()" type="button" value="斷開連接">
</div>
<div id="conversationDiv">
<label>名字:</label>
<input type="text" id="name"/>
<input type="button" id="sendName" onclick="sendName();" value="發送"/>
<p id="response"></p>
</div>
</div>
</body>
</html>