偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

全棧實戰(zhàn)!用 WebSocket 實現(xiàn)實時消息推送 + 動態(tài)進度條可視化

開發(fā) 前端
借助 WebSocket 實現(xiàn)的實時通信機制,我們有效地解決了輪詢帶來的性能瓶頸和用戶體驗問題。無論是消息推送,待辦提醒,還是任務(wù)進度的動態(tài)刷新,WebSocket 都提供了更優(yōu)雅與高效的解決方案。

在傳統(tǒng) Web 應(yīng)用中,任務(wù)狀態(tài)查詢或通知推送往往依賴前端定時輪詢接口獲取數(shù)據(jù)。雖然這種方式實現(xiàn)簡單,但在數(shù)據(jù)頻繁變化或用戶量激增的場景下,頻繁的 HTTP 請求會引起數(shù)據(jù)庫壓力增大,響應(yīng)延遲甚至系統(tǒng)性能下降。

本文將基于 Spring Boot + WebSocket 的技術(shù)棧,構(gòu)建一個服務(wù)端主動推送消息的實時提醒系統(tǒng),并可視化每項任務(wù)的進度。前端將通過 WebSocket 進行一次性連接,并實時響應(yīng)后端推送的最新數(shù)據(jù),從而極大提升用戶體驗與系統(tǒng)性能。

系統(tǒng)功能概覽

  • 待辦數(shù)量實時推送
  • 通知紅點自動刷新
  • 支持 WebSocket 持久連接
  • 動態(tài)進度條展示任務(wù)完成情況
  • 前后端獨立交互,解耦式開發(fā)結(jié)構(gòu)

依賴配置(Maven)

添加必要的依賴于 pom.xml 文件中:

<!-- MyBatis Plus & MySQL -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.2</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>


<!-- WebSocket -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
    <version>2.1.6.RELEASE</version>
</dependency>

數(shù)據(jù)庫結(jié)構(gòu)設(shè)計

建立兩張表用于模擬待辦任務(wù)及其子任務(wù)進度:

CREATE TABLE t_todo (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  user_name VARCHAR(255) COMMENT '用戶名稱',
  name VARCHAR(255) COMMENT '待辦標題'
) COMMENT='待辦任務(wù)主表';


CREATE TABLE t_todo_attr (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  todo_id BIGINT COMMENT '主表ID',
  status INT COMMENT '完成狀態(tài) 1為已完成'
) COMMENT='待辦任務(wù)進度子表';

一條 t_todo 記錄表示一個任務(wù),對應(yīng)若干 t_todo_attr 子任務(wù)進度項。

WebSocket 服務(wù)端配置

WebSocket 注冊配置

// /src/main/java/com/icoderoad/config/WebSocketConfig.java
@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

實現(xiàn)主任務(wù)通知服務(wù)

// /src/main/java/com/icoderoad/ws/WebSocketTodoServer.java
@ServerEndpoint("/ws/todo/{username}")
@Component
public class WebSocketTodoServer {
    private static final Map<String, Session> sessions = new ConcurrentHashMap<>();


    @OnOpen
    public void open(Session session, @PathParam("username") String username) {
        sessions.put(username, session);
        int count = SpringContextUtil.getBean(TodoService.class)
                .count(new LambdaQueryWrapper<Todo>().eq(Todo::getUserName, username));
        send(session, String.valueOf(count));
    }


    @OnClose
    public void close(@PathParam("username") String username) {
        sessions.remove(username);
    }


    @OnMessage
    public void message(String msg) {}


    @OnError
    public void error(Session session, Throwable throwable) {
        throwable.printStackTrace();
    }


    public void sendInfo(String username, String msg) {
        Session session = sessions.get(username);
        send(session, msg);
    }


