java webSocket


前端代码





后端代码

--引入包



org.springframework.boot
spring-boot-starter-websocket

import cn.com.zhengya.framework.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.server.Session;
import org.springframework.stereotype.Component;

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;


/**
 * webSocket客户端
 * @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 webSocketSet = new CopyOnWriteArraySet();

    /**
     * 存活的session集合(使用线程安全的map保存)
     */
    private static Map 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 getAllMac() {
        return new ArrayList<>(livingSessions.keySet());
    }


}

-发送消息

@Data
@ApiModel("发送消息给指定的对象")
public class SocketParam {
    @ApiModelProperty("发送对象标识(物理机器的MAC地址)")
    private String mac;
    @ApiModelProperty("消息")
    private String message;
}
@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());
    }

}