springboot websocket通信

简介: springboot websocket通信



一、websocket是什么

WebSocket_ohana!的博客-CSDN博客

二、实现websocket

2.1参考学习b站资料(一定要看,前后端详细)

01-websocket协议及实现_哔哩哔哩_bilibili

2.2学习配套代码

1.导入pom依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

2.编写配置类

//配置类
@Configuration
public class WebSocketConfig {
    @Bean
    //注入ServerEndpointExporter bean对象,自动注册使用注解@ServerEndpoint的bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}

3.所需要的pojo类:

4.需要的工具类,用于转化信息格式

import com.example.ex1.mes_websocket.pojo.ResultMessage;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class MessageUtils {
    public static String getMessage(boolean isSystemMessage,String fromName,Object message){
        try {
            ResultMessage result = new ResultMessage();
            result.setSystem(isSystemMessage);
            result.setMessage(message);
            if (fromName!=null){
                result.setFromName(fromName);
            }
            //把字符串转成json格式的字符串
            ObjectMapper mapper = new ObjectMapper();
            return mapper.writeValueAsString(result);
        }catch (JsonProcessingException e){
            e.printStackTrace();
        }
        return null;
    }
}

5.登录的验证以及获取用户名的controller

import com.example.ex1.mes_websocket.pojo.Result;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpSession;
@RestController
public class LoginController {
    @RequestMapping("/toLogin")
    public Result tologin(@RequestParam("user") String user,@RequestParam("pwd") String pwd, HttpSession session){
        Result result = new Result();
        if (user.equals("张三")&&pwd.equals("123")){
            result.setFlag(true);
            session.setAttribute("user",user);
        }else if (user.equals("李四")&&pwd.equals("123")){
            result.setFlag(true);
            session.setAttribute("user",user);
        }else if (user.equals("123")&&pwd.equals("123")){
            result.setFlag(true);
            session.setAttribute("user",user);
        }
        else if (user.equals("王五")&&pwd.equals("123")){
            result.setFlag(true);
            session.setAttribute("user",user);
        }else {
            result.setFlag(false);
            result.setMessage("登录失败");
        }
        return result;
    }
    @RequestMapping("/getUsername")
    public String getUsername(HttpSession session){
        String username = (String) session.getAttribute("user");
        return username;
    }
}

6.登录页面(前端页面用到jquery)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script src="js/jquery.min.js"></script>
<form id="loginForm">
    <label>账号:</label>
    <input type="text" name="user">
    <label>密码:</label>
    <input type="password" name="pwd">
    <button type="button" id="btn">登录</button>
</form>
<p id="err_msg"></p>
<script>
    $("#btn").click(function () {
        $.get("toLogin?",$("#loginForm").serialize(),function(res){
            if (res.flag){
                console.log(res);
                location.href = "main.html";
            } else {
                console.log(res);
                $("#err_msg").html(res.message);
            }
        },"json");
    })
</script>
</body>
</html>

7.主页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<style>
    #left{
        float: left;
        width: 30%;
        height: 500px;
        margin-left: 200px;
    }
    #right{
        float: right;
        width: 30%;
        height: 500px;
    }
    #top{
        margin-top: 50px;
        float: top;
        width: 30%;
        height: 250px;
    }
    #content{
        border: aquamarine 1px solid;
        width: 100%;
        height: 300px;
    }
    #input{
        margin-top: 20px;
        width: 100%;
        height: 200px;
    }
    #input input{
        width: 100%;
        height: 100px;
    }
    #input button{
        float: right;
    }
    #mes_left{
        float: left;
    }
    #mes_right{
        float: right;
        width: 50%;
        text-align: right;
    }
</style>
<body>
<script src="js/jquery.min.js"></script>
<h3 style="text-align: center" id="username"></h3>
<div>
    <div id="left">
        <h4 id="new"></h4>
        <div id="content">
        </div>
        <div id="input">
            <input type="text" id="input_text">
            <button id="submit">发送</button>
        </div>
    </div>
    <div id="right">
        <div id="top">
            <p>在线的好友</p>
            <div id="hylist">
            </div>
        </div>
        <div id="bottom">
            <p>系统广播</p>
            <div id="xtlist">
            </div>
        </div>
    </div>