    private void send(Session session, String msg) {
        if (session != null) {
            synchronized (session) {
                try {
                    session.getBasicRemote().sendText(msg);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

后端接口實現(xiàn)

// /src/main/java/com/icoderoad/controller/TodoController.java
@RestController
@RequestMapping("/todo")
public class TodoController {


    @Autowired private TodoService todoService;
    @Autowired private WebSocketTodoServer wsServer;


    @PostMapping("/insert")
    public ResponseUtils insert(@RequestParam String todoName, @RequestParam String userName) {
        Todo todo = new Todo();
        todo.setName(todoName);
        todo.setUserName(userName);
        todoService.save(todo);


        int count = todoService.count(new LambdaQueryWrapper<Todo>().eq(Todo::getUserName, userName));
        wsServer.sendInfo(userName, String.valueOf(count));


        return ResponseUtils.success(todoName);
    }


    @GetMapping("/list")
    public ResponseUtils list(@RequestParam String userName) {
        List<Todo> todos = todoService.list(new LambdaQueryWrapper<Todo>().eq(Todo::getUserName, userName));
        return ResponseUtils.success(todos);
    }
}

前端頁面展示

<!-- /src/main/resources/static/index.html -->
<div class="message-container" onclick="toggleTodo()">
    <div class="bell-icon"></div>
    <span class="message-count">0</span>
</div>
<div class="todo-section" id="todoSection" style="display:none;"></div>


<script>
    const socket = new WebSocket('ws://localhost:8077/ws/todo/張三');
    socket.onmessage = (event) => {
        document.querySelector('.message-count').textContent = event.data;
    };


    async function toggleTodo() {
        const section = document.getElementById('todoSection');
        section.style.display = section.style.display === 'none' ? 'block' : 'none';
        if (section.style.display === 'block') {
            const res = await fetch('/todo/list?userName=張三');
            const data = await res.json();
            section.innerHTML = data.data.map(t => `<div>${t.name}</div>`).join('');
        }
    }
</script>

子任務(wù)進度 WebSocket(進度條)

// /src/main/java/com/icoderoad/ws/WebSocketTodoAttrServer.java
@ServerEndpoint("/ws/todo/attr/{todoId}")
@Component
public class WebSocketTodoAttrServer {
    private static final Map<String, Session> attrSessions = new ConcurrentHashMap<>();


    @OnOpen
    public void onOpen(Session session, @PathParam("todoId") String todoId) {
        attrSessions.put(todoId, session);
        String progress = SpringContextUtil.getBean(TodoAttrService.class).progress(Long.valueOf(todoId));
        send(session, progress);
    }


    public void sendInfo(String todoId, String msg) {
        send(attrSessions.get(todoId), msg);
    }


    private void send(Session session, String msg) {
        try {
            if (session != null) session.getBasicRemote().sendText(msg);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

任務(wù)進度更新接口

// /src/main/java/com/icoderoad/controller/TodoAttrController.java
@PostMapping("/attr/update")
public ResponseUtils updateAttr(@RequestParam Long id) {
    todoAttrService.updateById(new TodoAttr(id, 1));
    TodoAttr attr = todoAttrService.getById(id);
    webSocketTodoAttrServer.sendInfo(String.valueOf(attr.getTodoId()),
            todoAttrService.progress(attr.getTodoId()));
    return ResponseUtils.success();
}

結(jié)語:高性能實時系統(tǒng)構(gòu)建的利器

借助 WebSocket 實現(xiàn)的實時通信機制,我們有效地解決了輪詢帶來的性能瓶頸和用戶體驗問題。無論是消息推送,待辦提醒,還是任務(wù)進度的動態(tài)刷新,WebSocket 都提供了更優(yōu)雅與高效的解決方案。

未來在構(gòu)建具有實時性要求的系統(tǒng)(如 IM 聊天、實時告警、系統(tǒng)監(jiān)控等)時,WebSocket 可以作為首選的通信技術(shù)基礎(chǔ),而非傳統(tǒng)的“輪詢 + 回調(diào)”。

責(zé)任編輯:武曉燕 來源: 路條編程
相關(guān)推薦

2023-12-27 13:45:00

Python進度條代碼

2024-09-02 09:31:19

2024-08-06 14:29:37

2009-08-17 14:41:47

C#進度條實現(xiàn)

2009-08-17 17:15:48

C# 進度條效果

2021-09-27 08:31:01

數(shù)據(jù)可視化柱狀圖折現(xiàn)圖

2015-07-31 11:19:43

數(shù)字進度條源碼

2023-12-11 17:15:05

應(yīng)用開發(fā)波紋進度條ArkUI

2024-06-13 08:15:00

2013-04-12 10:05:49

HTML5WebSocket

2023-11-17 09:35:58

2021-09-27 10:43:18

鴻蒙HarmonyOS應(yīng)用

2009-08-17 15:48:47

C# WinForm進

2021-02-05 07:28:11

SpringbootNettyWebsocke

2017-10-14 13:54:26

數(shù)據(jù)可視化數(shù)據(jù)信息可視化

2009-07-21 14:49:55

XmlHttpRequ文件上傳進度條

2023-11-30 11:38:29

CSS網(wǎng)頁進度條

2011-07-05 15:16:00

QT 進度條

2024-07-25 08:55:47

進度條水缸進度動畫效果

2022-05-16 09:34:17

Python可視化圖表
點贊
收藏

51CTO技術(shù)棧公眾號