SpringBoot 配置 WebSocket

来源:互联网 发布:中国人工智能技术发展 编辑:程序博客网 时间:2024/05/20 13:38

原文如下

Spring Boot provides WebSockets auto-configuration for embedded Tomcat (8 and 7), Jetty 9 and Undertow. If you’re deploying a war file to a standalone container, Spring Boot assumes that the container will be responsible for the configuration of its WebSocket support.

Spring Framework provides rich WebSocket support that can be easily accessed via the spring-boot-starter-websocket module.

开始配置,pom.xml

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

MyWebSocketConfig

@Configuration@EnableWebSocketpublic class MyWebSocketConfig implements WebSocketConfigurer {    public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {        webSocketHandlerRegistry                .addHandler(myTextWebSocketHandler(), "/alarm/webSocket")                .addInterceptors(myHttpSessionHandshakeInterceptor())                .setAllowedOrigins("http://mydomain.com");        //可指定多个跨域,如果无需限制可使用 *    }    //用于定义 WebSocket 的消息处理    @Bean    public WebSocketHandler myTextWebSocketHandler() {        return new MyTextWebSocketHandler();    }    //用于处理 WebSocket 连接    @Bean    public HandshakeInterceptor myHttpSessionHandshakeInterceptor(){        return new MyHttpSessionHandshakeInterceptor();    }}

MyHttpSessionHandshakeInterceptor

public class MyHttpSessionHandshakeInterceptor extends HttpSessionHandshakeInterceptor {    private static final Logger log = LoggerFactory.getLogger(MyHttpSessionHandshakeInterceptor.class);    //握手前    @Override    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,                                   Map<String, Object> attributes) throws Exception {        log.trace("Before Handshake");        if (request instanceof ServletServerHttpRequest) {            ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;            String username = servletRequest.getServletRequest().getParameter("username");            //必须提供 username 请求参数,否则不允许连接            if (null == username || username.equals(""))                return false;            attributes.put(MyTextWebSocketHandler.WEB_SOCKET_USERNAME, username);        }        return super.beforeHandshake(request, response, wsHandler, attributes);    }    //握手后    @Override    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,                               Exception ex) {        log.trace("After Handshake");        super.afterHandshake(request, response, wsHandler, ex);    }}

MyTextWebSocketHandler

public class MyTextWebSocketHandler extends TextWebSocketHandler {    public static final String WEB_SOCKET_USERNAME = "webSocketUsername";    private static final Map<String, WebSocketSession> users = new ConcurrentHashMap<>();    private static final Logger log = LoggerFactory.getLogger(MyTextWebSocketHandler.class);    //处理文本消息    @Override    public void handleTextMessage(WebSocketSession session, TextMessage message) {        log.trace("用户 " + session.getAttributes().get(WEB_SOCKET_USERNAME) + " 发来一条信息:" + message);        try {            session.sendMessage(new TextMessage("已收到,谢谢"));        } catch (IOException e) {            e.printStackTrace();        }    }    //连接建立后处理    @Override    public void afterConnectionEstablished(WebSocketSession session) throws Exception {        super.afterConnectionEstablished(session);        String username = (String) session.getAttributes().get(WEB_SOCKET_USERNAME);        users.put(username, session);        log.trace("用户 " + username + " 连接 WebSocket 成功......当前用户数量为:" + users.size());        session.sendMessage(new TextMessage("欢迎光临,热烈欢迎"));    }    //连接关闭后处理    @Override    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {        String username = (String) session.getAttributes().get(WEB_SOCKET_USERNAME);        users.remove(username);        log.trace(username + " 退出......剩余在线用户数量:" + users.size());        super.afterConnectionClosed(session, status);    }    //抛出异常时处理    @Override    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {        super.handleTransportError(session, exception);        String username = (String) session.getAttributes().get(WEB_SOCKET_USERNAME);        if(session.isOpen())            session.close();        users.remove(username);        log.error("Web Socket 发生异常!");    }    //是否支持局部消息    @Override    public boolean supportsPartialMessages() {        return false;    }    /**     * 给某个用户发送消息     *     * @param username     * @param message     */    public static void sendMessageToUser(String username, TextMessage message) {        WebSocketSession user = users.get(username);        doSendMessage(user, message);        log.info("给指定用户(" + username + ")发送一条消息:" + message);    }    /**     * 给所有在线用户发送消息     *     * @param message     */    public static void sendMessageToAllUser(TextMessage message) {        for (WebSocketSession user : users.values()) {            doSendMessage(user, message);        }        log.info("给所有 WebSocket 用户发送一条消息:" + message);    }    private static void doSendMessage(WebSocketSession user, TextMessage message){        try {            if (null != user && user.isOpen()) {                user.sendMessage(message);            }        } catch (IOException e) {            log.error(e.getMessage());            e.printStackTrace();        }    }}

webSocket1.html

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title></head><body>Welcome<br/><input id="text" type="text"/><button onclick="send()">发送消息</button><hr/><button onclick="closeWebSocket()">关闭WebSocket连接</button><hr/><div id="message"></div></body><script type="text/javascript">    var websocket = null;    //判断当前浏览器是否支持WebSocket    if ('WebSocket' in window) {        websocket = new WebSocket("ws://localhost:8080/pomer/alarm/webSocket?username=1号");    }    else {        alert('当前浏览器 Not support websocket')    }    //连接发生错误的回调方法    websocket.onerror = function () {        setMessageInnerHTML("WebSocket 连接发生错误");    };    //连接成功建立的回调方法    websocket.onopen = function () {        setMessageInnerHTML("WebSocket 连接成功");    }    //接收到消息的回调方法    websocket.onmessage = function (event) {        setMessageInnerHTML(event.data);    }    //连接关闭的回调方法    websocket.onclose = function () {        setMessageInnerHTML("WebSocket 连接关闭");    }    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。    window.onbeforeunload = function () {        closeWebSocket();    }    function closeWebSocket(){        websocket.close();    }    //将消息显示在网页上    function setMessageInnerHTML(innerHTML) {        document.getElementById('message').innerHTML += innerHTML + '<br/>';    }    //发送消息    function send() {        var message = document.getElementById('text').value;        websocket.send(message);    }</script></html>

AlarmTask(每隔 10s 向所有 WebSocket 用户发一条信息)

@Componentpublic class AlarmTask {    private Logger logger = LoggerFactory.getLogger(this.getClass());    private static int count = 0;    @Scheduled(cron="0/10 * * * * ?")    public void executeAlarmCheckTask() {        logger.warn("aheeeeeeeeeeeeeeeeee " + ++count);        MyTextWebSocketHandler.sendMessageToAllUser(new TextMessage("报警一下:" + count));    }}

执行系统,打开 webSocket1.html,显示:

WebSocket 连接成功欢迎光临,热烈欢迎报警一下:12报警一下:13报警一下:14报警一下:15报警一下:16报警一下:17报警一下:18报警一下:19报警一下:20报警一下:21报警一下:22报警一下:23报警一下:24报警一下:25
原创粉丝点击