文档章节

在Java代码中使用Spring WebSocket

Kxvz
 Kxvz
发布于 2017/12/19 10:09
字数 1101
阅读 975
收藏 39

首先 pom.xml

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>1.5.8.RELEASE</version>
</parent>

	

<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-io</artifactId>
</dependency>
<dependency>
	<groupId>javax.websocket</groupId>
	<artifactId>javax.websocket-api</artifactId>
	<version>1.0</version>
	<scope>provided</scope>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-websocket</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
	<exclusions>
		<exclusion>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
		</exclusion>
	</exclusions>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>

 

接收消息后的处理类 GameHandler :

import java.net.URI;
import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.PongMessage;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;

public class GameHandler extends AbstractWebSocketHandler {

    /**
     * 处理字符串类的信息
     *
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        session.sendMessage(new TextMessage(message.asBytes()));
    }

    /**
     * 处理二进制类的信息
     *
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception {
        session.sendMessage(new BinaryMessage(message.getPayload()));
    }

    /**
     * ping-pong
     *
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    protected void handlePongMessage(WebSocketSession session, PongMessage message) throws Exception {
	
    }

    /**
     * 传出错误的处理
     *
     * @param session
     * @param exception
     * @throws Exception
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
	
    }

    /**
     * 连接关闭的处理
     *
     * @param session
     * @param status
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
    }

    /**
     * 连接建立后的处理
     *
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
	
    }
}

 

握手信息拦截器  WebSocketHandshakeInterceptor :

import java.util.Map;
import javax.servlet.http.Cookie;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;


public class WebSocketHandshakeInterceptor implements HandshakeInterceptor {

    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse shr1, WebSocketHandler wsh, Map<String, Object> attributes) throws Exception {
        // 此处可以做一些权限认证的事情或者其他
        return true;
    }

    @Override
    public void afterHandshake(ServerHttpRequest shr, ServerHttpResponse shr1, WebSocketHandler wsh, Exception excptn) {
	
    }
}

 

使用WebSocket的配置类  WebSocketConfig :

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
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 extends WebMvcConfigurerAdapter implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        // 允许连接的域,只能以http或https开头
        String[] allowsOrigins = {"http://127.0.0.1:1213", "http://localhost:1213"};
        registry.addHandler(gameHandler(),"/game").addInterceptors(handshakeInterceptor()).setAllowedOrigins(allowsOrigins);
    }

    @Bean
    public GameHandler gameHandler() {
        return new GameHandler();
    }

    @Bean
    public WebSocketHandshakeInterceptor handshakeInterceptor() {
        return new WebSocketHandshakeInterceptor();
    }
}

 

启动类 Launcher  : 

@SpringBootApplication
public class Launcher {

    public static void main(String[] params) {
        SpringApplication.run(Launcher.class, params);
	}
}

 

配置文件 main/resources/application.properties:

server.port=1213
server.session-timeout=1800
server.undertow.io-threads=4
server.undertow.worker-threads=20
server.undertow.buffer-size=1024
server.undertow.buffers-per-region=1024
server.undertow.direct-buffers=true

 

前端的测试页面 main\resources\static\index.html

<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Platform Gateway</title>
        <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
        <!--<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" rel="stylesheet">-->
        <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
        <script src="https://cdn.bootcss.com/jquery-scrollTo/2.1.2/jquery.scrollTo.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/pako/1.0.6/pako.min.js"></script>
        <!--[if lt IE 9]>
          <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
          <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
        <![endif]-->
        <style>
            #message{
                height: 600px;
                overflow-y:auto;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <h1>WebSocket Test Page</h1>
            <hr/>
            <div class="form-inline">
                <div class="form-group">
                    <label for="wsAddr">WebSocket Address: </label>
                    <div class="input-group">
                        <span class="input-group-addon" id="basic-ws">ws://127.0.0.1:1213/</span>
                        <input type="text" class="form-control" id="basic-ws-addr" aria-describedby="basic-ws" placeholder="game" data-container="body"  data-placement="top" data-content="链接地址不能为空,请填写">
                    </div>
                </div>
                <button type="button" id="btnConnect" class="btn btn-primary" onclick="connect();">
                    <span class="glyphicon glyphicon-resize-small" aria-hidden="true"></span>
                    连接
                </button>
                <button type="button" id="btnClose" class="btn btn-danger" disabled="disabled" onclick="closeWebSocket();">
                    <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
                    断开
                </button>
                <button type="button" id="btnSend" class="btn btn-info" disabled="disabled" style="margin-left: 50px;" onclick="send();">
                    <span class="glyphicon glyphicon-transfer" aria-hidden="true"></span>
                    发送消息
                </button>
            </div><br/>
            <textarea class="form-control" id="inMsg" rows="5" placeholder="在这里输入需要发送的信息..."></textarea>
            <hr/>
            <div id="message"></div>
        </div>
        <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
        <script type="text/javascript">
                    function zip(str) {
                        var binaryString = pako.gzip(str, {to: 'string'});
                        return btoa(binaryString);
                    }

                    function unzip(b64Data) {
                        var strData = atob(b64Data);
                        var charData = strData.split('').map(function (x) {
                            return x.charCodeAt(0);
                        });
                        var binData = new Uint8Array(charData);
                        var data = pako.inflate(binData);
                        strData = String.fromCharCode.apply(null, new Uint16Array(data));
                        return strData;
                    }

                    var websocket = null;
                    var wsBaseUrl = null;
                    var wsUrl = null;
                    function init() {
                        wsBaseUrl = "ws://" + window.location.host + "/";
                        $("#basic-ws").text(wsBaseUrl);
                        $(function () {
                            $('[data-toggle="popover"]').popover();
                        });
                        return false;
                    }
//关闭WebSocket连接
                    function closeWebSocket() {
                        if (websocket) {
                            websocket.close();
                        }
                        return false;
                    }

//将消息显示在网页上
                    function setMessageInnerHTML(who, msg) {
                        var message = null;
                        if (who === 1) {
                            message = '<div class="alert alert-success" role="alert">本地: ' + msg + '</div>';
                        } else {
                            message = '<div class="alert alert-info" role="alert">服务器: ' + msg + '</div>';
                        }
                        document.getElementById('message').innerHTML = (document.getElementById('message').innerHTML + message);
                        $("#message").scrollTo('100%');
                        return false;
                    }

//发送消息
                    function send() {
                        if (websocket) {
                            var message = $("#inMsg").val();
                            websocket.send(zip(message));
                            setMessageInnerHTML(1, message);
                        }
                        return false;
                    }
                    function connect() {
                        var url = $("#basic-ws-addr").val();
                        if (url.length <= 0) {
                            $('#basic-ws-addr').popover('show');
                            setTimeout(function () {
                                $('#basic-ws-addr').popover('hide');
                            }, 3000);
                        } else {
                            wsUrl = wsBaseUrl + url;
                            if ('WebSocket' in window) {
                                websocket = new WebSocket(wsUrl);
                                //连接发生错误的回调方法
                                websocket.onerror = function () {
                                    setMessageInnerHTML(0, "WebSocket连接发生错误 -> " + wsUrl);
                                    $("#btnConnect").removeAttr("disabled");
                                    $("#btnClose").attr("disabled", "disabled");
                                    $("#btnSend").attr("disabled", "disabled");
                                };

                                //连接成功建立的回调方法
                                websocket.onopen = function () {
                                    setMessageInnerHTML(0, "WebSocket连接成功 -> " + wsUrl);
                                    $("#btnConnect").attr("disabled", "disabled");
                                    $("#btnClose").removeAttr("disabled");
                                    $("#btnSend").removeAttr("disabled");
                                };

                                //接收到消息的回调方法
                                websocket.onmessage = function (event) {
                                    setMessageInnerHTML(0, unzip(event.data));
                                };

                                //连接关闭的回调方法
                                websocket.onclose = function () {
                                    setMessageInnerHTML(0, "WebSocket连接关闭 -> " + wsUrl);
                                    $("#btnConnect").removeAttr("disabled");
                                    $("#btnClose").attr("disabled", "disabled");
                                    $("#btnSend").attr("disabled", "disabled");
                                };

                                //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
                                window.onbeforeunload = function () {
                                    closeWebSocket();
                                };
                            } else {
                                alert('Not support websocket');
                            }
                        }
                        return false;
                    }
                    window.onload = init();
        </script>
    </body>
</html>

 

到此就可以使用 WebSocket 进行前后端的通信了,Good Luck.

© 著作权归作者所有

Kxvz
粉丝 12
博文 106
码字总数 29791
作品 0
成都
程序员
私信 提问
关于 Java Scripting API 您不知道的 5 件事

现在,许多 Java 开发人员都喜欢在 Java 平台中使用脚本语言,但是使用编译到 Java 字节码中的动态语言有时是不可行的。在某些情况中,直接编写一个 Java 应用程序的脚本 部分 或者在一个脚本...

红薯
2010/09/12
495
2
Java 8 彻底改变数据库访问

Java 8终于到来了! 经过几年的等待, java程序员终于能在java中得到函数式编程的支持了. 函数式编程的支持能流程化现有的代码并且为java提供强大的能力.在这些新特性中最瞩目的是java程序员对...

oschina
2014/03/26
19.4K
111
设置eclise运行时JVM内存

Eclipse 中设置JVM 内存 今天在eclipse 中测试把文档转换为图片的时候,报出了下面的错误: java.lang.OutOfMemoryError: Java heap space 从上边的异常信息可以看到,JVM 需要使用的内存已经...

_火狼_
2014/10/04
0
0
深度探讨Java字节代码的操纵方法

本文为IBM工程师成富编写的《Java深度历险》的第一部分Java字节代码的操纵,像这样Java语言的深度理解和运用还没有很多文章,我们把他奉献给读者,希望读者们喜欢。 51CTO编者按:我们曾给大...

mj4738
2011/11/02
0
0
fabric-sdk-java 1.4安装说明

Hyperledger Fabric Java SDK是开发基于Hyperledger Fabric区块链的Java应用之必备开发包。本文将介绍如何在Maven、Gradle和Eclipse中安装使用最新1.4版本的Hyperledger Fabric Java SDK。 ...

汇智网教程
04/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

tornadofx动画演示分钱问题,多种方法

import javafx.animation.AnimationTimerimport javafx.collections.FXCollectionsimport javafx.scene.paint.Colorimport javafx.scene.shape.Rectangleimport javafx.util.Duratio......

oschina4cyy
20分钟前
0
0
Bootstrap(四)列表与代码

列表 无序列表 <ul> <li>...</li></ul> 有序列表 <ol> <li>...</li></ol> 去点列表 <ul class="list-unstyled"> <li>...</li></ul> 内联列表(列表元素放置于同一行) <ul class="......

ZeroBit
23分钟前
0
0
信必优成功案例 – H3C/CMCC企业项目管理系统

项目背景 •企业项目管理(EPM)系统涵盖了(无线)需求管理、预算管理、立项管理、建设管理、后评估等一系列功能,实现了从预算到建设到项目完成评估阶段的全面覆盖。同时,通过管理流程的电...

symbiochina88
24分钟前
0
0
DevExpress WPF v19.1新版亮点:PDF Viewer等控件新功能

行业领先的.NET界面控件DevExpress 日前正式发布v19.1版本,本站将以连载的形式介绍各版本新增内容。在本系列文章中将为大家介绍DevExpress WPF v19.1中新增的一些控件及部分功能增强,点击下...

FILA6666
25分钟前
0
0
PHP 获取类 / 对象的属性字段及属性值

get_class_vars 获取类的公有属性及默认值(包含公有的静态属性),用来列举类的公有属性字段。 get_object_vars 获取对象的公有属性及属性值(不包含公有的静态属性)。 ReflectionClass 如...

big_cat
27分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部