SpringBoot 搭建简单聊天室(queue 点对点)

1、引用 SpringBoot 搭建 WebSocket 链接

  https://www.cnblogs.com/yi1036943655/p/10089100.html

2、整合Spring Security

  1. package com.example.demo.config;
  2.  
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
  5. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  6. import org.springframework.security.config.annotation.web.builders.WebSecurity;
  7. import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  8. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  9.  
  10. @Configuration
  11. @EnableWebSecurity
  12. public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  13.  
  14. /**
  15. * 简单解释一下
  16. * 页面(login、ws)不设置拦截
  17. * 登录页面login
  18. * 登陆成功页面chat
  19. * @param http
  20. * @throws Exception
  21. */
  22. @Override
  23. protected void configure(HttpSecurity http) throws Exception {
  24. http
  25. .authorizeRequests()
  26. .antMatchers("/","/login","/ws").permitAll()
  27. .anyRequest().authenticated()
  28. .and()
  29. .formLogin()
  30. .loginPage("/login")
  31. .defaultSuccessUrl("/chat")
  32. .permitAll()
  33. .and()
  34. .logout()
  35. .permitAll();
  36.  
  37. }
  38.  
  39. /**
  40. * 添加两个用户
  41. * 账号:wfy 密码:wfy
  42. * 账号:wisely 密码:wisely
  43. * 角色:USER
  44. * @param auth
  45. * @throws Exception
  46. */
  47. @Override
  48. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  49. auth
  50. .inMemoryAuthentication()
  51. .passwordEncoder(new MyPasswordEncoder())
  52. .withUser("wfy").password("wfy").roles("USER")
  53. .and()
  54. .withUser("wisely").password("wisely").roles("USER");
  55. }
  56.  
  57. /**
  58. * 静态资源路径不设置拦截
  59. * @param web
  60. * @throws Exception
  61. */
  62. @Override
  63. public void configure(WebSecurity web) throws Exception {
  64. web.ignoring().antMatchers("/resources/static/**");
  65. }
  66. }

3、配置WebSocket

  1. package com.example.demo.config;
  2.  
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.messaging.simp.config.MessageBrokerRegistry;
  5. import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
  6. import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
  7. import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
  8.  
  9. @Configuration
  10. @EnableWebSocketMessageBroker
  11. public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
  12.  
  13. /**
  14. * 配置链接端点
  15. * @param registry
  16. */
  17. @Override
  18. public void registerStompEndpoints(StompEndpointRegistry registry){
  19. registry.addEndpoint("/endpointWisely").withSockJS();
  20. registry.addEndpoint("/endpointChat").withSockJS();
  21. }
  22.  
  23. /**
  24. * 配置消息代理
  25. * @param registry
  26. */
  27. @Override
  28. public void configureMessageBroker(MessageBrokerRegistry registry){
  29. registry.enableSimpleBroker("/topic","/queue");
  30. }
  31. }

4、书写控制器

  1. package com.example.demo.controller;
  2.  
  3. import com.example.demo.PoJo.WiselyMessage;
  4. import com.example.demo.PoJo.WiselyResponse;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.messaging.handler.annotation.MessageMapping;
  7. import org.springframework.messaging.handler.annotation.SendTo;
  8. import org.springframework.messaging.simp.SimpMessagingTemplate;
  9. import org.springframework.stereotype.Controller;
  10.  
  11. import java.security.Principal;
  12.  
  13. @Controller
  14. public class WsController {
  15.  
  16. /**
  17. * 服务器 推送数据
  18. */
  19. @Autowired
  20. private SimpMessagingTemplate messagingTemplate;
  21.  
  22. /**
  23. * MessageMapping 类似于 RequestMapping
  24. * SendTo 订阅地址 类似于 订阅一个URL (我的理解就是 调用了这个方法 在返回的时候会给订阅该url的地址发送数据)
  25. * @param message
  26. * @return
  27. * @throws Exception
  28. */
  29. @MessageMapping("/welcome")
  30. @SendTo("/topic/getResponse")
  31. public WiselyResponse say(WiselyMessage message) throws Exception {
  32. Thread.sleep(3000);
  33. return new WiselyResponse("Welcome," + message.getName() + "!");
  34. }
  35.  
  36. /**
  37. * 通过convertAndSendToUser 向指定用户发送消息
  38. * @param principal
  39. * @param msg
  40. */
  41. @MessageMapping("/chat")
  42. public void handleChat(Principal principal,String msg){
  43. if("wfy".equals(principal.getName())){
  44. messagingTemplate.convertAndSendToUser("wisely","queue/notifications",principal.getName() + "-send : "+ msg );
  45. }else{
  46. messagingTemplate.convertAndSendToUser("wfy","queue/notifications",principal.getName() + "-send : "+ msg );
  47. }
  48. }
  49.  
  50. }