</div>
<script>
    var username;
    $(function () {
        var toName;
        $.ajax({
            url:"getUsername",
            success:function (res) {
                username = res;
                $("#username").html("用户:"+ username +"<span>在线</span>");
                // $("#username").html("用户:123<span>在线</span>");
            },
            async:false //同步请求,只有上面好了才会接着下面
        });
        var ws = new WebSocket("ws://localhost:8080/chat");
        ws.onopen = function (ev) {
            $("#username").html("用户:"+ username +"<span>在线</span>");
        }
        //接受消息
        ws.onmessage = function (ev) {
            var datastr = ev.data;
            var res = JSON.parse(datastr);
            //判断是否是系统消息
            if(res.system){
                //好友列表
                //系统广播
                var names = res.message;
                var userlistStr = "";
                var broadcastListStr = "";
                for (var name of names){
                    if (name != username){
                        userlistStr += "<a οnclick='showChat(\""+name+"\")'>"+ name +"</a></br>";
                        broadcastListStr += "<p>"+ name +"上线了</p>";
                    }
                };
                $("#hylist").html(userlistStr);
                $("#xtlist").html(broadcastListStr);
            }else {
                //不是系统消息
                var str = "<span id='mes_left'>"+ res.message +"</span></br>";
                if (toName == res.fromName) 
                $("#content").append(str);
                var chatdata = sessionStorage.getItem(res.fromName);
                if (chatdata != null){
                    str = chatdata + str;
                }
                sessionStorage.setItem(res.fromName,str);
            };
        },
        ws.onclose = function (ev) {
            $("#username").html("用户:"+ username +"<span>离线</span>");
        }
        showChat = function(name){
            // alert("dsaad");
            toName = name;
            //清空聊天区
            $("#content").html("");
            $("#new").html("当前正与"+toName+"聊天");
            var chatdata = sessionStorage.getItem(toName);
            if (chatdata != null){
                $("#content").html(chatdata);
            }
        };
        //发送消息
        $("#submit").click(function () {
            //获取输入的内容
            var data = $("#input_text").val();
            $("#input_text").val("");
            var json = {"toName": toName ,"message": data};
            //将数据展示在聊天区
            var str = "<span id='mes_right'>"+ data +"</span></br>";
            $("#content").append(str);
            var chatdata = sessionStorage.getItem(toName);
            if (chatdata != null){
                str = chatdata + str;
            }
            sessionStorage.setItem(toName,str);
            //发送数据
            ws.send(JSON.stringify(json));
        })
    })
</script>
</body>
</html>

8.获取HttpSession对象的类

import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
public class GetHttpSessionConfigurator extends ServerEndpointConfig.Configurator {
    @Override
    public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
        //获取HttpSession对象
        HttpSession httpSession = (HttpSession) request.getHttpSession();
        sec.getUserProperties().put(HttpSession.class.getName(),httpSession);
    }
}

9.最后的通信类

