码迷,mamicode.com
首页 > 编程语言 > 详细

java webSocket

时间:2021-01-14 11:00:20      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:etl   vol   new   客户   cti   error   string   too   wired   

Springboot整合web socket

引入包

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

config

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

/**
 * websocket配置
 *
 * @author luwl
 * @date 2021/1/13 10:50
 */
@Configuration
public class WebSocketConfig {

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


}

server

import cn.com.zhengya.framework.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;


/**
 * @author luwl
 * @date 2021/1/13 10:54
 * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 * {mac}是传递唯一标识的识别参数
 */
@Slf4j
@Component
@ServerEndpoint("/socket/{mac}")
public class WebSocketServer {

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

    /**
     * 存活的session集合(使用线程安全的map保存)
     */
    private static Map<String, Session> livingSessions = new ConcurrentHashMap<>();
    /**
     * 在线的连接对象
     */
    private static volatile int livingCount = 0;
    /**
     * 当前的session对象
     */
    private Session session;

    /**
     * 建立连接的回调方法
     *
     * @param session 与客户端的WebSocket连接会话
     * @param mac     硬件MAC地址 唯一
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("mac") String mac) {
        if(!livingSessions.containsKey(mac)) {
            webSocketSet.add(this);
            livingSessions.put(mac, session);
            this.session = session;
            addLivingCount();
            log.info(mac + " 进入连接,当前连接中数量为:" + getLivingCount());
        }else {
            log.info(mac + "重新连接,当前连接中数量为:" + getLivingCount());
        }
    }

    @OnMessage
    public void onMessage(String message, Session session, @PathParam("mac") String mac) {
        log.info(mac + " : " + message);
        sendMessageToAll(message);
    }


    @OnError
    public void onError(Session session, Throwable error) {
        log.info("发生错误");
        log.error(error.getStackTrace() + "");
    }


    @OnClose
    public void onClose(Session session, @PathParam("mac") String mac) {
        webSocketSet.remove(this);
        livingSessions.remove(mac);
        subLivingCount();
        log.info(mac + " 关闭连接,当前连接中数量为:" + getLivingCount());
    }

    /**
     * 单独发送消息到指定用户
     *
     * @param message
     */
    public void sendMessage(String mac, String message) {
        try {
            if(getLivingCount()!=0) {
                livingSessions.get(mac).getBasicRemote().sendText(message);
            }else {
                throw new ServiceException("当前无连接对象");
            }
        } catch (IOException e) {
            log.info("sendMessage error", e);
        }
    }

    /**
     * 单独发送消息到当前用户
     *
     * @param message
     */
    public void sendMessage(String message) {
        try {
            synchronized (this) {
                this.session.getBasicRemote().sendText(message);
            }
        } catch (IOException e) {
            log.info("sendMessage error", e);
        }
    }

    /**
     * 群发消息
     *
     * @param message
     */
    public void sendMessageToAll(String message) {
        if(getLivingCount()!=0) {
            for (WebSocketServer server : webSocketSet) {
                server.sendMessage(message);
            }
        }else {
            throw new ServiceException("当前无连接对象");
        }
    }


    public static synchronized int getLivingCount() {
        return livingCount;
    }

    public static synchronized void addLivingCount() {
        WebSocketServer.livingCount++;
    }

    public static synchronized void subLivingCount() {
        WebSocketServer.livingCount--;
    }

    /**
     * 获取所有连接中对象的标识
     * @return
     */
    public List<String> getAllMac(){
        return new ArrayList<>(livingSessions.keySet());
    }


}

到这里启动项目就行了

客户端就简单使用html F12查看

<!DOCTYPE HTML>
<html>
   <head>
   <meta charset="utf-8">
   <title>websocket 客户端</title>
    
      <script type="text/javascript">
         function WebSocketTest()
         {
            if ("WebSocket" in window)
            {
               alert("您的浏览器支持 WebSocket!");
               
               // 创建一个 websocket
               var ws = new WebSocket("ws://localhost:8034/socket/00149733FABB");
                
               ws.onOpen = function()
               {
                  // Web Socket 已连接上,使用 send() 方法发送数据
                  ws.send("发送数据");
                  console.log("数据发送中")
               };
                
               ws.onMessage = function (evt) 
               { 
                  console.log(evt)
                  console.log(evt.data)
               };
                
               ws.onClose = function()
               { 
                  // 关闭 websocket
                  alert("连接已关闭..."); 
               };
            }
            else
            {
               // 浏览器不支持 WebSocket
               alert("您的浏览器不支持 WebSocket!");
            }
         }
      </script>
        
   </head>
   <body>
   
      <div id="sse">
         <a href="javascript:WebSocketTest()">运行 WebSocket</a>
      </div>
      
   </body>
</html>

 

想要主动发送通知的话用下面的controller

import cn.com.zhengya.framework.model.Result;
import cn.com.zhengya.framework.socket.WebSocketServer;
import cn.com.zhengya.spdapi.dto.tool.socket.SocketParam;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * Socket 服务端
 * @author luwl
 * @date 2021/1/13 13:21
 */
@Slf4j
@RestController
@RequestMapping("/socket/api")
@Api(value = "socket服务", tags = "socket服务")
public class SocketController {

    @Autowired
    private WebSocketServer webSocketServer;

    @PostMapping("/sendMessageToOne")
    @ApiOperation(value = "发送消息给单个通道")
    public Result<?> sendMessageToOne(@RequestBody SocketParam socketParam){
        webSocketServer.sendMessage(socketParam.getMac(),socketParam.getMessage());
        return Result.success();
    }

    @PostMapping("/sendMessageToALL")
    @ApiOperation(value = "发送消息给所有通道")
    public Result<?> sendMessageToAll(@RequestParam String message){
        webSocketServer.sendMessageToAll(message);
        return Result.success();
    }

    @PostMapping("/getAllSession")
    @ApiOperation(value = "获取所有连接中通道")
    public Result<?> getAllSession(){
        return Result.success(webSocketServer.getAllMac());
    }

}
/**
 * @author luwl
 * @date 2021/1/13 13:24
 */
@Data
@ApiModel("发送消息给指定的对象")
public class SocketParam {
    @ApiModelProperty("发送对象标识(物理机器的MAC地址)")
    private String mac;
    @ApiModelProperty("消息")
    private String message;
}

 

java webSocket

标签:etl   vol   new   客户   cti   error   string   too   wired   

原文地址:https://www.cnblogs.com/Sora-L/p/14271601.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!