5、书写页面(chat)

  1. <!DOCTYPE html>
  2.  
  3. <html xmlns:th="http://www.thymeleaf.org">
  4. <meta charset="UTF-8" />
  5. <head>
  6. <title>Home</title>
  7. <script th:src="@{sockjs.min.js}"></script>
  8. <script th:src="@{stomp.min.js}"></script>
  9. <script th:src="@{jquery.js}"></script>
  10. </head>
  11. <body>
  12. <p>
  13. 聊天室
  14. </p>
  15.  
  16. <form id="wiselyForm">
  17. <textarea rows="4" cols="60" name="text"></textarea>
  18. <input type="submit"/>
  19. </form>
  20.  
  21. <script th:inline="javascript">
  22. $('#wiselyForm').submit(function(e){
  23. e.preventDefault();
  24. var text = $('#wiselyForm').find('textarea[name="text"]').val();
  25. sendSpittle(text);
  26. });
  27.  
  28. var sock = new SockJS("/endpointChat"); //1
  29. var stomp = Stomp.over(sock);
  30. stomp.connect('guest', 'guest', function(frame) {
  31. stomp.subscribe("/user/queue/notifications", handleNotification);//2
  32. });
  33.  
  34. function handleNotification(message) {
  35. $('#output').append("<b>Received: " + message.body + "</b><br/>")
  36. }
  37.  
  38. function sendSpittle(text) {
  39. stomp.send("/chat", {}, text);//3
  40. }
  41. $('#stop').click(function() {sock.close()});
  42. </script>
  43.  
  44. <div id="output"></div>
  45. </body>
  46. </html>

页面(login)

  1. <!DOCTYPE html>
  2. <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
  3. xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
  4. <meta charset="UTF-8" />
  5. <head>
  6. <title>登陆页面</title>
  7. </head>
  8. <body>
  9. <div th:if="${param.error}">
  10. 无效的账号和密码
  11. </div>
  12. <div th:if="${param.logout}">
  13. 你已注销
  14. </div>
  15. <form th:action="@{/login}" method="post">
  16. <div><label> 账号 : <input type="text" name="username"/> </label></div>
  17. <div><label> 密码: <input type="password" name="password"/> </label></div>
  18. <div><input type="submit" value="登陆"/></div>
  19. </form>
  20. </body>
  21. </html>

6、编写视图解析器

  1. package com.example.demo.config;
  2.  
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
  5. import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
  6.  
  7. @Configuration
  8. public class WebMvcConfig extends WebMvcConfigurerAdapter {
  9.  
  10. @Override
  11. public void addViewControllers(ViewControllerRegistry registry){
  12. registry.addViewController("/ws").setViewName("/ws");
  13. registry.addViewController("/login").setViewName("/login");
  14. registry.addViewController("/chat").setViewName("/chat");
  15. }
  16. }

7、记录一个坑

  1)、如果使用的是 Security5.0 以上会报错 java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

解决办法:

  1. package com.example.demo.config;
  2.  
  3. import org.springframework.security.crypto.password.PasswordEncoder;
  4.  
  5. public class MyPasswordEncoder implements PasswordEncoder {
  6.  
  7. @Override
  8. public String encode(CharSequence charSequence) {
  9. return charSequence.toString();
  10. }
  11.  
  12. @Override
  13. public boolean matches(CharSequence charSequence, String s) {
  14. return s.equals(charSequence.toString());
  15. }
  16.  
  17. }

