admin 管理员组

文章数量: 1086866

SpringBoot 2.0+ /springframwork 5 自带的websocket, 实现后台主动推消息给前端,及前端发消息给后台(全双工模式通信)

    java实现 websocket 全双工模式的通信,除了 springframwork 5 自带的websocket,还可以用Tomcat 7+ 来实现,但 tomcat 7 onOpen() ,onMessage() , onClose()  感觉没有springframwork 5实现来的自然顺畅。

   下面介绍实现实列 包括java 服务端,java客户端, 及 前端js部分 (附源码

1.导入maven依赖

<!--核心依赖项--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-messaging</artifactId></dependency><!--自动生成 get set 等方法--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!--js客户端的静态资源--><dependency><groupId>org.webjars</groupId><artifactId>webjars-locator-core</artifactId></dependency><dependency><groupId>org.webjars</groupId><artifactId>sockjs-client</artifactId><version>1.0.2</version></dependency><dependency><groupId>org.webjars</groupId><artifactId>stomp-websocket</artifactId><version>2.3.3</version></dependency><dependency><groupId>org.webjars</groupId><artifactId>bootstrap</artifactId><version>3.3.7</version></dependency><dependency><groupId>org.webjars</groupId><artifactId>jquery</artifactId><version>3.1.0</version></dependency>

2.工具类配置

定义一个访问地址的静态变量类

public class GlobalConsts {public static final String TOPIC = "/topic/greetings";public static final String ENDPOINT = "/gs-guide-websocket";public static final String APP_PREFIX = "/app";public static final String HELLO_MAPPING = "/hello";
}

服务端发消息的实体类

package com.ryh.websocket.demo.model;import lombok.AllArgsConstructor;
import lombok.Data;/*** @author ryh*/
@Data
@AllArgsConstructor
public class ServerMessage {private String content;public ServerMessage() {}@Overridepublic String toString() {return content;}}

客户端发消息的实体类
 

package com.ryh.websocket.demo.model;import lombok.AllArgsConstructor;
import lombok.Data;/*** @author ryh*/
@Data
@AllArgsConstructor
public class ClientMessage {private String name;public ClientMessage() {}}

3.websocket 服务端 配置类

package com.ryh.websocket.demo.config;import com.ryh.websocket.demo.consts.GlobalConsts;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;/*** @author ryh*/
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {@Overridepublic void configureMessageBroker(MessageBrokerRegistry config) {config.enableSimpleBroker("/topic");//  设置主题config.setApplicationDestinationPrefixes(GlobalConsts.APP_PREFIX);//  设置访问前缀}@Overridepublic void registerStompEndpoints(StompEndpointRegistry registry) {registry.addEndpoint(GlobalConsts.ENDPOINT).withSockJS();// 注册套接字js}}

4.服务端启动类
 

package com.ryh.websocket.demo;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;/*** @author ryh*/
@EnableScheduling
@SpringBootApplication
public class DemoWebSocketServer {public static void main(String[] args) {SpringApplication.run(DemoWebSocketServer.class, args);}
}

5.服务端与客户端及前端通信的控制类

package com.ryh.websocket.demo.controller;import com.ryh.websocket.demo.consts.GlobalConsts;
import com.ryh.websocket.demo.model.ClientMessage;
import com.ryh.websocket.demo.model.ServerMessage;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
import org.springframework.web.util.HtmlUtils;/*** Created with IntelliJ IDEA.* Description:** @author ryh**/
@Controller
public class GreetingController {@MessageMapping(GlobalConsts.HELLO_MAPPING)@SendTo(GlobalConsts.TOPIC)public ServerMessage greeting(ClientMessage message) throws Exception {// 模拟延时,以便测试客户端是否在异步工作Thread.sleep(1000);return new ServerMessage("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!");}
}

6.js 及 html 客户端

  html

<!DOCTYPE html>
<html>
<head><title>Hello WebSocket</title><link href="/webjars/bootstrap/css/bootstrap.min.css" rel="stylesheet"><link href="/main.css" rel="stylesheet"><script src="/webjars/jquery/jquery.min.js"></script><script src="/webjars/sockjs-client/sockjs.min.js"></script><script src="/webjars/stomp-websocket/stomp.min.js"></script><script src="/app.js"></script>
</head>
<body>
<noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websocket relies on Javascript beingenabled. Please enableJavascript and reload this page!</h2></noscript>
<div id="main-content" class="container"><div class="row"><div class="col-md-6"><form class="form-inline"><div class="form-group"><label for="connect">WebSocket connection:</label><button id="connect" class="btn btn-default" type="submit">Connect</button><button id="disconnect" class="btn btn-default" type="submit" disabled="disabled">Disconnect</button></div></form></div><div class="col-md-6"><form class="form-inline"><div class="form-group"><label for="name">What is your name?</label><input type="text" id="name" class="form-control" placeholder="Your name here..."></div><button id="send" class="btn btn-default" type="submit">Send</button></form></div></div><div class="row"><div class="col-md-12"><table id="conversation" class="table table-striped"><thead><tr><th>Greetings</th></tr></thead><tbody id="greetings"></tbody></table></div></div>
</div>
</body>
</html>

js

var stompClient = null;function setConnected(connected) {$("#connect").prop("disabled", connected);$("#disconnect").prop("disabled", !connected);if (connected) {$("#conversation").show();}else {$("#conversation").hide();}$("#greetings").html("");
}function connect() {var socket = new SockJS('/gs-guide-websocket');stompClient = Stomp.over(socket);stompClient.connect({}, function (frame) {setConnected(true);console.log('Connected: ' + frame);stompClient.subscribe('/topic/greetings', function (greeting) {showGreeting(JSON.parse(greeting.body).content);});});
}function disconnect() {if (stompClient !== null) {stompClient.disconnect();}setConnected(false);console.log("Disconnected");
}function sendName() {stompClient.send("/app/hello", {}, JSON.stringify({'name': $("#name").val()}));
}function showGreeting(message) {$("#greetings").append("<tr><td>" + message + "</td></tr>");
}$(function () {$("form").on('submit', function (e) {e.preventDefault();});$( "#connect" ).click(function() { connect(); });$( "#disconnect" ).click(function() { disconnect(); });$( "#send" ).click(function() { sendName(); });
});

7.定时推送消息类

  该类实现了,每分钟往前端发送消息的推送,(前提前端有和 服务端进行长连接,且没断开)

@Slf4j
@Component
public class SendMessageSchedule {@Autowiredprivate SimpMessagingTemplate simpMessagingTemplate;@Scheduled(fixedRate = 1000 * 60 * 1)//每分钟发一次public void releaseClaimPoint() {ServerMessage msg = new ServerMessage();Random random = new Random();Map<Integer, String> map = new HashMap<>();map.put(1,"德玛西亚之力 盖伦");map.put(2,"至高之拳 李青");map.put(3,"疾风剑豪 亚索");map.put(4,"迅捷斥候 提莫");map.put(5,"恐惧新星 德莱厄斯");map.put(6,"祖安狂人 蒙多");Integer[] keys = map.keySet().toArray(new Integer[0]);Integer randomKey = keys[random.nextInt(keys.length)];String randomName = map.get(randomKey);msg.setContent(randomName);log.info("往客户端发送的name是 "+randomName);simpMessagingTemplate.convertAndSend(TOPIC, msg);}
}

8.服务端发送消息

9.客户端接收请求

 

10.源码下载     

 

本文标签: SpringBoot20springframwork 5 自带的websocket 实现后台主动推消息给前端,及前端发消息给后台(全双工模式通信)