【从0开始Web开发实战】Spring Boot集成WebSocket,详细代码手把手操做

目录:
css

一,Spring Boot集成WebSockethtml

二,声明WebSocket服务,发送接收消息前端

三,JavaScript建立WebSocket客户端java

四,增长SocketController,返回前端页面jquery

五,Spring Boot集成TioWebSocketgit

六,常见问题和解决方法github


WebSocket是创建在TCP协议上的全双工通讯链接。不一样于HTTP只能有客户端发送请求消息,WebSocket在客户端和后台服务创建链接后,双方均可以主动发送实时消息。web

image.png

在不少业务场景下,后台服务须要实时将数据推送到客户端,好比代驾定位系统,司机客户端定时发送位置信息到服务器,后台管理系统页面实时更新显示,这时就要使用WebSocket数据推送方式,并且不增长服务器负载压力。spring

image.png

项目下载:https://github.com/jextop/StarterApi浏览器

示例代码:https://github.com/rickding/HelloJava/tree/master/HelloSocket



代码文件

功能要点

Spring Boot集成WebSocket

pom.xml

引入WebSocket依赖spring-boot-starter-websocket

SocketConfig.java

配置Bean,启动WebSocketServer

SocketServer.java

声明WebSocket服务,接收和发送消息

JavaScript建立WebSocket客户端

socket.html

在前端页面中接收和发送消息

前端页面

SocketController.java

返回前端页面

一,Spring Boot集成WebSocket

1. 新建Spring Boot项目时,选中WebSocket,将自动添加依赖。

image.png

2. 已有Spring Boot项目,能够在pom.xml中直接引用WebSocket Starter

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

3. 增长SocketConfig.java,启动WebSocketServer

@Configuration
public class SocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

二,声明WebSocket服务,接收和发送消息

1,增长SocketServer.java,声明服务地址

2,声明@OnMessage,接收消息

3,声明@OnOpen,客户端链接成功时,将session保存起来

4,声明@OnClose,客户端断开链接时,将session信息删除

5,封装sendMessage()函数,经过session推送消息到客户端

@ServerEndpoint("/ws/{uid}")
@Component
public class SocketServer {
    private static ConcurrentHashMap<String, SocketServer> webSocketMap = new ConcurrentHashMap<>();

    private Session session;
    private String uid;

    public static void sendMessage(String uid, String msg) {
        System.out.printf("Send message: %s, %s\n", uid, msg);
        if (StringUtils.isNotBlank(uid) && webSocketMap.containsKey(uid)) {
            webSocketMap.get(uid).sendMessage(msg);
        } else {
            System.err.printf("Offline: %s\n", uid);
        }
    }

    public void sendMessage(String msg) {
        try {
            session.getBasicRemote().sendText(msg);
        } catch (IOException e) {
            System.err.println(e.getMessage());
        }
    }

    @OnMessage
    public void onMessage(String msg, Session session) {
        System.out.printf("Receive message: %s, %s, %s\n", uid, session.getId(), msg);

        for (String uid : webSocketMap.keySet()) {
            sendMessage(uid, String.format("%s消息: %s", uid.equals(this.uid) ? "本身" : "转发", msg));
        }
    }

    @OnOpen
    public void onOpen(Session session, @PathParam("uid") String uid) {
        this.session = session;
        this.uid = uid;

        webSocketMap.put(uid, this);
        System.out.printf("Online: %d, %s\n", webSocketMap.size(), uid);
        sendMessage("链接成功");
    }

    @OnClose
    public void onClose() {
        webSocketMap.remove(uid);
        System.out.printf("Offline 1, %s, online: %d\n", uid, webSocketMap.size());
    }
}

三,JavaScript建立WebSocket客户端

1,判断浏览器是否支持WebSocket

2,建立客户端,链接服务器

3,增长消息接收函数

4,增长发送消息功能

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>HelloSocket</title>
</head>

