SpringBoot+sockjs client+stompjs實現websocket

Grade構建依賴

build.gradle文件配置以下html

buildscript {
	ext {
		springBootVersion = '1.5.9.RELEASE'
	}
	repositories {
		mavenCentral()
	}
	dependencies {
		classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
	}
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
	mavenCentral()
}


dependencies {
	compile('org.springframework.boot:spring-boot-starter-data-redis')
	compile('org.springframework.boot:spring-boot-starter-web')
	compile('org.springframework.data:spring-data-redis')
	compile group: 'com.alibaba', name: 'fastjson', version: '1.1.15'
	runtime('mysql:mysql-connector-java')

	compile("org.springframework.boot:spring-boot-starter-websocket")
	compile("org.webjars:webjars-locator-core")
	compile("org.webjars:sockjs-client:1.0.2")
	compile("org.webjars:stomp-websocket:2.3.3")
	testCompile('org.springframework.boot:spring-boot-starter-test')
}
複製代碼

構建STOMP消息服務、服務交互流程

建立一個資源表示

服務將接受包含STOMP消息中名稱的消息,該消息的主體是JSON對象。若是給出的名稱是「Test」,那麼該消息可能以下所示:前端

{
    "username ": "Test"
}
複製代碼

爲了建模帶有名稱的消息,可使用username 屬性和相應的getUsername()方法建立一個普通的舊Java對象:java

public class ReceiveBean {
    private String username;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String toString() {
        return "UserBeans{" +
                "username='" + username + '\'' + '}'; } } 複製代碼

在收到消息並提取名稱後,服務將經過建立問候語並在客戶端訂閱的單獨隊列上發佈該問候語來處理它。問候語也將是一個JSON對象,可能看起來像這樣:mysql

{
    "content": "Hello, Test!"
}
複製代碼

爲了建模問候表示,能夠添加另外一個具備content屬性和相應getContent()方法的普通舊Java對象:web

public class ServerStatus {
    private String content;

    public ServerStatus() {}
    public ServerStatus (String content) {
        this.content = content;
    }

    public String getContent () {
        return content;
    }
}
複製代碼

Spring將使用Jackson JSON庫自動將類型實例編組Greeting爲JSON。 接下來,建立一個控制器來接收serverStatus消息併發送問候消息。 #####建立消息處理控制器 在Spring使用STOMP消息傳遞的方法中,STOMP消息能夠映射到到@Controller類。例如,它ServerStatusController被映射爲處理消息到目的地「/serverStatus」redis

@Controller
@EnableScheduling
public class ServerStatusController  {
    @Autowired
    private SimpMessagingTemplate simpMessagingTemplate;

    //當瀏覽器向服務端發送請求時,經過@MessageMapping映射的地址,相似於@RequestMapping
    @MessageMapping("/serverStatus")
    @SendTo("/receive/message") //廣播全部用戶
    //傳遞的參數會自動的被注入到userbean中
    public ServerStatus serverStatus (ReceiveBean receiveBean) throws InterruptedException {
        // 返回值被廣播給全部訂戶,如@SendTo註釋中所指定的"/receive/message" 。請注意,來自輸入消息的名稱已被清理,由於在這種狀況下,它將被回顯並從新呈如今客戶端的瀏覽器DOM中。
        return new ServerStatus((int) (Math.random() * 10 + 50));
    }
    @Scheduled(fixedRate = 5000) //每一個5秒提取一次
    @SendTo("/receive/message") //廣播全部用戶
    public Object sendAllMessage () {
        // 發現消息
        simpMessagingTemplate.convertAndSend("/receive/message", new ServerStatus((int) (Math.random() * 10 + 50)));
        return "callback";
    }
}
複製代碼
爲STOMP消息傳遞配置Spring

配置Spring以啓用WebSocket和STOMP消息傳遞。spring

/**
 * 爲STOMP消息傳遞配置Spring
 * WebSocketConfig被註釋@Configuration爲代表它是一個Spring配置類。
 * @EnableWebSocketMessageBroker: @EnableWebSocketMessageBroker啓用WebSocket消息處理,由消息代理支持。
 */
@Configuration //@Configuration註解代表它是一個Spring配置類
@EnableWebSocketMessageBroker //經過@EnableWebSocketMessageBroker 註解啓用WebSocket消息處理,由消息代理支持。
public class WebsocketConfig  implements WebSocketMessageBrokerConfigurer{
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        /*
         * 該registerStompEndpoints()方法註冊「/serverStatus」端點,
         * 啓用SockJS後備選項,以便在WebSocket不可用時可使用替代傳輸。
         * SockJS客戶端將嘗試鏈接到「/serverStatus」並使用可用的最佳傳輸(websocket,xhr-streaming,xhr-polling等)。
         * setAllowedOrigins: 容許跨域
         */
        registry.addEndpoint("/serverStatus").setAllowedOrigins("*").withSockJS();
    }

    /**
     * 配置消息代理
     * @param registry
     */
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/receive"); // 調用enableSimpleBroker()一個簡單的基於內存的消息代理,將問候消息帶回以「/ receive」爲前綴的客戶端
//        registry.setApplicationDestinationPrefixes("/app"); //爲綁定了@MessageMapping註解方法的消息指定「/ app」前綴,該前綴將用於定義全部消息映射
    }

    @Override
    public void configureWebSocketTransport(WebSocketTransportRegistration registry) {

    }

    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {

    }

    @Override
    public void configureClientOutboundChannel(ChannelRegistration registration) {

    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {

    }

    @Override
    public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {

    }

    @Override
    public boolean configureMessageConverters(List<MessageConverter> messageConverters) {
        return false;
    }
}
複製代碼

瀏覽器客戶端

服務器端部分就緒的狀況下,向服務器端發送消息並從服務器端接收消息的JavaScript客戶端

SockJS是一個瀏覽器JavaScript庫,提供了一個相似WebSocket的對象。SockJS爲您提供了一個連貫的,跨瀏覽器的JavaScript API,它在瀏覽器和Web服務器之間建立了一個低延遲,全雙工,跨域的通訊通道。 在底層SockJS首先嚐試使用本地WebSocket。若是失敗了,它可使用各類瀏覽器特定的傳輸協議,並經過WebSocket相似的抽象方式呈現它們。sql

安裝socket-client
npm install sockjs-client
複製代碼

經過在WebSocket 之上使用 STOMP協議,來爲瀏覽器 和 server 間的 通訊增長適當的消息語義。(STOMP—— Simple Text Oriented Message Protocol——面向消息的簡單文本協議)npm

安裝STOMPJS
npm install @stomp/stompjs websocket --save
複製代碼
前端代碼以下
const SockJS = require('sockjs-client')
const Stomp = require('@stomp/stompjs')
const socket = new SockJS('http://127.0.0.1:8080/serverStatus')
const stompClient = Stomp.over(socket)  //建立STOMP客戶端
stompClient.connect({}, (frame) => {   //鏈接到服務器
   let bean = {
      username: 'Test'
   }
   stompClient.send('/serverStatus', {}, JSON.stringify(bean)) //發送信息
   stompClient.subscribe('/receive/message', (receive) => { //訂閱並接收消息
       console.log('greeting', JSON.parse(receive.body))
   })
})
複製代碼

#####效果如圖: json

image.png
image.png
相關文章
相關標籤/搜索