Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >SpringBoot 实战 (十七) | 整合 WebSocket 实现聊天室

SpringBoot 实战 (十七) | 整合 WebSocket 实现聊天室

作者头像
JavaFish
发布于 2019-10-17 08:44:58
发布于 2019-10-17 08:44:58
1.5K00
代码可运行
举报
运行总次数:0
代码可运行

微信公众号:一个优秀的废人。如有问题,请后台留言,反正我也不会听。

昨天那篇介绍了 WebSocket 实现广播,也即服务器端有消息时,将消息发送给所有连接了当前 endpoint 的浏览器。但这无法解决消息由谁发送,又由谁接收的问题。所以,今天写一篇实现一对一的聊天室。

今天这一篇建立在昨天那一篇的基础之上,为便于更好理解今天这一篇,推荐阅读:

SpringBoot 整合WebSocket 实现广播消息

准备工作

  • Spring Boot 2.1.3 RELEASE
  • Spring Security 2.1.3 RELEASE
  • IDEA
  • JDK8

pom 依赖

因聊天室涉及到用户相关,所以在上一篇基础上引入 Spring Security 2.1.3 RELEASE 依赖

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!-- Spring Security 依赖 -->
<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-security</artifactId>
</dependency>

Spring Security 的配置

虽说涉及到 Spring Security ,但鉴于篇幅有限,这里只对这个项目相关的部分进行介绍,具体的 Spring Security 教程,后面会出。

这里的 Spring Security 配置很简单,具体就是设置登录路径、设置安全资源以及在内存中创建用户和密码,密码需要注意加密,这里使用 BCrypt 加密算法在用户登录时对密码进行加密。 代码注释很详细,不多说。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.nasus.websocket.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
// 开启Spring Security的功能
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
             // 设置 SpringSecurity 对 / 和 "/login" 路径不拦截
            .mvcMatchers("/","/login").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            // 设置 Spring Security 的登录页面访问路径为/login
            .loginPage("/login")
            // 登录成功后转向 /chat 路径
            .defaultSuccessUrl("/chat")
            .permitAll()
            .and()
            .logout()
            .permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            // 在内存中分配两个用户 nasus 和 chenzy ,用户名和密码一致
            // BCryptPasswordEncoder() 是 Spring security 5.0 中新增的加密方式
            // 登陆时用 BCrypt 加密方式对用户密码进行处理。
            .passwordEncoder(new BCryptPasswordEncoder())
            .withUser("nasus")
            // 保证用户登录时使用 bcrypt 对密码进行处理再与内存中的密码比对
            .password(new BCryptPasswordEncoder().encode("nasus")).roles("USER")
            .and()
            // 登陆时用 BCrypt 加密方式对用户密码进行处理。
            .passwordEncoder(new BCryptPasswordEncoder())
            .withUser("chenzy")
            // 保证用户登录时使用 bcrypt 对密码进行处理再与内存中的密码比对
            .password(new BCryptPasswordEncoder().encode("chenzy")).roles("USER");
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        // /resource/static 目录下的静态资源,Spring Security 不拦截
        web.ignoring().antMatchers("/resource/static**");
    }
}

WebSocket 的配置

在上一篇的基础上另外注册一个名为 "/endpointChat" 的节点,以供用户订阅,只有订阅了该节点的用户才能接收到消息;然后,再增加一个名为 "/queue" 消息代理

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Configuration
// @EnableWebSocketMessageBroker 注解用于开启使用 STOMP 协议来传输基于代理(MessageBroker)的消息,这时候控制器(controller)
// 开始支持@MessageMapping,就像是使用 @requestMapping 一样。
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {


    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        //注册一个名为 /endpointNasus 的 Stomp 节点(endpoint),并指定使用 SockJS 协议。
        registry.addEndpoint("/endpointNasus").withSockJS();
        //注册一个名为 /endpointChat 的 Stomp 节点(endpoint),并指定使用 SockJS 协议。
        registry.addEndpoint("/endpointChat").withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        // 广播式配置名为 /nasus 消息代理 , 这个消息代理必须和 controller 中的 @SendTo 配置的地址前缀一样或者全匹配
        // 点对点增加一个 /queue 消息代理
        registry.enableSimpleBroker("/queue","/nasus/getResponse");
    }
}

