springcloud⽹关转发websocket
⼩编在做微服务项⽬上遇到⼀个问题,正如标题描述⼀样,但是百度好久未果(太多⽂章都是互相copy的)
⼩编决定⾃⼰写⼀下解决⽅案。。。
下⾯只贴部分代码,如需完整demo请上获取
  1. ⾸先搭建 websocket 的服务端
1.1. 在 websocket 服务端的 pom 配置⽂件中需要有 websocket 的依赖(由于在pom中配置了统⼀版本管理,这⾥就不需要写版本了)
1<dependency>
2<groupId>org.springframework.boot</groupId>
3<artifactId>spring-boot-starter-websocket</artifactId>
4</dependency>
1.2. 略过启动类,配置 websocket ⼯具类;配置的说明,在代码中都有体现
1package fig;
2
3
4import t.annotation.Configuration;
5import org.springframework.fig.annotation.EnableWebSocketMessageBroker;
6import org.springframework.fig.annotation.StompEndpointRegistry;
7import org.springframework.fig.annotation.WebSocketMessageBrokerConfigurer;
8
9 @Configuration
10// 此注解表⽰使⽤STOMP协议来传输基于消息代理的消息,此时可以在@Controller类中使⽤@MessageMapping
11 @EnableWebSocketMessageBroker
12public class WebSocketAutoConfig implements WebSocketMessageBrokerConfigurer {
13    @Override
14public void registerStompEndpoints(StompEndpointRegistry registry) {
15//本实例前端 sockjs 请求路径为 localhost:8888/client/websocket/web/socket
16        registry.addEndpoint("/websocket/web/socket")        //websocket监听地址,sockjs连接地址(如果有配置项⽬路径【t-path】,需要加上)
17                .setAllowedOrigins("*")        //允许跨域访问
18                .withSockJS();                  //使⽤sockJS
19    }
20 }
1.3. 使⽤ websocket 【使⽤⽅式,只写了请求回复和定时推送两种】
1.3.1. 请求回复模式【编写⽅式和普通的 http 的请求回复很像】
1package ller;
2
3import com.alibaba.fastjson.JSONObject;
slf4j.Slf4j;
5import ssaging.handler.annotation.MessageMapping;
6import ssaging.handler.annotation.SendTo;
7import org.springframework.web.bind.annotation.RestController;
8
9 @RestController
10 @Slf4j
11public class FirstController {
12
13/**
14    * 此⽅法⽤于点对点,⼀发⼀答
15    *
16    * @param message
17    * @return
18*/
19    @SendTo("/websocket/read/response/message")//前端订阅消息的地址如果是这个,就会收到该⽅法的返回结果
20//MessageMapping 注解可写在类上,和 RequestMapping 类似
21    @MessageMapping("/websocket1")//前端往这个地址推送数据,类似于 http 的⽅法请求
22public String readMessage(String message) {
23//todo something
24        log.info("message {}", message);
25return JSONObject.parseObject(message).get("message") + " say: hello word.";
26    }
27 }
1.3.
2. 定时推送模式【这⾥需要注⼊ SimpMessagingTemplate 对象进⾏操作】;这⾥引⼊⼀点题外知识【注⼊对象的⽅式】
1package com.beyond.task;
2
slf4j.Slf4j;
4import ssaging.simp.SimpMessagingTemplate;
5import org.springframework.scheduling.annotation.Async;
6import org.springframework.scheduling.annotation.Scheduled;
7import org.springframework.stereotype.Component;
8
9 @Component
10 @Async
11 @Slf4j
12public class WebsocketTask {
13
14
15/*
16 *
17 * ⽅式⼀ Autowired 属性注⼊(不推荐使⽤)
18//    @Autowired
19//    private SimpMessagingTemplate simpMessagingTemplate;
21
22/*
23 *
24 * ⽅式⼆ set注⼊,在属性多的情况下推荐使⽤
25//    private SimpMessagingTemplate simpMessagingTemplate;
26
27//    @Autowired
28//    public void setSimpMessagingTemplate(SimpMessagingTemplate simpMessagingTemplate) {
29//        this.simpMessagingTemplate = simpMessagingTemplate;
30//    }
31*/
32
微服务网关设计
33/**
34    * ⽅式三构造函数注⼊,在属性少的情况下推荐使⽤
35*/
36private final SimpMessagingTemplate simpMessagingTemplate;
37
38public WebsocketTask(SimpMessagingTemplate simpMessagingTemplate) {
39this.simpMessagingTemplate = simpMessagingTemplate;
40    }
41
42
43/**
44    * 此定时任务⽤于往 /websocket/send/response/message 订阅地址定时发送消息;发送消息需要依赖 SimpMessagingTemplate 消息模板
45*/
46    @Scheduled(cron = "*/5 * * * * ?")
47public void roundSendMessage() {
48//todo something
49//向 /websocket/send/response/message 订阅地址发送消息 [hello word!!]
50        vertAndSend("/websocket/send/response/message", "hello word!!");
51    }
52 }
  2. 现在就可以⽤前端代码测试了,这个代码是从百度上 copy 后改写的
