springboot+websockt实现简易单聊,群发消息
实现效果:
1.导入maven依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.tangshuai</groupId>
<artifactId>springboot_websocket</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--websocket-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
</project>
2.新增用户类
package com.tangshuai.entity;
/**
* @author TANGSHUAI
* @version 1.0
* @date 2022-03-15 9:10
*/
public class User{
String id;
String username;
String password;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
3.创建基础数据
package com.tangshuai.entity;
import java.util.ArrayList;
import java.util.List;
/**
* @author TANGSHUAI
* @version 1.0
* @date 2022-03-15 9:18
*/
public class UserList {
public static List<User> getUser(){
List<User> list=new ArrayList<>();
User user=new User();
user.setId("1");
user.setUsername("admin");
user.setPassword("123456");
list.add(user);
User user2=new User();
user2.setId("2");
user2.setUsername("zhangsan");
user2.setPassword("123456");
list.add(user2);
User user3=new User();
user3.setId("3");
user3.setUsername("lisi");
user3.setPassword("123456");
list.add(user3);
return list;
}
}
4.配置websocket
package com.tangshuai.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
@EnableAsync
@Configuration
//表示开启使用STOMP协议来传输基于代理的消息
@EnableWebSocketMessageBroker
public class WsConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
// 注册一个端点,websocket的访问地址
registry.addEndpoint("/websocket").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
//推送消息前缀
registry.enableSimpleBroker("/user/", "/topic/");
registry.setApplicationDestinationPrefixes("/app");
}
}
5.创建配置类,保存所有的session
package com.tangshuai.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author TANGSHUAI
* @version 1.0
* @date 2022-03-15 11:12
* 用于保存所有创建的session
*/
@Configuration
public class HttpSessionConfig {
private static final Map<String, HttpSession> sessions = new HashMap<>();
public List<HttpSession> getActiveSessions() {
return new ArrayList<>(sessions.values());
}
@Bean
public HttpSessionListener httpSessionListener() {
return new HttpSessionListener() {
@Override
public void sessionCreated(HttpSessionEvent hse) {
sessions.put(hse.getSession().getId(), hse.getSession());
}
@Override
public void sessionDestroyed(HttpSessionEvent hse) {
sessions.remove(hse.getSession().getId());
}
};
}
}
6.创建service
package com.tangshuai.service;
/**
* @author TANGSHUAI
* @version 1.0
* @date 2022-03-14 19:41
*/
public interface WsService {
void sendToUser(String toUserId,String concent);
}
package com.tangshuai.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
/**
* @author TANGSHUAI
* @version 1.0
* @date 2022-03-14 19:41
*/
@Service
public class WsServiceImpl implements WsService{
@Autowired
SimpMessagingTemplate messagingTemplate;
/**
* 发送消息给用户
* @param toUserId
*/
@Async
@Override
public void sendToUser(String toUserId,String concent) {
// websocket通知 (/user/20/messCount)
messagingTemplate.convertAndSendToUser(toUserId, "/messCount", concent);
}
}
7.创建登陆Controller
package com.tangshuai.controller;
import com.tangshuai.entity.User;
import com.tangshuai.entity.UserList;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpSession;
import java.util.List;
/**
* @author TANGSHUAI
* @version 1.0
* @date 2022-03-15 9:22
*/
@Controller
public class LogoinController {
@GetMapping("")
public String login (){
return "login.html";
}
@RequestMapping("/loginCheck")
public String loginCheck(String username, String password, HttpSession session, Model model){
System.out.println("登陆用户名:"+username);
List<User> user = UserList.getUser();
for (User u : user) {
if(u.getUsername().equals(username) && u.getPassword().equals(password)){
session.setAttribute("user", u);
model.addAttribute("user", u);
System.out.println("=======================>【"+u.getUsername()+"】登陆成功!");
return "index.html";
}else{
System.out.println("=======================>用户名或密码错误!");
}
}
return "login.html";
}
}
8.创建发送消息Controller
package com.tangshuai.controller;
import com.tangshuai.config.HttpSessionConfig;
import com.tangshuai.entity.User;
import com.tangshuai.service.WsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpSession;
import java.util.List;
/**
* @author TANGSHUAI
* @version 1.0
* @date 2022-03-14 18:05
*/
@Controller
public class WebSocketController {
@Autowired
WsService wsService;
@Autowired
HttpSessionConfig httpSessionConfig;
/**
*给用户ID为1的发送消息
*/
@ResponseBody
@GetMapping("/reply")
public void reply() {
wsService.sendToUser("1","您好,用户【1】");
}
/**
*给用户为2的发送消息
*/
@ResponseBody
@GetMapping("/reply2")
public void reply2() {
wsService.sendToUser("2","您好,用户【2】");
}
/**
* 群发
*/
@ResponseBody
@GetMapping("/broadcast")
public void broadcast(HttpSession session){
List<HttpSession> activeSessions = httpSessionConfig.getActiveSessions();
System.out.println(activeSessions.size());
for (HttpSession httpSession : activeSessions) {
User u = (User) httpSession.getAttribute("user");
wsService.sendToUser(u.getId(),"所有用户您们好!");
}
}
/**
* 模拟发送消息控制台
* @return
*/
@GetMapping("/home")
public String home(){
return "home.html";
}
}
9.创建登陆html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户登陆</title>
</head>
<body>
<h3>欢迎来的简易聊天系统</h3>
<form action="loginCheck">
用户名:<input name="username" type="text"/><br/>
密码:<input name="password" type="text"/><br/>
<input type="submit" value="登陆">
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>聊天信息</title>
<script th:src="@{/js/sockjs.js}"></script>
<script th:src="@{/js/stomp.js}"></script>
<script th:src="@{/js/jquery.min.js}"></script>
</head>
<h3>聊天系统</h3>
<input type="text" id="userId" hidden th:value="${user.id}">
<h5>欢迎您:<span th:text="${user.username}"></span></h5>
<br>
<a th:href="@{/home}" target="_blank">模拟发送消息控制台</a>
<hr/>
<div id="message">
</div>
<script>
$(function () {
var userId=$("#userId").val();
var socket = new SockJS("/websocket")
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
stompClient.subscribe("/user/" + userId +"/messCount", function (res) {
console.log("==================>");
console.log(res.body);
console.log("==================>");
$("#message").append("<br/>");
$("#message").append(res.body);
})
});
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>控制台</title>
</head>
<body>
<a th:href="@{/reply}">发送消息给admin</a><br>
<a th:href="@{/reply2}">发送消息给zhangsan</a><br>
<a th:href="@{/broadcast}">群发消息</a><br>
</body>
</html>
JS文件