什么是webSocket

WebSocket是一种建立在TCP协议之上的通信协议,也称长连接套接字。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

以下主要分为两个方面来实现,1-服务器后台,2-网页客户端

服务器后台WebSocketServer搭建

  • 引入依赖,在此之前我们已经构建好了SpringBoot框架,当然也可以直接在构建SpringBoot框架的时候勾选WebSocket
<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.20</version>
    <scope>provided</scope>
</dependency>
  • 配置Config类
@Configuration
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}
  • controller编写
@Controller
public class WebSocketController {

    @RequestMapping("/webSocket")
    @ResponseBody
    public void webSocket(HttpServletRequest request){

        String ip = request.getRemoteAddr();
        try {
            WebSocketServer.sendInfo("有新小伙伴加入了我们"+ip);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

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

  • 核心的WebSocketServer类
/**
 * com.qd.ws.controller
 *
 * @author liyawei
 * @date 2018/5/21
 */
@Slf4j
@ServerEndpoint(value = "/webSocket")
@Component
public class WebSocketServer {

    // 当前客户端连接数
    private static int onlineCount = 0;

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

    private Session session;

    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        webSocket.add(this);
        addCount();
        log.info("有新的小伙伴加入,目前连接数:" + onlineCount);
        try {
            sendMessage("连接成功,欢迎回来");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @OnClose
    public void onClose() {
        webSocket.remove(this);
        subCount();
        log.info("又一位小伙伴失去了梦想,目前连接数:" + onlineCount);
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("收到消息:" + message);
        try {
            sendInfo(message);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("消息发送失败");
        }
    }

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

    /**
     * 发送消息
     *
     * @param message
     * @throws IOException
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    public static void sendInfo(String message) throws IOException {
        log.info(message);
        for (WebSocketServer webSocketServer : webSocket) {
            try {
                webSocketServer.sendMessage(message);
            } catch (IOException e) {
                // 如果有发送失败的继续发送下一个
                continue;
            }
        }
    }

    public static synchronized Integer getCount(){
        return onlineCount;
    }

    public static synchronized void addCount() {
        onlineCount++;
    }

    public static synchronized void subCount() {
        onlineCount--;
    }
}

H5客户端实现

这里需要在application.properties或yml中配置一下web页面配置,这样可以让controller直接返回html页面,当然你也可以用使用模板引擎

spring.mvc.view.prefix=/
spring.mvc.view.suffix=.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>QD聊天室</title>
</head>
<body>
<div>
    <input type="text" id="sendMessage">
    <button type="button" onclick="send()">发送</button>
    <div id="getMessage"></div>

    <script type="text/javascript">
        // 判断当前浏览器是否支持webSocket
        webSocket = new WebSocket("ws://localhost:8089/webSocket");

        webSocket.onopen = function (ev) {
            alert("欢迎回来");
        };

        webSocket.onclose = function (ev) {
            alert("88");
        };

        webSocket.onmessage = function (ev) {
            displayMessage(ev.data);
        };

        function displayMessage(innerHTML) {
            document.getElementById('getMessage').innerHTML += innerHTML+'<br/>';
        }

        function close() {
            webSocket.close();
        }

        function send() {
            var sendMessage = document.getElementById('sendMessage').value;
            webSocket.send(sendMessage);
        }
    </script>
</div>
</body>
</html>

页面效果,不要在意这些细节。。

客户端发送消息和服务器后台