Spring Boot整合WebSocket 消息点对点发送

Spring Boot整合WebSocket 消息群发

 

添加依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

 

配置Spring Security:

对Spring Security进行配置,添加两个用户,同时配置所有地址都认证后才能访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
 
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("admin")
                .password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq")
                .roles("admin")
                .and()
                .withUser("sang")
                .password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq")
                .roles("user");
    }
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin().permitAll();
    }
}

  

改造WebSocket配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Configuration
@EnableWebSocketMessageBroker // 开启WebSocket消息代理
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
 
    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        /*
         * 表示设置消息代理的前缀,即如果消息的前缀是“/topic”,就会将消息转发给消息代理(broker),再由消息代理将消息广播给当前连接的客户端。
         */
        config.enableSimpleBroker("/topic", "/queue");
        /*
         * 表示配置一个或多个前缀,通过这些前缀过滤出需要被注解方法处理的消息
         * 例如,前缀为“/app”的destination可以通过@MessageMapping注解的方法处理,
         * 而其他destination(例如“/ topic”“/ queue”)将被直接交给broker处理。
         */
        config.setApplicationDestinationPrefixes("/app");
    }
 
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        /*
         * 表示定义一个前缀为“/chat”的endPoint,并开启sockjs支持,
         * sockjs可以解决浏览器对WebSocket的兼容性问题,
         * 客户端将通过这里配置的URL来建立WebSocket连接。
         */
        registry.addEndpoint("/chat").withSockJS();
    }
 
}

这里的修改是在config.enableSimpleBroker("/topic");方法的基础上又增加了一个broker前缀“/queue”,方便对群发消息和点对点消息进行管理。

 

配置Controller:

对WebSocket的Controller进行改造

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Controller
public class GreetingController {
 
    @Autowired
    SimpMessagingTemplate messagingTemplate;
 
    @MessageMapping("/hello") // 用来接收“/app/hello”路径发送来的消息 在注解方法中对消息进行处理后,再将消息转发到@SendTo定义的路径上
    @SendTo("/topic/greetings") // @SendTo路径是一个前缀为“/topic”的路径,因此该消息将被交给消息代理broker,再由broker进行广播。
    public Message greeting(Message message) {
        return message;
    }
 
    /**
     * 点对点的消息发送
     *
     * @param principal 用来获取当前登录用户的信息
     * @param chat      客户端发送来的消息
     */
    @MessageMapping("/chat") // 注解表示来自“/app/chat”路径的消息将被chat方法处理
    public void chat(Principal principal, Chat chat) {
        String from = principal.getName(); // 首先获取当前用户的用户名
        chat.setFrom(from); // 设置给chat对象的from属性
        /*
         * 再将消息发送出去,发送的目标用户就是chat对象的to属性值
         * 消息发送使用的方法是convertAndSendToUser,该方法内部调用了convertAndSend方法,并对消息路径做了处理
         * chat是一个普通的JavaBean,to属性表示消息的目标用户,from表示消息从哪里来,content则是消息的主体内容
         */
        messagingTemplate.convertAndSendToUser(chat.getTo(), "/queue/chat", chat);
    }
 
}

  

创建在线聊天页面:

在resources/static目录下创建onlinechat.html页面作为在线聊天页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>单聊</title>
    <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="/chat.js"></script>
</head>
<body>
<div id="chat">
    <div id="chatsContent">
    </div>
    <div>
        请输入聊天内容:
        <input type="text" id="content" placeholder="聊天内容">
        目标用户:
        <input type="text" id="to" placeholder="目标用户">
        <button id="send" type="button">发送</button>
    </div>
</div>
</body>
</html>

这个页面和chat.html页面基本类似,不同的是,为了演示方便,这里需要用户手动输入目标用户名。另外,还有一个chat.js文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
var stompClient = null;
 
function connect() {
    var socket = new SockJS('/chat');
    stompClient = Stomp.over(socket);
    stompClient.connect({}, function (frame) {
        // 连接成功后,订阅的地址为“/user/queue/chat”,该地址比服务端配置的地址多了“/user”前缀,这是因为SimpMessagingTemplate类中自动添加了路径前缀。
        stompClient.subscribe('/user/queue/chat', function (chat) {
            showGreeting(JSON.parse(chat.body));
        });
    });
}
 
function sendMsg() {
    // 聊天消息发送路径为“/app/chat”
    stompClient.send("/app/chat", {},
        JSON.stringify({
            'content': $("#content").val(),
            'to': $("#to").val() // 发送的消息内容中有一个to字段,该字段用来描述消息的目标用户
        }));
}
 
function showGreeting(message) {
    $("#chatsContent")
        .append("<div>" + message.from + ":" + message.content + "</div>");
}
 
$(function () {
    connect();
    $("#send").click(function () {
        sendMsg();
    });
});

  

测试:

接下来启动Spring Boot项目进行测试,在浏览器中输入http://localhost:8081/onlinechat.html

 

文章来源: Spring Boot+Vue全栈开发实战 - 11.3 Spring Boot整合WebSocket

 

posted @   草木物语  阅读(421)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示