spring boot 集成 websocket 实现消息主动
来源:https://www.cnblogs.com/leigepython/p/11058902.html
pom.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4 <modelVersion>4.0.0</modelVersion>
5 <parent>
6 <groupId>org.springframework.boot</groupId>
7 <artifactId>spring-boot-starter-parent</artifactId>
8 <version>2.1.1.RELEASE</version>
9 <relativePath/> <!-- lookup parent from repository -->
10 </parent>
11 <groupId>com.zhengcj</groupId>
12 <artifactId>spring-boot-09-websocket</artifactId>
13 <version>0.0.1-SNAPSHOT</version>
14 <name>spring-boot-09-websocket</name>
15 <description>Demo project for Spring Boot</description>
16
17 <properties>
18 <java.version>1.8</java.version>
19 </properties>
20
21 <dependencies>
22 <dependency>
23 <groupId>org.springframework.boot</groupId>
24 <artifactId>spring-boot-starter-thymeleaf</artifactId>
25 </dependency>
26 <dependency>
27 <groupId>org.springframework.boot</groupId>
28 <artifactId>spring-boot-starter-web</artifactId>
29 </dependency>
30 <dependency>
31 <groupId>org.springframework.boot</groupId>
32 <artifactId>spring-boot-starter-websocket</artifactId>
33 </dependency>
34
35 <dependency>
36 <groupId>org.springframework.boot</groupId>
37 <artifactId>spring-boot-starter-test</artifactId>
38 <scope>test</scope>
39 </dependency>
40 </dependencies>
41
42 <build>
43 <plugins>
44 <plugin>
45 <groupId>org.springframework.boot</groupId>
46 <artifactId>spring-boot-maven-plugin</artifactId>
47 </plugin>
48 </plugins>
49 </build>
50
51
52 </project>
SpringBoot09WebsocketApplication.java
1 package com.zhengcj.websocket;
2
3 import org.springframework.boot.SpringApplication;
4 import org.springframework.boot.autoconfigure.SpringBootApplication;
5
6 /**
7 * 地址:https://www.cnblogs.com/leigepython/p/11058902.html
8 * @author zhengcj
9 *
10 */
11 @SpringBootApplication
12 public class SpringBoot09WebsocketApplication {
13
14 public static void main(String[] args) {
15 SpringApplication.run(SpringBoot09WebsocketApplication.class, args);
16 }
17
18 }
WebSocketConfig.java
1 package com.zhengcj.websocket.config;
2
3 import org.springframework.context.annotation.Bean;
4 import org.springframework.context.annotation.Configuration;
5 import org.springframework.web.socket.server.standard.ServerEndpointExporter;
6
7 /**
8 * @author zhengcj
9 * @Date 2020年4月27日 上午11:37:26
10 * @version
11 * @Description socket配置类,往 spring 容器中注入ServerEndpointExporter实例
12 *
13 */
14 @Configuration
15 public class WebSocketConfig {
16 @Bean
17 public ServerEndpointExporter serverEndpointExporter() {
18 return new ServerEndpointExporter();
19 }
20
21 }
WebSocketServer.java
1 package com.zhengcj.websocket.common;
2
3 import java.io.IOException;
4 import java.util.HashMap;
5 import java.util.Map;
6 import java.util.concurrent.atomic.AtomicInteger;
7
8 import javax.websocket.OnClose;
9 import javax.websocket.OnError;
10 import javax.websocket.OnMessage;
11 import javax.websocket.OnOpen;
12 import javax.websocket.Session;
13 import javax.websocket.server.PathParam;
14 import javax.websocket.server.ServerEndpoint;
15
16 import org.springframework.stereotype.Component;
17
18 /**
19 * WebSocket服务端代码,包含接收消息,推送消息等接口
20 * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
21 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
22 * @author zhengcj
23 * @Date 2020年4月27日 下午1:36:13
24 * @version
25 * @Description
26 */
27 @Component
28 @ServerEndpoint(value = "/socket/{name}")
29 public class WebSocketServer {
30
31 // 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
32 private static AtomicInteger online = new AtomicInteger();
33 // concurrent包的线程安全Set,用来存放每个客户端对应的WebSocketServer对象。
34 // private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
35 private static Map<String, Session> sessionPools = new HashMap<>();
36
37 /**
38 * 发送消息方法
39 * @param session 客户端与socket建立的会话
40 * @param message 消息
41 * @throws IOException
42 */
43 public void sendMessage(Session session, String message) throws IOException {
44 if (session != null) {
45 session.getBasicRemote().sendText(message);
46 }
47 }
48
49 /**
50 * 连接建立成功调用
51 * @param sessionv 客户端与socket建立的会话
52 * @param userName 客户端的userName
53 */
54 @OnOpen
55 public void onOpen(Session session, @PathParam(value = "name") String userName) {
56 sessionPools.put(userName, session);
57 addOnlineCount();
58 System.out.println(userName + "加入webSocket!当前人数为" + online);
59 try {
60 sendMessage(session, "欢迎" + userName + "加入连接!");
61 } catch (IOException e) {
62 e.printStackTrace();
63 }
64 }
65
66 /**
67 * 关闭连接时调用
68 * @param userName 关闭连接的客户端的姓名
69 */
70 @OnClose
71 public void onClose(@PathParam(value = "name") String userName) {
72 sessionPools.remove(userName);
73 subOnlineCount();
74 System.out.println(userName + "断开webSocket连接!当前人数为" + online);
75 }
76
77 /**
78 * 收到客户端消息时触发(群发)
79 * @param message
80 * @throws IOException
81 */
82 @OnMessage
83 public void onMessage(String message) throws IOException {
84 System.out.println("群发信息:"+message);
85 for (Session session : sessionPools.values()) {
86 try {
87 sendMessage(session, message);
88 } catch (Exception e) {
89 e.printStackTrace();
90 continue;
91 }
92 }
93 }
94
95 /**
96 * 发生错误时候
97 * @param session
98 * @param throwable
99 */
100 @OnError
101 public void onError(Session session, Throwable throwable) {
102 System.out.println("发生错误");
103 throwable.printStackTrace();
104 }
105
106 /**
107 * 给指定用户发送消息
108 *
109 * @param userName
110 * 用户名
111 * @param message
112 * 消息
113 * @throws IOException
114 */
115 public void sendInfo(String userName, String message) {
116 Session session = sessionPools.get(userName);
117 try {
118 sendMessage(session, message);
119 } catch (Exception e) {
120 e.printStackTrace();
121 }
122 }
123
124 public static void addOnlineCount() {
125 online.incrementAndGet();
126 }
127
128 public static void subOnlineCount() {
129 online.decrementAndGet();
130 }
131 }
WebMvcConfig.java
1 package com.zhengcj.websocket.config;
2
3 import org.springframework.context.annotation.Configuration;
4 import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
5 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
6
7 /**
8 * @author zhengcj
9 * @Date 2020年4月27日 下午1:38:31
10 * @version
11 * @Description
12 *
13 * 在SpringBoot2.0及Spring 5.0 WebMvcConfigurerAdapter已被废弃,目前找到解决方案就有
14 * 1 直接实现WebMvcConfigurer (官方推荐)
15 * 2 直接继承WebMvcConfigurationSupport
16 * @ https://blog.csdn.net/lenkvin/article/details/79482205
17 */
18 @Configuration
19 public class WebMvcConfig implements WebMvcConfigurer{
20 /**
21 * 为各个页面提供路径映射
22 * @param registry
23 */
24 @Override
25 public void addViewControllers(ViewControllerRegistry registry) {
26 registry.addViewController("/zhengcj").setViewName("zhengcj");
27 registry.addViewController("/yuzh").setViewName("yuzh");
28 }
29 }
SocketController.java
1 package com.zhengcj.websocket.controller;
2
3 import java.io.IOException;
4
5 import javax.annotation.Resource;
6
7 import org.springframework.web.bind.annotation.GetMapping;
8 import org.springframework.web.bind.annotation.RequestParam;
9 import org.springframework.web.bind.annotation.RestController;
10
11 import com.zhengcj.websocket.common.WebSocketServer;
12
13 /**
14 * @author zhengcj
15 * @Date 2020年4月27日 下午1:44:32
16 * @version
17 * @Description
18 *
19 */
20 @RestController
21 public class SocketController {
22 @Resource
23 private WebSocketServer webSocketServer;
24
25 /**
26 * 给指定用户推送消息
27 * @param userName 用户名
28 * @param message 消息
29 * @throws IOException
30 */
31 @GetMapping("/socket")
32 public void pushOneUser(@RequestParam String userName, @RequestParam String message){
33 System.err.println("====socket===="+message);
34 webSocketServer.sendInfo(userName, message);
35 }
36
37 /**
38 * 给所有用户推送消息
39 * @param message 消息
40 * @throws IOException
41 */
42 @GetMapping("/socket/all")
43 public void pushAllUser(@RequestParam String message){
44 try {
45 System.err.println("====socket/all===="+message);
46 webSocketServer.onMessage(message);
47 } catch (IOException e) {
48 e.printStackTrace();
49 }
50 }
51 }
yuzh.html
<!DOCTYPE HTML>
<html>
<head>
<title>WebSocket</title>
</head> <body>
Welcome
<br />
<input id="text" type="text" />
<button onclick="send()">Send</button>
<button onclick="closeWebSocket()">Close</button>
<div id="message"></div>
</body> <script type="text/javascript">
var websocket = null; //判断当前浏览器是否支持WebSocket
if ('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:8080/socket/yuzh");
} else {
alert('Not support websocket')
} //连接发生错误的回调方法
websocket.onerror = function() {
setMessageInnerHTML("error");
}; //连接成功建立的回调方法
websocket.onopen = function(event) {
setMessageInnerHTML("open");
} //接收到消息的回调方法
websocket.onmessage = function(event) {
setMessageInnerHTML(event.data);
} //连接关闭的回调方法
websocket.onclose = function() {
setMessageInnerHTML("close");
} //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function() {
websocket.close();
} //将消息显示在网页上
function setMessageInnerHTML(innerHTML) {
document.getElementById('message').innerHTML += innerHTML + '<br/>';
} //关闭连接
function closeWebSocket() {
websocket.close();
} //发送消息
function send() {
var message = document.getElementById('text').value;
websocket.send(message);
}
</script>
</html>
zhengcj.html
<!DOCTYPE HTML>
<html>
<head>
<title>WebSocket</title>
</head> <body>
Welcome
<br />
<input id="text" type="text" />
<button onclick="send()">Send</button>
<button onclick="closeWebSocket()">Close</button>
<div id="message"></div>
</body> <script type="text/javascript">
var websocket = null; //判断当前浏览器是否支持WebSocket
if ('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:8080/socket/zhengcj");
} else {
alert('Not support websocket')
} //连接发生错误的回调方法
websocket.onerror = function() {
setMessageInnerHTML("error");
}; //连接成功建立的回调方法
websocket.onopen = function(event) {
setMessageInnerHTML("open");
} //接收到消息的回调方法
websocket.onmessage = function(event) {
setMessageInnerHTML(event.data);
} //连接关闭的回调方法
websocket.onclose = function() {
setMessageInnerHTML("close");
} //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function() {
websocket.close();
} //将消息显示在网页上
function setMessageInnerHTML(innerHTML) {
document.getElementById('message').innerHTML += innerHTML + '<br/>';
} //关闭连接
function closeWebSocket() {
websocket.close();
} //发送消息
function send() {
var message = document.getElementById('text').value;
websocket.send(message);
}
</script>
</html>
spring boot 集成 websocket 实现消息主动的更多相关文章
- spring boot 集成 websocket 实现消息主动推送
spring boot 集成 websocket 实现消息主动 前言 http协议是无状态协议,每次请求都不知道前面发生了什么,而且只可以由浏览器端请求服务器端,而不能由服务器去主动通知浏览器端,是单 ...
- Spring Boot 集成 WebSocket 实现服务端推送消息到客户端
假设有这样一个场景:服务端的资源经常在更新,客户端需要尽量及时地了解到这些更新发生后展示给用户,如果是 HTTP 1.1,通常会开启 ajax 请求询问服务端是否有更新,通过定时器反复轮询服务端响应的 ...
- 【websocket】spring boot 集成 websocket 的四种方式
集成 websocket 的四种方案 1. 原生注解 pom.xml <dependency> <groupId>org.springframework.boot</gr ...
- spring boot集成Websocket
websocket实现后台像前端主动推送消息的模式,可以减去前端的请求获取数据的模式.而后台主动推送消息一般都是要求消息回馈比较及时,同时减少前端ajax轮询请求,减少资源开销. spring boo ...
- Spring boot集成Websocket,前端监听心跳实现
第一:引入jar 由于项目是springboot的项目所以我这边简单的应用了springboot自带的socket jar <dependency> <groupId>org. ...
- spring boot集成websocket实现聊天功能和监控功能
本文参考了这位兄台的文章: https://blog.csdn.net/ffj0721/article/details/82630134 项目源码url: https://github.com/zhz ...
- Spring Boot之WebSocket
一.项目说明 1.项目地址:https://github.com/hqzmss/test01-springboot-websocket.git 2.IDE:IntelliJ IDEA 2018.1.1 ...
- spring boot 集成 zookeeper 搭建微服务架构
PRC原理 RPC 远程过程调用(Remote Procedure Call) 一般用来实现部署在不同机器上的系统之间的方法调用,使得程序能够像访问本地系统资源一样,通过网络传输去访问远程系统资源,R ...
- Spring boot入门(二):Spring boot集成MySql,Mybatis和PageHelper插件
上一篇文章,写了如何搭建一个简单的Spring boot项目,本篇是接着上一篇文章写得:Spring boot入门:快速搭建Spring boot项目(一),主要是spring boot集成mybat ...
随机推荐
- flink安装及standalone模式启动、idea中项目开发
安装 环境 Ubuntu 18 jdk8 flink-1.8.1 安装步骤 安装jdk(略) 下载flink-1.8.1-bin-scala_2.12.tgz,解压到指定目录 wget http:// ...
- Netty源码解析 -- PoolSubpage实现原理
前面文章说了PoolChunk如何管理Normal内存块,本文分享PoolSubpage如何管理Small内存块. 源码分析基于Netty 4.1.52 内存管理算法 PoolSubpage负责管理S ...
- 在matlab 画箭头
[转载]在matlab 画箭头 原文地址:在matlab 画箭头作者:纯情小郎君 完整见链接http://www.mathworks.com/matlabcentral/fx_files/14056/ ...
- 将XML转换为实体
需求 将XML文件中的数据经过转换后插入到数据库中. 参考 C#实体类和XML的相互转换 https://blog.csdn.net/pan_junbiao/article/details/82938 ...
- H3C S5120V2-SI 交换机配置
连接终端线 可以看到开机信息 ......................................................................Done. System is ...
- Mybatis【8】-- Mybatis返回List或者Map以及模糊查询怎么搞?
使用mybatis的时候,经常发现一个需求,我怎么知道自己是不是增加/修改/删除数据成功了? 好像执行sql之后都没有结果的.其实不是的,增删改的sql执行之后都会有一个int类型的返回值,表示的意思 ...
- 在 xunit 测试项目中使用依赖注入
在 xunit 测试项目中使用依赖注入 Intro 之前写过几篇 xunit 依赖注入的文章,今天这篇文章将结合我在 .NET Conf 上的分享,更加系统的分享一下在测试中的应用案例. 之所以想分享 ...
- 【整理】互联网服务端技术体系:高性能之并发(Java)
分而合之,并行不悖. 综述入口见:"互联网应用服务端的常用技术思想与机制纲要" 引子 并发,就是在同一时间段内有多个任务同时进行着.这些任务或者互不影响互不干扰,或者共同协作来完成 ...
- Java数组的三种打印方式
1.数组的输出的三种方式 一维数组: 定义一个数组 int[] array = {1,2,3,4,5}; (1)传统的for循环方式 for(int i=0;i<array.length;i++ ...
- Linux课程知识点总结(二)
Linux课程知识点总结(二) 七.Shell实用功能 7.1 命令行自动补全 在Linux系统中,有太多的命令和文件名称需要记忆,使用命令行补全功能[Tab]可以快速的写出文件名和命令名 7.2 命 ...