java springboot 框架下websocket

7 篇文章 0 订阅
1 篇文章 0 订阅

0.pom

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

1.启动器(Application)或者webConfig中

 
/**
 * 如果不是spring boot项目,那就不需要进行这样的配置,因为如果在tomcat中运行的话,tomcat会扫描带有@ServerEndpoint的注解成为websocket,而spring boot项目中需要由这个bean来提供注册管理。
 * @return
 */
@Bean
public ServerEndpointExporter serverEndpointExporter() {
    return new ServerEndpointExporter();
}


2.服务器端

 
package com.uniview.gdp.websocket;

import com.fasterxml.jackson.core.type.TypeReference;
import com.uniview.gdp.utils.JacksonUtil;
import org.springframework.beans.factory.annotation.Autowired;
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.HashMap;
import java.util.Map;


@Component
/**
   * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
   * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
   * 使用websocket的核心,就是一系列的websocket注解,@ServerEndpoint是注册在类上面开启。  
*/
@ServerEndpoint("/websocket/{user}")
public class websocket {
    private static String user;
    //连接时执行
    @OnOpen
    public void onOpen(@PathParam("user") String user, Session session) throws IOException {
        System.out.println("新连接:" + user);
    }

    //关闭时执行
    @OnClose
    public void onClose(){
        System.out.println(user+" is close");
    }

    //收到消息时执行
    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        System.out.println("来自客户端的消息:" + message);
       /* Map<String,Object> result = new HashMap<>();
        result.put("message", message);
        session.getBasicRemote().sendText(JacksonUtil.mapToJSon(result));*/
       // websocket sesion发送消息
        //通过这两个方法 可以实现服务器主动推送
        session.getBasicRemote().sendText(message);
        session.getAsyncRemote().sendText(message);
        /*session.close();*/
    }

    //连接错误时执行
    @OnError
    public void onError(Session session, Throwable error){
        System.out.println("用户id为:{}的连接发送错误"+this.user);
        error.printStackTrace();
    }
}

3.html页面
 
<!DOCTYPE HTML>
<html>
<head>
    <title>首页</title>
    <script type="text/javascript">
        var websocket = null;
        function startWebSocket(){
            //判断当前浏览器是否支持WebSocket
            if('WebSocket' in window){
                //访问路径  端口号+定义的websocket地址
                websocket = new WebSocket("ws://localhost:8080/websocket/333");
                console.log("link success")
            }else{
                alert('Not support websocket')
            }

            //连接发生错误的回调方法
            websocket.onerror = function(){
                setMessageInnerHTML("error");
            };

            //连接成功建立的回调方法
            websocket.onopen = function(event){
                setMessageInnerHTML("open");
            }
            console.log("-----")
            //接收到消息的回调方法
            websocket.onmessage = function(event){
                setMessageInnerHTML(event.data);
            }

            //连接关闭的回调方法
            websocket.onclose = function(){
                setMessageInnerHTML("close");
            }

            //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
            window.onbeforeunload = function(){
                websocket.close();
            }
        }

        //将消息显示在网页上
        function setMessageInnerHTML(innerHTML){
            document.getElementById('message').innerHTML += innerHTML + '<br/>';
        }

        //关闭连接
        function closeWebSocket(){
            websocket.close();
        }

        //发送消息
        function send(){
            var message = document.getElementById('text').value;
            websocket.send(message);
        }
    </script>
</head>
<body>
<section class="Hui-article-box">
    <nav class="breadcrumb"><i class="Hui-iconfont"></i> webSocket
        <a class="btn btn-success radius r" style="line-height:1.6em;margin-top:3px"
           href="javascript:location.replace(location.href);" title="刷新"><i class="Hui-iconfont"></i></a>
    </nav>
    <div class="Hui-article">
        <article class="cl pd-20">
            websocket Demo---- user000 <br />
            <input id="text" type="text" />
            <button οnclick="startWebSocket()"> connect </button>
            <button οnclick="send()"> Send </button>
            <button   οnclick="closeWebSocket()"> Close </button>
            <div id="message">   </div>
        </article>
    </div>
</section>
<script>
</script>
</body>
</html>

4.控制器

@GetMapping("/webSocket")
public String webSocket(){
    return "internal/system/webSocket";
}



springboot使用websocket时,打成war包,发布到服务器,项目启动报错问题

如果用外置 tomcat ,要注释掉以下代码,否则启动项目会报错,用 springboot 内置 tomcat 就得放开以下代码
@Bean
public ServerEndpointExporter serverEndpointExporter() {
      return new ServerEndpointExporter();
 }



websocket通信failed to execute 'send'问题的解决

在建立web socket通信后,发送数据时,出现下图所示现象: 
websocket error

问题代码演示
function TestSockets() {
    //实例化一个WebSocket对象
    var socket = new WebSocket("ws://127.0.0.1:8000/ws");
    //声明一个消息
    var message = {
        nickname: "benben_2015",
        email: "123456@qq.com",
        content: "I love programming"
    };
    //web sockets只能通过连接发送纯文本数据,所以对于复杂的数据结构,在通过连接发送之前,必须进行序列化。
    socket.send(JSON.stringify(message));
}

要明白这个问题产生的原因,就需要了解websocket的几个状态。通常在实例化一个websocket对象之后,客户端就会与服务器进行连接。但是连接的状态是不确定的,于是用readyState属性来进行标识。它有四个值,分别对应不同的状态:

  • CONNECTING:值为0,表示正在连接;
  • OPEN:值为1,表示连接成功,可以通信了;
  • CLOSING:值为2,表示连接正在关闭;
  • CLOSED:值为3,表示连接已经关闭,或者打开连接失败。

这样问题的原因就很明显了,之所以数据不能发送出去,是因为websocket还处在“CONNECTING”状态下,连接还没有成功。

解决办法

只要在函数中添加对状态的判断,在状态为OPEN时,执行send方法即可。方法一代码如下:

function TestSockets() {
    var socket = new WebSocket("ws://127.0.0.1:8000/ws");
    var message = {
        nickname: "benben_2015",
        email: "123456@qq.com",
        content: "I love programming"
    };
    //添加状态判断,当为OPEN时,发送消息
    if (socket.readyState===1) {
        socket.send(JSON.stringify(message));
    }else{
        //do something
    }
}

也可以设置事件监听,当为OPEN时,执行send操作。方案二代码如下:

function TestSockets() {
    var socket = new WebSocket("ws://127.0.0.1:8000/ws");
    var message = {
        nickname: "benben_2015",
        email: "123456@qq.com",
        content: "I love programming"
    };
    message = JSON.stringify(message);
    //添加事件监听
    socket.addEventListener('open', function () {
        socket.send(message)
    });
}

实例对象websocket的onopen属性,可以用来指定连接成功后的回调函数。方案三代码如下:

function TestSockets() {
    var socket = new WebSocket("ws://127.0.0.1:8000/ws");
    //设置连接成功后的回调函数
    socket.onopen=function () {
        console.log("socket has been opened");
        var message = {
            nickname: "benben_2015",
            email: "123456@qq.com",
            content: "I love programming"
        };
        message = JSON.stringify(message);
        socket.send(message);
    };
}

转载文章:https://blog.csdn.net/benben_2015/article/details/79294547
https://blog.csdn.net/qq_18649209/article/details/79529434


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值