Spring boot 使用 Websocket

一、概述

        Websocket是一种基于TCP的全双工通信协议,像我们日常使用的http协议是一种“半双工”也就是只能是客户端请求----服务器响应。而Websocket却可以实现让服务器主动给客户端发送消息。在没有Websocket之前想要实现客户端和服务器之间的,服务器主动发送消息给客户端,一般是通过客户端,轮询或者长连接的方式。Websocket在建立连接的时候用的是http协议,之后就使用的ws协议。


二、代码实现

1. pom依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

2. 配置类

/**
 * WebSocket config
 */
@Configuration
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}

3. Websocket核心实现类

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

    private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);

    /**
     *  online number user
     */
    private static int onlineCount = 0;
    /**
     *  ConcurrentHashMap
     */
    private static ConcurrentHashMap<String,WebSocketServer> concurrentHashMap = new ConcurrentHashMap<>();
    /**
     *  WebSocket Session
     */
    private Session session;
    /**
     *  Current userId;
     */
    private String userId = "";


    /**
     * made success next
     * @param session
     * @param userId
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId){
        this.session = session;
        this.userId = userId;
        if(concurrentHashMap.containsKey(userId)){
            concurrentHashMap.remove(userId);
            concurrentHashMap.put(userId,this);
        }else{
            concurrentHashMap.put(userId,this);
            addOnlineCount();
        }
        log.info("userId:"+userId+"online user num:"+getOnlineCount());
        sendMessage("link WebSocket is success!");

    }


    @OnMessage
    public void onMessage(String message){
        log.info("userId :"+userId+",send message:"+message+"to :other");
        if(StringUtils.isNotBlank(message)){
            Map<String,String> map = (Map<String, String>) JSONObject.parse(message);
            String toUserId = map.get("toUserId");
            String msg = map.get("contentText");
            if(StringUtils.isNotBlank(toUserId) && concurrentHashMap.containsKey(toUserId)){
                concurrentHashMap.get(toUserId).sendMessage(msg);
            }else{
                log.error("this userId is not this System");
            }
        }

    }

    @OnError
    public void onError(Throwable error){
        log.error("用户错误:"+this.userId+",原因:"+error.getMessage());
        error.printStackTrace();
    }

    @OnClose
    public void onClose(){
        if(concurrentHashMap.containsKey(userId)){
            concurrentHashMap.remove(userId);
            subOnlineCount();
        }else{
            log.info("user downed :"+userId+"online num is:"+getOnlineCount());
        }
    }




    private void sendMessage(String message) {
        try{
            this.session.getBasicRemote().sendText(message);
        }catch (IOException e){
            e.printStackTrace();
        }
    }


    private static void sendText(String message,String userId){
        log.info("send message:"+message+",to userId:"+userId);
        if(StringUtils.isNotBlank(userId) && concurrentHashMap.containsKey(userId)){
            concurrentHashMap.get(userId).sendMessage(message);
        }else {
            log.error("userId:"+userId+"is down");
        }

    }


    //广播
    public void sendAllMessage(String message){
        Set<Map.Entry<String, WebSocketServer>> entries = concurrentHashMap.entrySet();
        for(Map.Entry<String, WebSocketServer> enty : entries){
            enty.getValue().sendMessage("【服务器】 广播消息:"+message);
        }
    }

    //多发
    public void sendMoneyMessage(String[] userIds,String message){
        for (String userId : userIds){
            if(concurrentHashMap.containsKey(userId)){
                concurrentHashMap.get(userId).sendMessage("【服务器】VIP定向广播:"+message);
            }else{
                log.error(userId+"已断开无法通信");
            }
        }
    }




    public static synchronized int getOnlineCount(){
        return onlineCount;
    }

    public static synchronized void addOnlineCount(){
        log.info("调用++");
        onlineCount++;
    }

    public static synchronized void subOnlineCount(){
        log.info("调用--");
        onlineCount--;
    }

}

4. controller类

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

    @Autowired
    private WebSocketServer webSocketServer;

    @GetMapping
    public String goIndex(){

        return "WebSocketDemo";
    }

    @GetMapping("/index")
    public String index(){
        return "PollingDemo";
    }


    @GetMapping("/sendAllMessage")
    @ResponseBody
    public void sendAllMessage(String msg){
        webSocketServer.sendAllMessage(msg);
    }

    @PostMapping("/sendMoneyMessage")
    @ResponseBody
    public void sendMoneyMessage(String[] userIds,@RequestParam("msg") String msg2){
        System.out.println("==============="+userIds);
        webSocketServer.sendMoneyMessage(userIds,msg2);
    }
}

5. 前端页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebSocket Demo</title>
</head>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script>
    let socket;
    function openSocket() {


        const socketUrl = "ws://127.0.0.1:8099/api/pushMessage/" + $("#userId").val();
        console.log(socketUrl);
        if(socket!=null){
            socket.close();
            socket=null;
        }
        socket = new WebSocket(socketUrl);
        //打开事件
        socket.onopen = function() {
            console.log("websocket已打开");
        };
        //获得消息事件
        socket.onmessage = function(msg) {
            console.log(msg.data);
            //发现消息进入,开始处理前端触发逻辑
        };
        //关闭事件
        socket.onclose = function() {
            console.log("websocket已关闭");
        };
        //发生了错误事件
        socket.onerror = function() {
            console.log("websocket发生了错误");
        }
    }
    function closeSocket() {
        socket.close();
        socket=null;
        console.log('手动退出');
    }
    function sendMessage() {
        if(socket == null){
            console.log('请先开启Socket连接');
        }
        socket.send('{"toUserId":"'+$("#toUserId").val()+'","contentText":"'+$("#contentText").val()+'"}');
        //console.log('{"toUserId":"'+$("#toUserId").val()+'","contentText":"'+$("#contentText").val()+'"}');

    }
    function sendAllMessage() {
        $.ajax({
            url:"/websocket/sendAllMessage?msg="+$("#msg").val(),
            type:"GET"
        })
    }
    function sendMoneyMessage() {
        $.ajax({
            url: "/websocket/sendMoneyMessage",
            type: 'POST',
            traditional: true,
            data:{
                userIds: ['10','20','40'],
                msg: $("#msg2").val()
            }
        })

    }
</script>
<body>
<p>【socket开启者的ID信息】:<div><input id="userId" name="userId" type="text" value="10"></div>
<p>【客户端向服务器发送的内容】:<div><input id="toUserId" name="toUserId" type="text" value="20">
    <input id="contentText" name="contentText" type="text" value="hello websocket"></div>
<p>【利用服务器广播消息】:<div><input id="msg" name="msg" type="text">
<p>【利用服务器定向推送消息】:<div><input id="msg2" name="msg2" type="text">

<p>【操作】:<div><a onclick="openSocket()">开启socket</a></div>
<p>【操作】:<div><a onclick="closeSocket()">关闭连接</a></div>
<p>【操作】:<div><a onclick="sendMessage()">发送消息</a></div>
<p>【操作】:<div><a onclick="sendAllMessage()">广播消息</a></div>
<p>【操作】:<div><a onclick="sendMoneyMessage()">定向广播消息</a></div>
</body>
</html>

三、测试效果

 

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 使用Java Spring BootWebSocket程序,可以使用如下步骤: 1. 创建一个Spring Boot项目,选择Web和Websocket模块; 2. 在项目中配置WebSocket服务器,这可以通过实现WebSocketConfigurer接口并重写registerWebSocketHandlers方法来完成; 3. 创建一个WebSocket消息处理类,实现WebSocketHandler接口,并重写其中的方法来处理WebSocket消息; 4. 在页面上使用JavaScript代码连接WebSocket服务器并发送和接收消息。 以上就是使用Java Spring Boot编写WebSocket程序的基本流程。具体实现过程中可能会有一些细节需要注意,请参考相关文档或教程。 ### 回答2: 使用Java Spring Boot编写WebSocket是一种实现实时双向通信的常见方式。下面简要介绍一下如何使用Java Spring Boot编写WebSocket: 1. 首先,确保已经添加了Spring BootWebSocket依赖项。这可以通过在Maven或Gradle配置文件中添加相应的依赖项来实现。 2. 创建一个WebSocket配置类。在此类中,使用@EnableWebSocket注解启用WebSocket,并继承WebSocketConfigurer接口。重写registerWebSocketHandlers方法,创建并配置WebSocket处理器和WebSocket拦截器。 3. 创建一个WebSocket处理器类。在此类中,扩展TextWebSocketHandler类,并重写handleTextMessage方法以处理客户端发送的消息。您可以在此方法中编写自定义逻辑以处理消息。 4. 在WebSocket配置类中,使用addHandler方法将WebSocket处理器添加为WebSocket的处理程序,并指定WebSocket的端点。可以通过重写configureMessageBroker方法来配置消息代理(可选)。 5. 在控制器或服务类中,使用@MessageMapping和@SendTo注解定义处理WebSocket消息的方法。在处理方法中,您可以处理传入的消息并返回要发送给客户端的消息。 6. 在前端页面中,使用JavaScript编写WebSocket客户端代码。使用WebSocket对象连接到WebSocket服务器,并通过send方法发送消息。您可以使用onmessage事件处理器处理从服务器接收到的消息。 7. 运行应用程序并通过浏览器访问前端页面。您将能够使用WebSocket服务器进行实时双向通信。 这是一个基本的步骤和结构,用于使用Java Spring Boot编写WebSocket。根据您的需求,您可以根据自己的需求进行扩展和自定义。 ### 回答3: 使用Java Spring Boot编写WebSocket可以按照以下步骤进行: 1. 创建一个新的Spring Boot项目,并添加相关依赖。在pom.xml文件中添加spring-boot-starter-websocket依赖: ```xml <dependencies> <!-- 其他依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> </dependencies> ``` 2. 创建一个WebSocket处理器类,在该类中处理WebSocket的连接、消息发送和接收等操作。可以使用@Component注解将其作为一个Spring Bean进行管理。例如: ```java import org.springframework.stereotype.Component; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketMessage; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.TextWebSocketHandler; @Component public class MyWebSocketHandler extends TextWebSocketHandler { @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { // WebSocket连接建立后的操作 // 可以在此保存会话信息,如将该会话加入到某个会话列表中 } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { // 接收到WebSocket消息的操作 // 可以在此处理接收到的消息,并根据需要进行回复 String receivedMessage = message.getPayload(); // 处理消息并回复 session.sendMessage(new TextMessage("Received: " + receivedMessage)); } // 其他WebSocket操作的重写方法 } ``` 3. 创建一个WebSocket配置类,配置WebSocket的端点以及WebSocket处理器。可以使用@EnableWebSocket注解开启WebSocket支持,并重写registerWebSocketHandlers方法配置WebSocket处理器和端点。例如: ```java import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(new MyWebSocketHandler(), "/websocket") .setAllowedOrigins("*"); // 允许跨域访问 } } ``` 4. 启动Spring Boot应用程序,WebSocket将注册/websocket端点以供客户端连接。客户端可以使用浏览器的WebSocket API或其他WebSocket客户端与服务器建立连接,并发送和接收WebSocket消息。 以上就是使用Java Spring Boot编写WebSocket的基本步骤,根据需要可以进一步修改和扩展WebSocket处理器以满足具体的业务需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值