SpringBoot 搭建简单聊天室的更多相关文章

  1. Jaguar_websocket结合Flutter搭建简单聊天室

    1.定义消息 在开始建立webSocket之前,我们需要定义消息,如:发送人,发送时间,发送人id等.. import 'dart:convert'; class ChatMessageData { ...

  2. 基于springboot的websocket聊天室

    WebSocket入门 1.概述 1.1 Http #http简介 HTTP是一个应用层协议,无状态的,端口号为80.主要的版本有1.0/1.1/2.0. #http1.0/1.1/2.0 1.HTT ...

  3. ASP.NET SingalR + MongoDB 实现简单聊天室(一):搭建基本框架

    ASP.NET SingalR不多介绍.让我介绍不如看官网,我这里就是直接上源代码,当然代码还是写的比较简单的,考虑的也少,希望各位技友多多提意见. 先简单介绍聊天室功能: 用户加入聊天室,自动给用户 ...

  4. Python Socket 简单聊天室2

    上篇文章写了一个简单的单线程的一问一答的简单聊天室.这次我们使用SocketServer模块搭建一个多线程异步的聊天室. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...

  5. 基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍。最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室。

    基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍.最后我们将会实现一个基于S ...

  6. SilverLight搭建WCF聊天室详细过程[转]

    http://www.silverlightchina.net/html/zhuantixilie/getstart/2011/0424/7148.html 默认节点 SilverLight搭建WCF ...

  7. Asp.Net SignalR - 简单聊天室实现

    简单聊天室 使用持久链接类我们就可以做一些即时通讯的应用了,我使用Group做了一个简单的聊天室,先上图技术细节下面再讲 可以加入聊天室.创建聊天室.发送消息,下面就说说我是如何通过Group做出来的 ...

  8. 利用socket.io+nodejs打造简单聊天室

    代码地址如下:http://www.demodashi.com/demo/11579.html 界面展示: 首先展示demo的结果界面,只是简单消息的发送和接收,包括发送文字和发送图片. ws说明: ...

  9. C#实例之简单聊天室(状态管理)

    前言        状态管理是在同一页或不同页的多个请求发生时,维护状态和页信息的过程.因为Web应用程序的通信协议使用了无状态的HTTP协议,所以当客户端请求页面时,ASP.NET服务器端都会重新生 ...

随机推荐

  1. Xcode 获取本地IP

    // // // #define MAXADDRS 32 extern char *ip_names[MAXADDRS]; void InitAddresses(); void GetIPAddres ...

  2. 回溯算法_01背包问题_Java实现

    原文地址:http://blog.csdn.net/ljmingcom304/article/details/50314839 本文出自:[梁敬明的博客] 1.回溯算法 回溯算法也叫试探法,通俗的将就 ...

  3. mysql 提权总结

    1.MOF提权 简单的说mof就是系统内部的一个程序,每隔一定时间系统就会以root权限去执行,我们将其替换然后执行我们的而已攻击代码.此举称之为mof提权. 以下便是脚本: #pragma name ...

  4. S3C6410 SPI全双工读写流程分析(原创)【转】

    转自:http://blog.csdn.net/hustyangju/article/details/21165721 原创博文,知识共享!转载请注明出处:http://blog.csdn.net/h ...

  5. C# Selenium with PhantomJSDriver get image width and height (获取图片的长和高)

    //get image width and height var image=driver.FindElement(By.ClassName("it-Header_authorImage&q ...

  6. HDU 6195 2017沈阳网络赛 公式

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6195 题意:有M个格子,有K个物品.我们希望在格子与物品之间连数量尽可能少的边,使得——不论是选出M个 ...

  7. 用js实现登录的简单验证

    实现过程示意图 代码 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> &l ...

  8. BeanUtils简化数据封装

    BeanUtils主要用来封装JavaBean的. 1.什么是JavaBean JavaBean指的是标准的类. 要求: 1. 类必须被public修饰2. 必须提供空参的构造器3. 成员变量必须使用 ...

  9. beego学习笔记(4):开发文档阅读(1)

    1.beego的设计是高度模块化的.每个模块,都可以单独使用.一共八大模块: cache;session;log;orm;context;httplibs;toolbox 2.beego的执行逻辑 3 ...

  10. hive的窗口函数cume_dist、fercent_rank

    一.cume_dist 这两个序列分析函数不是很常用,这里也介绍一下.注意: 序列函数不支持WINDOW子句. 数据准备: d1,user1, d1,user2, d1,user3, d2,user4 ...