WebSocket初体验之JavaWeb 实时显示文件处理进度

最近天需要做这么个业务:文件解析处理,要能够看到解析进度。

原因:
当点击按钮后,后端在跑代码,前端页面只有一个等待遮罩转圈,并不知道处理到哪一步,只能默默地等待,客户反馈不爽。

查资料:
针对文件解析进度,b/s模式的应用网上给出的方案很少,最让人不爽的是千篇一律的copy。(不知道谁copy谁的,找资料很难)(ps:copy之余能不能不要一个字不落的全copy,还不加任何修饰,让后来者怎么看??)

解决方案:
在知识海洋中,找到两种觉得可行的方案,一个是ajax轮询(太耗资源,pass),另一个便是webSocket建立一个全双工通讯的通道,能够让客户端和服务器之间进行相互通信,既客户端可以实时地接收服务器的消息。

WebSocket概述
(摘自菜鸟教程https://www.runoob.com/html/html5-websocket.html)
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

话不多说,上代码
1.添加webSocket依赖

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

2.注入ServerEndpointExporter

@Configuration
public class WebSocketConfig {

    /**
   	 * 这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint。
     * 要注意,如果使用独立的servlet容器,而不是直接使用springboot的内置容器,
     * 就不要注入ServerEndpointExporter,因为它将由容器自己提供和管理
     * 
     * 当使用这个类时,通过在Spring配置中声明它,
     * 应该可以关闭Servlet容器对WebSocket端点的扫描
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}

3.WebSocket 服务

@Slf4j
@ServerEndpoint("/websocket")
@Component
public class WebSocketServer {
    //concurrent包的线程安全set,用来存放每个客户端对应的MyWebSocket
    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet
            = new CopyOnWriteArraySet<>();
    //与某个客户端的连接会话,通过session传递消息
    private Session session;

    //建立连接成功的回调
    @OnOpen
    public void open(Session session) {
        this.session = session;
        webSocketSet.add(this);
        log.info("连接成功");
        //sendMessage("连接成功");
    }

    //连接关闭的回调
    @OnClose
    public void close(){
        webSocketSet.remove(this);
        log.info("连接关闭");
    }

    //发生错误的回调
    @OnError
    public void error(Session session,Throwable err){
        this.session = session;
        log.error("连接错误");
        err.printStackTrace();
    }

    //收到客户端消息后的回调
    @OnMessage
    public void message(Session session,String message) throws IOException {
        this.session = session;
        log.info("收到来自窗口的信息: " + message);
        for (WebSocketServer item : webSocketSet) {
            item.sendMessage(message);
        }
    }

    //服务器主动发消息
    private void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    public static void sendInfo(String message) throws IOException {
        for (WebSocketServer item : webSocketSet) {
            item.sendMessage(message);
        }
    }
}

4.在代码中,如同log.info()般使用方法

WebSocketServer.sendInfo("共有 " + fileListSize + " 个文件<br/>正在操作第 " + i + " 个文件");

5.js发起连接与断开连接

$("#query").click(function () {
            var socket = new WebSocket("ws://localhost:8033/GK/websocket");
            socket.onopen = function () {
                console.log("socket已打开")
            };
            socket.onmessage = function (event) {
                //$(".test").innerText = ;
                $(".test").html(event.data);
                console.log(event.data);
            };
            socket.onclose = function () {
                $(".test").html("文件处理完成");
                console.log("socket已关闭");
                //$(".test").html("");
            };
            $.ajax({
                url: contextpath + "/getUpar",    //请求的url地址
                async: true,//请求是否异步,默认为异步,这也是ajax重要特性
                type: "POST",   //请求方式
                data: obj,
                success: function (date) {
                	//webSocket关闭
                    socket.close();
                    $('#shade').hide();
                    $('#s-loading').hide();
                    $("#query").prop("disabled", false);
                    //请求成功 时处理
                    layer.msg(date.msg);
                },
                error: function () {
               		//webSocket关闭
                    socket.close();
                    $('#shade').hide();
                    $('#s-loading').hide();
                    $("#query").prop("disabled", false);
                    //请求出错处理
                    layer.msg("生成文件报错")
                }
            });
        });

6.效果图
在这里插入图片描述
在这里插入图片描述
这里只做了简答的使用,如有问题或更好的知识,希望读者评论分享。

展开阅读全文
©️2020 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值