ruoyi若依整合websocket
原文链接:https://blog.csdn.net/qq_33342112/article/details/132096930
注:本文档中的ruoyi框架为前后不分离版本,nginx配置与前后分离版有所不同。
一、导pom,版本需与springboot版本一致
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>2.5.15</version>
</dependency>
如果是新建module,则需要在ruoyi-admin的pom.xml中导入新建的module,否则注解不生效
<dependency>
<groupId>com.ruoyi</groupId>
<!-- 新module的名称 -->
<artifactId>ruoyi-websocket</artifactId>
</dependency>
二、注册websocket
@Configuration
@EnableWebSocket
public class SpringWebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
System.out.println("注册websocket");
//固定连接路径则使用/ws,如/ws后还有参数,则追加/*通配符
registry.addHandler(new MyWebSocketHandler(), "/ws/*")//设置连接路径和处理器
.setAllowedOrigins("*") //允许跨域访问
.addInterceptors(new MyWebSocketInterceptor());//设置拦截器
}
}
三、创建拦截器 MyWebSocketInterceptor
public class MyWebSocketInterceptor implements HandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest servletRequest, ServerHttpResponse servletResponse, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
System.out.println("websocket前置拦截");
//如果用到Sec-WebSocket-Protocol,可以采用getHeaders().get(key)的方法获取
if (servletRequest.getHeaders().get("Sec-WebSocket-Protocol") == null) {
System.out.println("无Sec-WebSocket-Protocol,进行拦截!");
return false;
}
String protocol = servletRequest.getHeaders().get("Sec-WebSocket-Protocol").get(0);
//如果uri的路径中带有参数,可获取到uri字符串,采用截取的方式处理,最后存入attributes
String path = servletRequest.getURI().getPath();
String id = path.substring(path.lastIndexOf('/') + 1);
attributes.put("id", id);
System.out.println("设备id:" + id);
return true;
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
System.out.println("websocket后置拦截");
}
}
四、创建处理器 MyWebSocketHandler
public class MyWebSocketHandler implements WebSocketHandler {
//建立新的 socket 连接后回调的方法
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println("新连接");
//从session中获取存放的参数
session.getAttributes().get("id");
}
// 接收客户端发送的 Socket
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
// 连接发送的消息
String msg = message.getPayload().toString();
// 通过session向连接发送消息
session.sendMessage(new TextMessage("发送消息"));
}
//连接出错时,回调的方法
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
System.out.println("收到的错误信息:" + exception);
}
//连接关闭时,回调的方法
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
System.out.println("断开连接");
}
// WebSocketHandler 是否处理部分消息 默认返回false即可
@Override
public boolean supportsPartialMessages() {
return false;
}
}
五、本地启动项目
六、本地环境测试,或者使用在线测试 http://www.websocket-test.com/
<!DOCTYPE HTML>
<html>
<head>
<title>My WebSocket</title>
</head>
<body>
<input id="text" type="text" />
<button onclick="send()">Send</button>
<button onclick="closeWebSocket()">Close</button>
<div id="message"></div>
</body>
<script type="text/javascript">
let ws = null;
//判断当前浏览器是否支持WebSocket
if ('WebSocket' in window) {
//【非必须】 在ws后面添加了些内容
var str = 'abc';
//【非必须】 Sec-WebSocket-Protocol的内容
var protocol = ['Sec-WebSocket-Protocol的内容']
ws = new WebSocket("ws://127.0.0.1:14000/ws/" + str, protocol);
}
else {
alert('当前浏览器 Not support websocket')
}
//连接发生错误的回调方法
ws.onerror = function () {
setMessageInnerHTML("error");
};
//连接成功建立的回调方法
ws.onopen = function(event) {
setMessageInnerHTML("success");
}
//接收到消息的回调方法
ws.onmessage = function(message) {
if (typeof(message.data) == 'string') {
setMessageInnerHTML(message.data);
}
}
//ws连接断开的回调方法
ws.onclose = function(e) {
setMessageInnerHTML("close");
}
//将消息显示在网页上
function setMessageInnerHTML(innerHTML) {
document.getElementById('message').innerHTML += innerHTML + '<br/>';
}
//关闭连接
function closeWebSocket() {
ws.close();
}
//发送消息
function send(msg) {
if(!msg){
msg = document.getElementById('text').value;
document.getElementById('message').innerHTML += "send:" + msg + '<br/>';
ws.send(msg);
}
}
</script>
</html>
成功连接!
七、生产环境需配置nginx (本配置为wss版,需监听443,ws版监听80端口即可)
server {
listen 443 ssl;
#监听的域名地址
server_name xxxx.com;
ssl_certificate cert/xxxx.com.pem;
ssl_certificate_key cert/xxxx.com.key;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_ciphers ALL:!kEDH!ADH:RC4+RSA:+HIGH:+EXP;
#监听的路径,对应第二步中的连接路径
location /ws/ {
proxy_pass http://127.0.0.1:14000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# 不添加,则会导致后台管理页面无法登录
location / {
#这里是反向代理的地址,我用的是tomcat默认的8080端口
proxy_pass http://localhost:14000/login;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 1;
proxy_send_timeout 200;
proxy_read_timeout 200;
}
}