import com.example.ex1.mes_websocket.pojo.Message;
import com.example.ex1.mes_websocket.utils.MessageUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@ServerEndpoint(value = "/chat",configurator = GetHttpSessionConfigurator.class)
@Component
public class ChatEndpoint {
    //用来存储每个用户客户端对象的ChatEndpoint对象
    private static Map<String,ChatEndpoint> onlineUsers = new ConcurrentHashMap<>();
    //声明session对象,通过对象可以发送消息给指定的用户
    private Session session;
    //声明HttpSession对象,我们之前在HttpSession对象中存储了用户名
    private HttpSession httpSession;
    //连接建立
    @OnOpen
    public void onOpen(Session session, EndpointConfig config){
        this.session = session;
        HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
        this.httpSession = httpSession;
        //存储登陆的对象
        String username = (String)httpSession.getAttribute("user");
        onlineUsers.put(username,this);
        //将当前在线用户的用户名推送给所有的客户端
        //1 获取消息
        String message = MessageUtils.getMessage(true, null, getNames());
        //2 调用方法进行系统消息的推送
        broadcastAllUsers(message);
    }
    private void broadcastAllUsers(String message){
        try {
            //将消息推送给所有的客户端
            Set<String> names = onlineUsers.keySet();
            for (String name : names) {
                ChatEndpoint chatEndpoint = onlineUsers.get(name);
                chatEndpoint.session.getBasicRemote().sendText(message);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    //返回在线用户名
    private Set<String> getNames(){
        return onlineUsers.keySet();
    }
    //收到消息
    @OnMessage
    public void onMessage(String message,Session session){
        //将数据转换成对象
        try {
            ObjectMapper mapper =new ObjectMapper();
            Message mess = mapper.readValue(message, Message.class);
            String toName = mess.getToName();
            String data = mess.getMessage();
            String username = (String) httpSession.getAttribute("user");
            String resultMessage = MessageUtils.getMessage(false, username, data);
            //发送数据
            onlineUsers.get(toName).session.getBasicRemote().sendText(resultMessage);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //关闭
    @OnClose
    public void onClose(Session session) {
        String username = (String) httpSession.getAttribute("user");
        //从容器中删除指定的用户
        onlineUsers.remove(username);
        MessageUtils.getMessage(true,null,getNames());
    }}


目录
相关文章
|
2月前
|
开发框架 前端开发 网络协议
Spring Boot结合Netty和WebSocket,实现后台向前端实时推送信息
【10月更文挑战第18天】 在现代互联网应用中,实时通信变得越来越重要。WebSocket作为一种在单个TCP连接上进行全双工通信的协议,为客户端和服务器之间的实时数据传输提供了一种高效的解决方案。Netty作为一个高性能、事件驱动的NIO框架,它基于Java NIO实现了异步和事件驱动的网络应用程序。Spring Boot是一个基于Spring框架的微服务开发框架,它提供了许多开箱即用的功能和简化配置的机制。本文将详细介绍如何使用Spring Boot集成Netty和WebSocket,实现后台向前端推送信息的功能。
464 1
|
1月前
|
Kubernetes Cloud Native JavaScript
为使用WebSocket构建的双向通信应用带来基于服务网格的全链路灰度
介绍如何使用为基于WebSocket的云原生应用构建全链路灰度方案。
|
2月前
|
前端开发 Java C++
RSocket vs WebSocket:Spring Boot 3.3 中的两大实时通信利器
本文介绍了在 Spring Boot 3.3 中使用 RSocket 和 WebSocket 实现实时通信的方法。RSocket 是一种高效的网络通信协议,支持多种通信模式,适用于微服务和流式数据传输。WebSocket 则是一种标准协议,支持全双工通信,适合实时数据更新场景。文章通过一个完整的示例,展示了如何配置项目、实现前后端交互和消息传递,并提供了详细的代码示例。通过这些技术,可以大幅提升系统的响应速度和处理效率。
|
4月前
|
开发框架 网络协议 Java
SpringBoot WebSocket大揭秘:实时通信、高效协作,一文让你彻底解锁!
【8月更文挑战第25天】本文介绍如何在SpringBoot项目中集成WebSocket以实现客户端与服务端的实时通信。首先概述了WebSocket的基本原理及其优势,接着详细阐述了集成步骤:添加依赖、配置WebSocket、定义WebSocket接口及进行测试。通过示例代码展示了整个过程,旨在帮助开发者更好地理解和应用这一技术。
393 1
|
4月前
|
小程序 Java API
springboot 微信小程序整合websocket,实现发送提醒消息
springboot 微信小程序整合websocket,实现发送提醒消息
|
4月前
|
JavaScript 前端开发 网络协议
WebSocket在Java Spring Boot+Vue框架中实现消息推送功能
在现代Web应用中,实时消息提醒是一项非常重要的功能,能够极大地提升用户体验。WebSocket作为一种在单个TCP连接上进行全双工通信的协议,为实现实时消息提醒提供了高效且低延迟的解决方案。本文将详细介绍如何在Java Spring Boot后端和Vue前端框架中利用WebSocket实现消息提醒功能。
207 0
|
消息中间件 缓存 前端开发
Springboot 整合 WebSocket ,使用STOMP协议 ,前后端整合实战 (一)
Springboot 整合 WebSocket ,使用STOMP协议 ,前后端整合实战 (一)
2149 1
Springboot 整合 WebSocket ,使用STOMP协议 ,前后端整合实战 (一)
|
消息中间件 存储 负载均衡
Springboot 整合 WebSocket ,使用STOMP协议+Redis 解决负载场景问题(二)
Springboot 整合 WebSocket ,使用STOMP协议+Redis 解决负载场景问题(二)
1302 0
Springboot 整合 WebSocket ,使用STOMP协议+Redis 解决负载场景问题(二)
|
2月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
173 1
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
111 62