<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script>
    var socket;

    function openSocket() {
        if (typeof(WebSocket) === "undefined") {
            $("#status").html("浏览器不支持WebSocket");
        } else {
            if (socket !== undefined) {
                socket.close();
                socket = undefined;
            }

            // 创建链接
            var socketUrl = "ws://localhost:8080/ws/" + $("#uid").val();
            socket = new WebSocket(socketUrl);
            socket.onmessage = function (msg) {
                $("#status").html(msg.data);
            };
        }
    }

    function sendMessage() {
        if (socket === undefined) {
            $("#status").html("请先链接Socket");
        } else {
            socket.send($("#msg").val() + ", " + new Date().getTime());
        }
    }
</script>

<body>
${msg}
<br/>uid: <div><input id="uid" name="uid" value="user_id"></div>
<br/>msg: <div><input id="msg" name="msg" value="Hello WebSocket"></div>

<br/>
<div>
    <button onclick="openSocket()">链接Socket</button>
</div>
<br/>
<div>
    <button onclick="sendMessage()">发送消息</button>
</div>

<br/>
<div><label id="status">Status</label></div>
</body>
</html>

四,增长SocketController,返回前端页面

@Controller
public class SocketController {
    @RequestMapping("/ws")
    public String ws(Model model){
        model.addAttribute("msg","Web Socket!");
        return "socket";
    }
}

启动项目,浏览器打开页面,链接WebSocket服务,接收和发送消息。

image.png

五,Spring Boot集成TioWebSocket

tio-websocket是基于T-io 网络通信框架实现的开源websocket服务器,易于使用,没必要关心链接的维护问题,只要作好业务处理便可。


代码文件

功能要点

Spring Boot集成TioWebSocket

pom.xml

引入TioWebSocket依赖tio-websocket-spring-boot-starter

application.xml

配置端口、超时等属性

TioMsgHandler.java

实现IWsMsgHandler,接收和发送消息

JavaScript建立WebSocket客户端

tio.html

在前端页面中接收和发送消息

前端页面

SocketController.java

返回前端页面

1,pom.xml中引入依赖

<dependency>
   <groupId>org.t-io</groupId>
   <artifactId>tio-websocket-spring-boot-starter</artifactId>
   <version>3.6.0.v20200315-RELEASE</version>
</dependency>

2,在application.xml中配置端口、超时等属性

tio:
  websocket:
    server:
      port: 8200
      heartbeat-timeout: 3600000

3,增长TioMsgHandler.java,实现接收和发送消息功能

@Component
public class TioMsgHandler implements IWsMsgHandler {
    @Autowired
    private TioWebSocketServerBootstrap tioServer;

    public void sendMessage(String msg) {
        Tio.sendToAll(tioServer.getServerTioConfig(), WsResponse.fromText(msg, "utf-8"));
    }

    @Override
    public Object onText(WsRequest wsRequest, String msg, ChannelContext channelContext) throws Exception {
        System.out.printf("收到文本消息:%s\n", msg);

        sendMessage(String.format("转发消息: %s", msg));
        return String.format("收到消息: %s", msg);
    }

    @Override
    public Object onBytes(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
        System.out.printf("收到二进制数据:%d\n", bytes.length);
        return null;
    }
}

4,开发前端页面,JavaScript建立WebSocket客户端

5,SocketController.java返回前端页面

6,启动项目,看到WebSocket服务信息

image.png

六,常见问题和解决方法

运行单元测试时错误,不能建立Bean 'serverEndpointExporter'

IllegalStateException: javax.websocket.server.ServerContainer not available


解决:声明@SpringBootTest时指定webEnvironment参数。

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)


缘由:WebSocket运行在servlet容器中,因此须要加载servlet容器。

webEnvironment为Spring Boot指定启动时的ApplicationContext, SpringBootTest.WebEnvironment.DEFINED_PORT表示内嵌的服务器将会在定义的端口启动。


运行单元测试时不能启动,Failed to load ApplicationContext

Web server failed to start. Port 8011 was already in use.

解决:服务端口被占用,若是项目已经启动,先停掉再运行测试。

相关文章
相关标签/搜索