控制器 controller

指定发送消息的格式以及模板。详情见,代码注释。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Autowired
//使用 SimpMessagingTemplate 向浏览器发送信息
private SimpMessagingTemplate messagingTemplate;

@MessageMapping("/chat")
public void handleChat(Principal principal,String msg){
    // 在 SpringMVC 中,可以直接在参数中获得 principal,principal 中包含当前用户信息
    if (principal.getName().equals("nasus")){
        // 硬编码,如果发送人是 nasus 则接收人是 chenzy 反之也成立。
        // 通过 messageingTemplate.convertAndSendToUser 方法向用户发送信息,参数一是接收消息用户,参数二是浏览器订阅地址,参数三是消息本身
        messagingTemplate.convertAndSendToUser("chenzy",
                "/queue/notifications",principal.getName()+"-send:" + msg);
    } else {
        messagingTemplate.convertAndSendToUser("nasus",
               "/queue/notifications",principal.getName()+"-send:" + msg);
    }
}

登录页面

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<meta charset="UTF-8" />
<head>
    <title>登陆页面</title>
</head>
<body>
<div th:if="${param.error}">
    无效的账号和密码
</div>
<div th:if="${param.logout}">
    你已注销
</div>
<form th:action="@{/login}" method="post">
    <div><label> 账号 : <input type="text" name="username"/> </label></div>
    <div><label> 密码: <input type="password" name="password"/> </label></div>
    <div><input type="submit" value="登陆"/></div>
</form>
</body>
</html>

聊天页面

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!DOCTYPE html>

<html xmlns:th="http://www.thymeleaf.org">
<meta charset="UTF-8" />
<head>
    <title>Home</title>
    <script th:src="@{sockjs.min.js}"></script>
    <script th:src="@{stomp.min.js}"></script>
    <script th:src="@{jquery.js}"></script>
</head>
<body>
<p>
    聊天室
</p>

<form id="nasusForm">
    <textarea rows="4" cols="60" name="text"></textarea>
    <input type="submit"/>
</form>

<script th:inline="javascript">
    $('#nasusForm').submit(function(e){
        e.preventDefault();
        var text = $('#nasusForm').find('textarea[name="text"]').val();
        sendSpittle(text);
    });

    // 连接 SockJs 的 endpoint 名称为 "/endpointChat"
    var sock = new SockJS("/endpointChat");
    var stomp = Stomp.over(sock);
    stomp.connect('guest', 'guest', function(frame) {
        // 订阅 /user/queue/notifications 发送的消息,这里与在控制器的
        // messagingTemplate.convertAndSendToUser 中订阅的地址保持一致
        // 这里多了 /user 前缀,是必须的,使用了 /user 才会把消息发送到指定用户
        stomp.subscribe("/user/queue/notifications", handleNotification);
    });



    function handleNotification(message) {
        $('#output').append("<b>Received: " + message.body + "</b><br/>")
    }

    function sendSpittle(text) {
        stomp.send("/chat", {}, text);
    }
    $('#stop').click(function() {sock.close()});
</script>

<div id="output"></div>
</body>
</html>

页面控制器 controller

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Controller
public class ViewController {

    @GetMapping("/nasus")
    public String getView(){
        return "nasus";
    }

    @GetMapping("/login")
    public String getLoginView(){
        return "login";
    }

    @GetMapping("/chat")
    public String getChatView(){
        return "chat";
    }

}

测试

预期结果应该是:两个用户登录系统,可以互相发送消息。但是同一个浏览器的用户会话的 session 是共享的,这里需要在 Chrome 浏览器再添加一个用户。

具体操作在 Chrome 的 设置-->管理用户-->添加用户:

谷歌浏览器添加用户

两个用户分别访问 http://localhost:8080/login 登录系统,跳转至聊天界面:

聊天界面

相互发送消息:

互发消息

完整代码

https://github.com/turoDog/Demo/tree/master/springboot_websocket_demo

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-03-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 一个优秀的废人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Spring Boot实现带STOMP的WebSocket
WebSocket协议是应用程序处理实时消息的方法之一。最常见的替代方案是长轮询(long polling)和服务器推送事件(server-sent events)。这些解决方案中的每个都有其优缺点。在本文中,我将向您展示如何使用 SpringBoot实现 WebSocket。我将介绍服务器端和客户端设置,使用 WebSocket协议之上的 STOMP进行相互通信。
乱敲代码
2019/06/26
5.7K0
手把手搭建WebSocket多人在线聊天室
https://www.callicoder.com/spring-boot-websocket-chat-example/
Java3y
2019/08/27
4.7K1
手把手搭建WebSocket多人在线聊天室
SpringBoot+WebSocket实现在线聊天(二)
本文是vhr系列第15篇,项目地址:https://github.com/lenve/vhr 在线聊天使用了SpringBoot+WebSocket实现,为了保证用户隐私,所有的聊天数据都保存在系统本地,服务器只进行了数据转发。OK,那接下来,我们来看下大致的实现步骤。 服务端 服务端首先加入websocket依赖,如下: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-st
江南一点雨
2018/04/02
2.3K0
SpringBoot 实战 (十六) | 整合 WebSocket 基于 STOMP 协议实现广播消息
如题,今天介绍的是 SpringBoot 整合 WebSocket 实现广播消息。
JavaFish
2019/10/17
3.6K0
SpringBoot 实战 (十六) | 整合 WebSocket 基于 STOMP 协议实现广播消息
Spring消息之STOMP
一、STOMP 简介     直接使用WebSocket(或SockJS)就很类似于使用TCP套接字来编写Web应用。因为没有高层级的线路协议(wire protocol),因此就需要我们定义应用之间所发送消息的语义,还需要确保连接的两端都能遵循这些语义。     就像HTTP在TCP套接字之上添加了请求-响应模型层一样,STOMP在WebSocket之上提供了一个基于帧的线路格式(frame-based wire format)层,用来定义消息的语义。     与HTTP请求和响应类似,STOMP帧由命令
JMCui
2018/06/14
3.4K0
使用消息队列轻松实现 分布式 webSocket
简单的概括一下:如果我们的项目是分布式环境,登录的用户被Nginx的反向代理分配到多个不同服务器,那么在其中一个服务器建立了WebSocket连接的用户如何给在另外一个服务器上建立了WebSocket连接的用户发送消息呢?
码猿技术专栏
2023/09/07
6300
使用消息队列轻松实现 分布式 webSocket
使用消息队列实现 分布式 webSocket
陈某的《Spring Cloud Alibaba实战项目》 视频教程已经录完了,涉及到Alibaba的各种中间件、OAuth2微服务认证鉴权、全链路灰度发布、分布式事务实战,戳这里--->Spring Cloud Alibaba 实战 视频专栏 开放订阅~
码猿技术专栏
2023/05/01
1.4K0
使用消息队列实现 分布式 webSocket
Springboot整合Websocket实现一对一消息推送和广播消息推送
同时因为控制器有注解@SendTo所以会向@SendTo的地址广播消息,客户端订阅了广播地址所有控制台显示接收了消息
业余草
2020/06/23
2.1K0
Springboot整合Websocket实现一对一消息推送和广播消息推送
【多人聊天室】WebSocket集群/分布式改造
https://github.com/qqxx6661/springboot-websocket-demo/releases/tag/%E9%9B%86%E7%BE%A4%E7%89%88
Java3y
2019/08/27
3.5K0
【多人聊天室】WebSocket集群/分布式改造
spring boot集成WebSocket实时输出日志到web页面
前言碎语 今天来做个有趣的东西,就是实时将系统日志输出的前端web页面,因为是实时输出,所有第一时间就想到了使用webSocket,而且在spring boot中,使用websocket超级方便,阅读本文,你会接触到以下关键词相关技术,WebSocket(stopmp服务端),stomp协议,sockjs.min.js,stomp.min.js(stomp客户端),本文使用到的其实就是使用spring boot自带的webSocket模块提供stomp的服务端,前端使用stomp.min.js做stomp的客户端,使用sockjs来链接,前端订阅后端日志端点的消息,后端实时推送,达到日志实时输出到web页面的目的,效果如下图
kl博主
2018/04/13
3.7K0
spring boot集成WebSocket实时输出日志到web页面
spring boot集成WebSocket实时输出日志到web页面
前言碎语 今天来做个有趣的东西,就是实时将系统日志输出的前端web页面,因为是实时输出,所有第一时间就想到了使用webSocket,而且在spring boot中,使用websocket超级方便,阅读本文,你会接触到以下关键词相关技术,WebSocket(stopmp服务端),stomp协议,sockjs.min.js,stomp.min.js(stomp客户端),本文使用到的其实就是使用spring boot自带的webSocket模块提供stomp的服务端,前端使用stomp.min.js做stomp的客户端,使用sockjs来链接,前端订阅后端日志端点的消息,后端实时推送,达到日志实时输出到web页面的目的,效果如下图
kl博主
2023/11/18
1.2K0
spring boot集成WebSocket实时输出日志到web页面
重学SpringBoot3-集成Spring Security(一)
Spring Security 是一个强大、灵活的安全框架,广泛用于保护 Java 应用程序。随着 Spring Boot 3 和 Java 17 的引入,Spring Security 继续增强其功能,为开发者提供了更简化的配置和现代化的安全实践。
CoderJia
2024/10/18
1.2K0
重学SpringBoot3-集成Spring Security(一)
[WebSocket入门]手把手搭建WebSocket多人在线聊天室(SpringBoot+WebSocket)
https://www.callicoder.com/spring-boot-websocket-chat-example/
Rude3Knife的公众号
2019/08/16
2.8K0
[WebSocket入门]手把手搭建WebSocket多人在线聊天室(SpringBoot+WebSocket)
springboot整合websocket实现消息推送
maven依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" x
似水的流年
2018/06/20
2.5K1
springboot整合websocket技术
简单来说就是一个基于TCP的持久化的网络通信协议。主要作用就是:服务端可以主动推送信息给客户端,不需要客户端重复的向服务端发请求查询。
海加尔金鹰
2020/06/09
1.1K0
Spring Boot使用websocket实现聊天室
先看效果:这里面demo用的是原生js跟html,方便打包一体化,在效果上我更倾向于使用vue、react等进行页面开发
余生大大
2022/11/02
9020
Spring Boot使用websocket实现聊天室
再谈 websocket 论架构设计
如我们所了解,http连接为一次请求一次响应(request->response),必须为同步调用方式。 而websocket为一次连接以后,会建立tcp连接,后续客户端与服务器交互为全双工方式的交互方式,客户端可以发送消息到服务端,服务端也可将消息发送给客户端。
凯哥Java
2019/06/28
2.2K0
再谈 websocket 论架构设计
Spring和WebSocket整合详解(建立Web聊天室)
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
品茗IT
2019/09/12
5.1K0
SpringBoot轻松整合WebSocket实现Web在线聊天室
前面为大家讲述了 Spring Boot的整合Redis、RabbitMQ、Elasticsearch等各种框架组件;随着移动互联网的发展,服务端消息数据推送已经是一个非常重要、非常普遍的基础功能。今天就和大家聊聊在SpringBoot轻松整合WebSocket,实现Web在线聊天室,希望能对大家有所帮助。
架构师精进
2023/10/06
3.1K0
SpringBoot轻松整合WebSocket实现Web在线聊天室
[WebSocket]第二章:WebSocket集群分布式改造——实现多人在线聊天室
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
蛮三刀酱
2019/09/10
3K0
推荐阅读
相关推荐
Spring Boot实现带STOMP的WebSocket
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验