spring项目整合webSocket附带测试结果

1、引入jar包
maven项目

        <!-- WebSocket -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-websocket</artifactId>
			<version>2.1.0.RELEASE</version>
		</dependency>

如果是Java项目,引入以下jar包
在这里插入图片描述
红框为必须:
javax.websocket-api-1.0.jar
spring-context-4.2.5.RELEASE.jar
spring-websocket-4.2.5.RELEASE.jar
注意引入jar包和项目所用的spring版本保持一致,项目中用4.2.5我这demo也用这个
2、编写配置文件

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfig {
    
    
    /**
     * 注入ServerEndpointExporter,
     * 这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
    
    
        return new ServerEndpointExporter();
    }
}

2、编写主要的实现类

import com.alibaba.fastjson.JSON;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.entity.SocketMessage;
import java.io.IOException;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@ServerEndpoint("/webSocket/{userId}")
@Component
public class WebSocketServer {
    
    


	 //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static AtomicInteger onlineNum = new AtomicInteger();

    //concurrent包的线程安全Set,用来存放每个客户端对应的WebSocketServer对象。
    private static ConcurrentHashMap<String, Session> sessionPools = new ConcurrentHashMap<>();

    //发送消息
    public void sendMessage(Session session, String message) throws IOException {
    
    
        if(session != null){
    
    
            synchronized (session) {
    
    
                session.getBasicRemote().sendText(message);
            }
        }
    }
    //给指定用户发送信息
    public Integer sendInfo(String userId, String message){
    
    
        Session session = sessionPools.get(userId);
        try {
    
    
            sendMessage(session, message);
            return 1;
        }catch (Exception e){
    
    
            e.printStackTrace();
            return 0;
        }
    }
    // 群发消息
    public void broadcast(String message){
    
    
    	for (Session session: sessionPools.values()) {
    
    
            try {
    
    
                sendMessage(session, message);
            } catch(Exception e){
    
    
                e.printStackTrace();
                continue;
            }
        }
    }

    //建立连接成功调用
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "userId") String userId){
    
    
        sessionPools.put(userId, session);
        addOnlineCount();
        // 广播上线消息
        SocketMessage msg = new SocketMessage();
        msg.setDate(new Date());
        msg.setTo("0");
        msg.setText(userId);
        broadcast(JSON.toJSONString(msg,true));
    }

    //关闭连接时调用
    @OnClose
    public void onClose(@PathParam(value = "userId") String userId){
    
    
        sessionPools.remove(userId);
        subOnlineCount();
        // 广播下线消息
        SocketMessage msg = new SocketMessage();
        msg.setDate(new Date());
        msg.setTo("-2");
        msg.setText(userId);
        broadcast(JSON.toJSONString(msg,true));
    }

    //收到客户端信息后,根据接收人的userId把消息推下去或者群发
    // to=-1群发消息
    @OnMessage
    public void onMessage(String message) throws IOException{
    
    
        SocketMessage msg= JSON.parseObject(message, SocketMessage.class);
		msg.setDate(new Date());
		if (msg.getTo().equals("-1")) {
    
    
			broadcast(JSON.toJSONString(msg,true));
		} else {
    
    
			sendInfo(msg.getTo(), JSON.toJSONString(msg,true));
		}
    }

    //错误时调用
    @OnError
    public void onError(Session session, Throwable throwable){
    
    
        throwable.printStackTrace();
    }

    public static void addOnlineCount(){
    
    
        onlineNum.incrementAndGet();
    }

    public static void subOnlineCount() {
    
    
        onlineNum.decrementAndGet();
    }

    public static AtomicInteger getOnlineNumber() {
    
    
        return onlineNum;
    }

    public static ConcurrentHashMap<String, Session> getSessionPools() {
    
    
        return sessionPools;
    }
}

引入了额外的jar包也是为了这里使用的,其中在这里插入图片描述
这个实体类是为了方便发送消息添加的,也可删掉这块相关的代码,不影响,我这里也贴出,方便大家使用

import com.alibaba.fastjson.annotation.JSONField;

import java.util.Date;

public class SocketMessage {
    
    

	//发送者name
	public String from;
	//接收者name
	public String to;
	//发送的文本
	public String text;
	//发送时间
	@JSONField(format="yyyy-MM-dd HH:mm:ss")
	public Date date;

	public String getFrom() {
    
    
		return from;
	}

	public void setFrom(String from) {
    
    
		this.from = from;
	}

	public String getTo() {
    
    
		return to;
	}

	public void setTo(String to) {
    
    
		this.to = to;
	}

	public String getText() {
    
    
		return text;
	}

	public void setText(String text) {
    
    
		this.text = text;
	}

	public Date getDate() {
    
    
		return date;
	}

	public void setDate(Date date) {
    
    
		this.date = date;
	}

	@Override
	public String toString() {
    
    
		return "SocketMessage{" +
				"from='" + from + '\'' +
				", to='" + to + '\'' +
				", text='" + text + '\'' +
				", date=" + date +
				'}';
	}
}

3、编写测试接口

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.service.WebSocketServer;

@Controller
@RequestMapping("/web")
public class WebSocketController {
    
    

    @Autowired
    WebSocketServer webSocketServer;

    /**
     * 发送单人消息
     *
     * @param userId 接收人用户ID
     * @param mes    消息
     * @return 1 发送成功  0 发送失败
     */
    @RequestMapping("/sendInfo")
    @ResponseBody
    public Integer sendInfo(@RequestParam("userId") String userId, @RequestParam("mes") String mes) {
    
    
        Integer num = webSocketServer.sendInfo(userId, mes);
        return num;
    }


    /**
     * 群发消息
     *
     * @param mes 消息
     * @return 1 发送成功  0 发送失败
     */
    @RequestMapping("/broadcast")
    @ResponseBody
    public void broadcast(@RequestParam String mes) {
    
    
        webSocketServer.broadcast(mes);
    }


    /**
     * 测试发送多条
     */
    @RequestMapping("/sendInfoFor")
    @ResponseBody
    public Integer sendInfo() {
    
    
        for (int i = 0; i < 100; i++) {
    
    
            webSocketServer.sendInfo(1 + "", i + "");
        }

        return 1;
    }

}

