博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringBoot 实战 (十七) | 整合 WebSocket 实现聊天室
阅读量:6471 次
发布时间:2019-06-23

本文共 5533 字,大约阅读时间需要 18 分钟。

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

前言

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

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

准备工作

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

pom 依赖

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

org.springframework.boot
spring-boot-starter-security
复制代码

Spring Security 的配置

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

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

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的功能@EnableWebSecuritypublic 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" 消息代理。

@Configuration// @EnableWebSocketMessageBroker 注解用于开启使用 STOMP 协议来传输基于代理(MessageBroker)的消息,这时候控制器(controller)// 开始支持@MessageMapping,就像是使用 @requestMapping 一样。@EnableWebSocketMessageBrokerpublic 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

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

@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);    }}复制代码

登录页面

登陆页面
无效的账号和密码
你已注销
复制代码

聊天页面

Home

聊天室

复制代码

页面控制器 controller

@Controllerpublic 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

如果觉得对你有帮助,请给个 Star 再走呗,非常感谢。

后语

如果本文对你哪怕有一丁点帮助,请帮忙点好看。你的好看是我坚持写作的动力。

另外,关注之后在发送 1024 可领取免费学习资料。

资料详情请看这篇旧文:

转载地址:http://oovko.baihongyu.com/

你可能感兴趣的文章
原生Js交互之DSBridge
查看>>
Matlab编程之——卷积神经网络CNN代码解析
查看>>
白洋淀周末游
查看>>
三篇文章了解 TiDB 技术内幕 —— 说计算
查看>>
copy strong weak assign的区别
查看>>
OpenCV 入门
查看>>
css 3D transform变换
查看>>
ele表格合并行之后的selection选中
查看>>
正则表达式分解剖析(一文悟透正则表达式)
查看>>
解决UILable标点符号居中的问题
查看>>
HTML5新特性教程
查看>>
SpringBoot 实战 (十七) | 整合 WebSocket 实现聊天室
查看>>
ImageOptim-无损图片压缩Mac版
查看>>
12 Go语言map底层浅析
查看>>
vue-resumer 项目中 element-ui 遇到的 textarea autosize 问题
查看>>
以主干开发作为持续交付的基础
查看>>
PHP扩展库PEAR被攻击,近半年下载者或被影响
查看>>
传统运维团队转型应该注意哪些问题?
查看>>
JavaScript函数(二)
查看>>
Airbnb改进部署管道安全性,规范部署顺序
查看>>