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

1、引用 SpringBoot 搭建 WebSocket 链接

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

2、整合Spring Security

package com.example.demo.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; @Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { /**
* 简单解释一下
* 页面(login、ws)不设置拦截
* 登录页面login
* 登陆成功页面chat
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/","/login","/ws").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/chat")
.permitAll()
.and()
.logout()
.permitAll(); } /**
* 添加两个用户
* 账号:wfy 密码:wfy
* 账号:wisely 密码:wisely
* 角色:USER
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.passwordEncoder(new MyPasswordEncoder())
.withUser("wfy").password("wfy").roles("USER")
.and()
.withUser("wisely").password("wisely").roles("USER");
} /**
* 静态资源路径不设置拦截
* @param web
* @throws Exception
*/
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/static/**");
}
}

3、配置WebSocket

package com.example.demo.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry; @Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { /**
* 配置链接端点
* @param registry
*/
@Override
public void registerStompEndpoints(StompEndpointRegistry registry){
registry.addEndpoint("/endpointWisely").withSockJS();
registry.addEndpoint("/endpointChat").withSockJS();
} /**
* 配置消息代理
* @param registry
*/
@Override
public void configureMessageBroker(MessageBrokerRegistry registry){
registry.enableSimpleBroker("/topic","/queue");
}
}

4、书写控制器

package com.example.demo.controller;

import com.example.demo.PoJo.WiselyMessage;
import com.example.demo.PoJo.WiselyResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller; import java.security.Principal; @Controller
public class WsController { /**
* 服务器 推送数据
*/
@Autowired
private SimpMessagingTemplate messagingTemplate; /**
* MessageMapping 类似于 RequestMapping
* SendTo 订阅地址 类似于 订阅一个URL (我的理解就是 调用了这个方法 在返回的时候会给订阅该url的地址发送数据)
* @param message
* @return
* @throws Exception
*/
@MessageMapping("/welcome")
@SendTo("/topic/getResponse")
public WiselyResponse say(WiselyMessage message) throws Exception {
Thread.sleep(3000);
return new WiselyResponse("Welcome," + message.getName() + "!");
} /**
* 通过convertAndSendToUser 向指定用户发送消息
* @param principal
* @param msg
*/
@MessageMapping("/chat")
public void handleChat(Principal principal,String msg){
if("wfy".equals(principal.getName())){
messagingTemplate.convertAndSendToUser("wisely","queue/notifications",principal.getName() + "-send : "+ msg );
}else{
messagingTemplate.convertAndSendToUser("wfy","queue/notifications",principal.getName() + "-send : "+ msg );
}
} }

5、书写页面(chat)

<!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="wiselyForm">
<textarea rows="4" cols="60" name="text"></textarea>
<input type="submit"/>
</form> <script th:inline="javascript">
$('#wiselyForm').submit(function(e){
e.preventDefault();
var text = $('#wiselyForm').find('textarea[name="text"]').val();
sendSpittle(text);
}); var sock = new SockJS("/endpointChat"); //1
var stomp = Stomp.over(sock);
stomp.connect('guest', 'guest', function(frame) {
stomp.subscribe("/user/queue/notifications", handleNotification);//2
}); function handleNotification(message) {
$('#output').append("<b>Received: " + message.body + "</b><br/>")
} function sendSpittle(text) {
stomp.send("/chat", {}, text);//3
}
$('#stop').click(function() {sock.close()});
</script> <div id="output"></div>
</body>
</html>

页面(login)

<!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>

6、编写视图解析器

package com.example.demo.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter { @Override
public void addViewControllers(ViewControllerRegistry registry){
registry.addViewController("/ws").setViewName("/ws");
registry.addViewController("/login").setViewName("/login");
registry.addViewController("/chat").setViewName("/chat");
}
}

7、记录一个坑

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

解决办法:

package com.example.demo.config;

import org.springframework.security.crypto.password.PasswordEncoder;

public class MyPasswordEncoder implements PasswordEncoder {

    @Override
public String encode(CharSequence charSequence) {
return charSequence.toString();
} @Override
public boolean matches(CharSequence charSequence, String s) {
return s.equals(charSequence.toString());
} }

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. 2017ACM暑期多校联合训练 - Team 7 1002 HDU 6121 Build a tree (深搜+思维)

    题目链接 Problem Description HazelFan wants to build a rooted tree. The tree has n nodes labeled 0 to n− ...

  2. ubuntu下中文输入法的配置,建议用fcitx

    Fcitx [ˈfaɪtɪks] 是一个支持扩展的输入法框架.它有自己维护的三个输入法,拼音,区位和码表:还支持其他引擎,rime 中州韵,google-pinyin,sunpinyin.Fcitx ...

  3. 64_m3

    molequeue-doc-0.8.0-2.20161222giteb397e.fc26.no..> 05-Apr-2017 10:04 451570 molequeue-libs-0.8.0- ...

  4. 《secret》读书笔记

    这是在从大连到深圳飞机上看完的一本书,也是大学毕业时室友整理书籍给我的.正好回来的途中,一气呵成读完了. 全书讲了几个事情,其中费了很大篇幅就围绕一个主题,当然书题了——秘密,这个秘密就是“吸引力法则 ...

  5. POJ - Problem 2282 - The Counting Problem

    整体思路:对于每一位,先将当前未达到$limit$部分的段 [如 $0$ ~ $10000$] 直接处理好,到下一位时再处理达到$limit$的部分. · $1 × 10 ^ n$以内每个数(包括$0 ...

  6. oracle只要第一条数据SQL

    select * from ( select * from COMMON_BIZREL_WF where sponsor is not null order by serialid ) where r ...

  7. Java文件上传与下载

    文件上传与下载可谓上网中的常见现象.apache为我们准备了用于文件上传与下载的两个jar包(commons-fileupload-1.2.1.jar,commons-io-1.4.jar).我们在w ...

  8. Linux中常用命令 <一>

    本笔记中记录的命令来源于 <Linux C 编程实战> ------------------------------------------------------------------ ...

  9. django的orm中F对象的使用

    今天不巧就用上了. 就是将数据库的字段,自增1的场景. from django.db.models import F DeployPool.objects.filter(name=deployvers ...

  10. day4 迭代器与生成器解析

    一.迭代器 迭代器是访问集合元素的一种方式.其实迭代器就是一种列表,只是访问集合元素的时候比较特殊,具有一些特定功能,记忆功能,能够记住用户上一次的状态.迭代器是访问集合元素的一种方式.并且,迭代器只 ...