4、简单的html页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
          integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <title>websocket测试页面</title>
</head>
<body>
<div class="panel panel-default">
    <div class="panel-body">
        <div class="row">
            <div class="col-md-6">
                <div class="input-group">
                    <span class="input-group-addon">ws地址</span>
                    <input type="text" id="address" class="form-control" placeholder="ws地址"
                           aria-describedby="basic-addon1" value="ws://localhost:8010/webSocket/admin">
                    <div class="input-group-btn">
                        <button class="btn btn-default" type="submit" id="connect">连接</button>
                    </div>
                </div>
            </div>
        </div>
        <div class="row" style="margin-top: 10px;display: none;" id="msg-panel">
            <div class="col-md-6">
                <div class="input-group">
                    <span class="input-group-addon">消息</span>
                    <input type="text" id="msg" class="form-control" placeholder="消息内容" aria-describedby="basic-addon1">
                    <div class="input-group-btn">
                        <button class="btn btn-default" type="submit" id="send">发送</button>
                    </div>
                </div>
            </div>
        </div>
        <div class="row" style="margin-top: 10px; padding: 10px;">
            <div class="panel panel-default">
                <div class="panel-body" id="log" style="height: 450px;overflow-y: auto;">
                </div>
            </div>
        </div>
    </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"
        integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
        crossorigin="anonymous"></script>

<script type="text/javascript">
    $(function () {
     
     
        var _socket;

        $("#connect").click(function () {
     
     
            _socket = new _websocket($("#address").val());
            _socket.init();
        });

        $("#send").click(function () {
     
     
            var _msg = $("#msg").val();
            output("发送消息:" + _msg);
            _socket.client.send(JSON.stringify(_msg));
        });
    });

    function output(e) {
     
     
        var _text = $("#log").html();
        $("#log").html(_text + "<br>" + e);
    }

    function _websocket(address) {
     
     
        this.address = address;
        this.client;

        this.init = function () {
     
     
            if (!window.WebSocket) {
     
     
                this.websocket = null;
                return;
            }

            var _this = this;
            var _client = new window.WebSocket(_this.address);

            _client.onopen = function () {
     
     
                output("websocket打开");
                $("#msg-panel").show();
            };

            _client.onclose = function () {
     
     
                _this.client = null;
                output("websocket关闭");
                $("#msg-panel").hide();
            };

            _client.onmessage = function (evt) {
     
     
                output(evt.data);
            };

            _this.client = _client;
        };

        return this;
    }
</script>
</body>
</html>

可以把这里修改成自己项目的访问地址,方便每次访问
在这里插入图片描述
5、进行测试
启动项目,启动html页面,点击连接
在这里插入图片描述
连接成功会如图所示
打开postman发送请求
在这里插入图片描述
这里的1是发送成功之后的返回值,也可根据实际情况来修改
html页面已接受到消息
在这里插入图片描述
最后附上项目的结构图,demo项目有点粗糙
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45352783/article/details/108703504