因为最近有后端实时推送数据的需求,所以想到了websocket组件,在此写一下springboot集成使用websocket的方法,供各位童鞋参考。
注:基于test项目。
1.首先打开pom.xml引入相关依赖
<!-- webSocket --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <!-- thymeleaf模板引擎 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
2.编写websocket配置文件:
@Configuration @EnableWebSocketMessageBroker public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry registry) { //注册STOMP协议的节点(endpoint),并映射指定的url //注册一个STOMP的endpoint,并指定使用SockJS协议 // 允许使用socketJs方式访问,访问点为webSocketServer,允许跨域 // 在网页上我们就可以通过这个链接来和服务器的WebSocket连接 registry.addEndpoint("/endpointTest").setAllowedOrigins("*").withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { //配置消息代理(Message Broker) //广播式应配置一个/topic消息代理 //queue 点对点 registry.enableSimpleBroker("/queue","/topic"); } }
3.webmvc配置
/** * @author xiaofeng * @version V1.0 * @title: WebMvcConfig.java * @package: com.yingda.xsignal.test * @description: 配置viewController, 为页面提供路径映射 * @date 2018/3/30 0030 下午 7:05 */ @Controller public class WebMvcConfig extends WebMvcConfigurerAdapter { /** * 配置viewController,提供映射路径 */ @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/webSocket").setViewName("/webSocket"); } }
4.websocket控制器
/** * @author xiaofeng * @version V1.0 * @title: WebSocketController.java * @package: com.yingda.xsignal.test * @description: webSocket控制器 * @date 2018/3/30 0030 下午 7:04 */ @RestController @EnableScheduling public class WebSocketController { private Logger logger = LoggerFactory.getLogger(getClass()); /** * 当浏览器向服务端发送请求时,通过@MessageMapping映射/sendTest这个地址,类似于@ResponseMapping * 当服务器有消息时,会对订阅了@SendTo中的路径的浏览器发送消息 * * @param message * @return */ @MessageMapping("/sendTest") @SendTo("/topic/responseTest") public String say(String message) { try { //睡眠1秒 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return message; } @SubscribeMapping("/topic/responseTest") public String sub() { logger.info("X用户订阅了"); return "thanks for your subscribe!"; } @Autowired WebSocketTemplate webSocketTemplate; /** * 模拟服务端推送数据(注:必须在同一个服务内,否则无法进行订阅推送) */ @Scheduled(fixedRate = 2000) public void task() { webSocketTemplate.sendMessage("服务器端推送~" + UUID.randomUUID()); } }
WebSocketTemplate:
/** * @author xiaofeng * @version V1.0 * @title: WebSocketTemplate.java * @package: com.yingda.xsignal.test.websocket.send * @description: webSocket发送模板 * @date 2018/3/30 0030 下午 3:57 */ @Component public class WebSocketTemplate { private SimpMessagingTemplate messagingTemplate; @Autowired public WebSocketTemplate(SimpMessagingTemplate messagingTemplate) { this.messagingTemplate = messagingTemplate; } /** * 向订阅了 /topic/responseTest 客户端websocket实例发送数据 * * @param message */ public void sendMessage(String message) { AricMessage aricMessage = new AricMessage(); aricMessage.setName(message); messagingTemplate.convertAndSend("/topic/responseTest", aricMessage); } }
5.在resources -> templates中创建html文件
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8" /> <title>SpringBoot 服务端推送消息</title> <script src="http://cdn.bootcss.com/sockjs-client/1.1.1/sockjs.min.js"></script> <script src="http://cdn.bootcss.com/stomp.js/2.3.3/stomp.js"></script> <script src="http://cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script> </head> <body> <div> <div> <button id="connect" οnclick="connect();">connect</button> <button id="disconnect" disabled="disabled" οnclick="disconnect();">disconnect</button> </div> <div id="conversationDiv"> <div id="response"></div> </div> </div> </body> <script type="text/javascript"> var stompClient = null; function setConnected(connected){ document.getElementById('connect').disabled = connected; document.getElementById('disconnect').disabled = !connected; document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden'; $("#response").html(); } function connect(){ var socket = new SockJS('/endpointTest'); //连接SockJS的endpoint名称为"endpointTest" stompClient = Stomp.over(socket);//使用STMOP子协议的WebSocket客户端 stompClient.connect({},function(frame){//连接WebSocket服务端 setConnected(true); console.log('Connected:' + frame); //通过stompClient.subscribe订阅/topic/responseTest 目标(destination)发送的消息,这个是在控制器的@SentTo中定义的 stompClient.subscribe('/topic/responseTest',function(response){ showResponse(JSON.parse(response.body).name); }); }); } function disconnect(){ if(stompClient != null) { stompClient.disconnect(); } setConnected(false); console.log("Disconnected"); } function showResponse(message){ var response = $("#response"); response.html(message); } </script> </html>
启动服务,测试,点击connect,发现每隔几秒随机字符串都会发生变化,说明后台服务一直在向前端推送数据
ok,至此我们的springboot集成websocket并向前端推送数据成功,congratulation!