1<!DOCTYPE html>
2<html>
3<head>
4<meta charset="UTF-8"/>
5<title>Spring cloud gateway WebSocket</title>
6</head>
7<body>
8<div>
9<div>
10<button id="connect" onclick="connect()">连接</button>
11<button id="disconnect"  onclick="disconnect();">断开连接</button>
12</div>
13<div id="conversationDiv">
14<label>输⼊消息</label><input type="text" id="messgae"/>
15<button id="send" onclick="send();">发送</button>
16<p id="response"></p>
17</div>
18</div>
19<script src="sockjs.min.js"></script>
20<script src="stomp.min.js"></script>
21<script src="jquery.min.js"></script>
22<script type="text/javascript">
23var connectioned = false;
24
25function connect() {
26// websocket的连接地址,此值等于WebSocketMessageBrokerConfigurer中registry.addEndpoint("/websocket/web/socket").withSockJS()配置的地址;如果有项⽬前缀,需要加上
27//var socket = new SockJS('192.168.1.95:19999/server/websocket/web/socket');//⽹关websocket代理地址
28var socket = new SockJS('192.168.1.95:8888/server/websocket/web/socket');//⼦项⽬websocket地址
29                stompClient = Stomp.over(socket);
30                t({}, function(frame) {
31                    connectioned = true;
32                    console.log('Connected: ' + frame);
33// 客户端订阅消息的⽬的地址:此值等于BroadcastCtl中@SendToUser("/topic/getResponse")注解的⾥配置的值。这是请求的地址必须使⽤/user前缀
34                    stompClient.subscribe('/websocket/read/response/message', function(respnose){
35                        console.log("read -------------------");
36                        console.log(respnose.body);
37                    });
38
39                      stompClient.subscribe('/websocket/send/response/message', function(respnose){
40                        console.log("------------------- send");
41                        console.log(respnose.body);
42                    });
43                });
44            }
45
46
47function disconnect() {
48if (stompClient != null) {
49                    stompClient.disconnect();
50                }
51                connectioned = false;
52                console.log("Disconnected");
53            }
54
55function send() {
56if(connectioned){
57var name = $('#messgae').val();
58                    console.log("message --- " +name);
59//客户端消息发送的⽬的:服务端使⽤BroadcastCtl中@MessageMapping("/websocket1")注解的⽅法来处理发送过来的消息;如果类上有配置 @MessageMapping 注解,请求路径需要拼接 [类上/⽅法上]
60                    stompClient.send("/websocket1", {}, JSON.stringify({ 'message': name }));
61                }
62            }
63</script>
64</body>
65</html>
测试结果就不上图了,亲测可⽤
  3. ⽹关配置
  先说明下,这⾥⼩编踩过坑,在这⾥要提醒各位同学,在配置 spring cloud gateway 的时候,必须要⽤ yml 格式的配置⽂件,否则不⽣效。但是不知道为什么,有知道的⼤神可以告诉我!
3.1. ⽹关的pom配置⽂件中需要引⼊ springcloud 的 gateway
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
3.2. 只需要配置路由转发规则即可,其他帖⼦上说要配置其他的,全部都是瞎扯
要使⽤ yml 格式的配置⽂件
properties 和 yml 配置⽂件可以共存【properties 优先级⽐ yml ⾼】
#必须使⽤ yml 格式配置⽂件,转发 socket 才会⽣效
spring:
cloud:
gateway:
#路由转发
routes:
#转发web请求
- id: customize-web
#lb 代表从注册中⼼获取 serverId 来做负载请求
uri: lb://server
predicates:
- Path=/server/websocket/web/socket/info/**
#如果需要加访问前缀,转发是需要去掉;前缀加⼀层,StripPrefix 值+1
#filters:
# - StripPrefix=1
#转发websocket
-
id: customize-websocket
uri: lb:ws://server
predicates:
- Path=/server/websocket/web/socket/**
到这⾥就已经配置完成了,在刚刚那个前端实例⾥⾯,端⼝改成 gateway 的端⼝即可
亲测可⽤
有问题的同学可以留⾔讨论

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。