欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot實現(xiàn)實時彈幕的示例代碼

 更新時間:2025年06月05日 08:39:35   作者:風(fēng)象南  
實時彈幕系統(tǒng)已成為現(xiàn)代視頻網(wǎng)站和直播平臺的標準功能,它讓觀眾可以在觀看視頻時發(fā)送即時評論,本文將介紹如何使用SpringBoot構(gòu)建一個實時彈幕系統(tǒng),需要的可以了解下

實時彈幕系統(tǒng)已成為現(xiàn)代視頻網(wǎng)站和直播平臺的標準功能,它讓觀眾可以在觀看視頻時發(fā)送即時評論,這些評論會以橫向滾動的方式顯示在視頻畫面上,增強了用戶的互動體驗和社區(qū)參與感。

本文將介紹如何使用SpringBoot構(gòu)建一個實時彈幕系統(tǒng)。

效果展示

一、實時彈幕系統(tǒng)概述

1.1 什么是彈幕系統(tǒng)

彈幕系統(tǒng)允許用戶發(fā)送的評論直接顯示在視頻畫面上,這些評論會從右向左橫向滾動。

1.2 彈幕系統(tǒng)特點

實時性:用戶發(fā)送的彈幕幾乎立即顯示在所有觀看者的屏幕上

互動性:觀眾可以直接"看到"其他人的反應(yīng),形成集體觀看體驗

時間關(guān)聯(lián)性:彈幕通常與視頻的特定時間點關(guān)聯(lián)

視覺沖擊力:大量彈幕同時出現(xiàn)會形成獨特的視覺效果

二、技術(shù)設(shè)計

2.1 整體架構(gòu)

我們將構(gòu)建的彈幕系統(tǒng)包括以下主要組件:

1. 前端播放器:負責(zé)視頻播放和彈幕展示

2. WebSocket服務(wù):處理實時彈幕消息的傳遞

3. 彈幕存儲:保存歷史彈幕記錄

4. 內(nèi)容過濾組件:過濾不良內(nèi)容

2.2 通信協(xié)議選擇

實現(xiàn)實時彈幕系統(tǒng),我們需要選擇一個適合的通信協(xié)議。主要選項包括:

協(xié)議優(yōu)點缺點適用場景
WebSocket全雙工通信,低延遲,廣泛支持需要服務(wù)器保持連接,資源消耗較大實時性要求高的場景
SSE (Server-Sent Events)服務(wù)器推送,簡單實現(xiàn)只支持服務(wù)器到客戶端的單向通信服務(wù)器推送更新場景
長輪詢 (Long Polling)兼容性好,實現(xiàn)簡單效率低,延遲高兼容性要求高的場景

此處選擇WebSocket進行實現(xiàn)。

三、使用SpringBoot實現(xiàn)WebSocket服務(wù)

3.1 添加依賴

首先,在pom.xml中添加相關(guān)依賴:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.4.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>cm</groupId>
    <artifactId>springboot-danmaku</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- WebSocket -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
            <version>3.5.5</version>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>21</source>
                    <target>21</target>
                    <encoding>utf-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>3.2.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

3.2 WebSocket配置

創(chuàng)建WebSocket配置類:

package com.example.danmaku.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        // 啟用簡單的消息代理,用于將消息返回給客戶端
        config.enableSimpleBroker("/topic");
        // 設(shè)置應(yīng)用程序前綴
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // 注冊STOMP端點,客戶端通過這個端點連接到WebSocket服務(wù)器
        registry.addEndpoint("/ws-danmaku")
                .setAllowedOriginPatterns("*")
                .withSockJS(); // 啟用SockJS fallback選項
    }
}

3.3 定義彈幕消息模型

使用MyBatis-Plus實體定義:

@Data
@TableName("danmaku")
public class Danmaku {
    
    @TableId(type = IdType.AUTO)
    private Long id;
    
    @TableField(value = "content", strategy = FieldStrategy.NOT_EMPTY)
    private String content;  // 彈幕內(nèi)容
    
    @TableField("color")
    private String color;    // 彈幕顏色
    
    @TableField("font_size")
    private Integer fontSize; // 字體大小
    
    @TableField("time")
    private Double time;     // 視頻時間點
    
    @TableField("video_id")
    private String videoId;  // 關(guān)聯(lián)的視頻ID
    
    @TableField("user_id")
    private String userId;   // 發(fā)送用戶ID
    
    @TableField("username")
    private String username; // 用戶名
    
    @TableField("created_at")
    private LocalDateTime createdAt; // 創(chuàng)建時間
}

3.4 彈幕消息傳輸對象

@Data
public class DanmakuDTO {
    private String content;
    private String color = "#ffffff"; // 默認白色
    private Integer fontSize = 24;    // 默認字體大小
    private Double time;
    private String videoId;
    private String userId;
    private String username;
}

3.5 定義Mapper接口

@Mapper
public interface DanmakuMapper extends BaseMapper<Danmaku> {
    
    /**
     * 根據(jù)視頻ID查詢所有彈幕,按時間排序
     */
    @Select("SELECT * FROM danmaku WHERE video_id = #{videoId} ORDER BY time ASC")
    List<Danmaku> findByVideoIdOrderByTimeAsc(@Param("videoId") String videoId);
    
    /**
     * 根據(jù)視頻ID和時間范圍查詢彈幕
     */
    @Select("SELECT * FROM danmaku WHERE video_id = #{videoId} AND time BETWEEN #{startTime} AND #{endTime} ORDER BY time ASC")
    List<Danmaku> findByVideoIdAndTimeBetween(
            @Param("videoId") String videoId, 
            @Param("startTime") Double startTime, 
            @Param("endTime") Double endTime);
}

3.6 彈幕服務(wù)

@Service
public class DanmakuService {
    
    private final DanmakuMapper danmakuMapper;
    private final SimpMessagingTemplate messagingTemplate;
    
    @Autowired
    public DanmakuService(DanmakuMapper danmakuMapper, SimpMessagingTemplate messagingTemplate) {
        this.danmakuMapper = danmakuMapper;
        this.messagingTemplate = messagingTemplate;
    }
    
    /**
     * 保存并發(fā)送彈幕
     */
    public Danmaku saveDanmaku(DanmakuDTO danmakuDTO) {
        // 內(nèi)容過濾(簡單示例)
        String filteredContent = filterContent(danmakuDTO.getContent());
        
        // 創(chuàng)建彈幕實體
        Danmaku danmaku = new Danmaku();
        danmaku.setContent(filteredContent);
        danmaku.setColor(danmakuDTO.getColor());
        danmaku.setFontSize(danmakuDTO.getFontSize());
        danmaku.setTime(danmakuDTO.getTime());
        danmaku.setVideoId(danmakuDTO.getVideoId());
        danmaku.setUserId(danmakuDTO.getUserId());
        danmaku.setUsername(danmakuDTO.getUsername());
        danmaku.setCreatedAt(LocalDateTime.now());
        
        // 保存到數(shù)據(jù)庫
        danmakuMapper.insert(danmaku);
        
        // 通過WebSocket發(fā)送到客戶端
        messagingTemplate.convertAndSend("/topic/video/" + danmaku.getVideoId(), danmaku);
        
        return danmaku;
    }
    
    /**
     * 獲取視頻的所有彈幕
     */
    public List<Danmaku> getDanmakusByVideoId(String videoId) {
        return danmakuMapper.findByVideoIdOrderByTimeAsc(videoId);
    }
    
    /**
     * 獲取指定時間范圍內(nèi)的彈幕
     */
    public List<Danmaku> getDanmakusByVideoIdAndTimeRange(
            String videoId, Double startTime, Double endTime) {
        return danmakuMapper.findByVideoIdAndTimeBetween(videoId, startTime, endTime);
    }
    
    /**
     * 簡單的內(nèi)容過濾實現(xiàn)
     */
    private String filterContent(String content) {
        // 實際應(yīng)用中這里可能會有更復(fù)雜的過濾邏輯
        String[] sensitiveWords = {"敏感詞1", "敏感詞2", "敏感詞3"};
        String filtered = content;
        
        for (String word : sensitiveWords) {
            filtered = filtered.replaceAll(word, "***");
        }
        
        return filtered;
    }
}

3.7 彈幕控制器

package com.example.danmaku.controller;

import com.example.danmaku.dto.DanmakuDTO;
import com.example.danmaku.model.Danmaku;
import com.example.danmaku.service.DanmakuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/danmaku")
public class DanmakuController {
    
    private final DanmakuService danmakuService;
    
    @Autowired
    public DanmakuController(DanmakuService danmakuService) {
        this.danmakuService = danmakuService;
    }
    
    /**
     * 發(fā)送彈幕
     */
    @MessageMapping("/danmaku/send")
    public Danmaku sendDanmaku(DanmakuDTO danmakuDTO) {
        return danmakuService.saveDanmaku(danmakuDTO);
    }
    
    /**
     * 獲取視頻的所有彈幕(REST API)
     */
    @GetMapping("/video/{videoId}")
    public ResponseEntity<List<Danmaku>> getDanmakusByVideoId(@PathVariable String videoId) {
        List<Danmaku> danmakus = danmakuService.getDanmakusByVideoId(videoId);
        return ResponseEntity.ok(danmakus);
    }
    
    /**
     * 獲取指定時間范圍內(nèi)的彈幕(REST API)
     */
    @GetMapping("/video/{videoId}/timerange")
    public ResponseEntity<List<Danmaku>> getDanmakusByTimeRange(
            @PathVariable String videoId,
            @RequestParam Double start,
            @RequestParam Double end) {
        List<Danmaku> danmakus = danmakuService.getDanmakusByVideoIdAndTimeRange(videoId, start, end);
        return ResponseEntity.ok(danmakus);
    }
}

四、前端實現(xiàn)

4.1 HTML和CSS

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>彈幕視頻播放器</title>
    <style>
        #video-container {
            position: relative;
            width: 800px;
            height: 450px;
            margin: 0 auto;
            background-color: #000;
            overflow: hidden;
        }
        
        #video-player {
            width: 100%;
            height: 100%;
        }
        
        #danmaku-container {
            position: absolute;
            transform: translateY( 0;
            left: 0;
            width: 100%;
            height: 100%;
            pointer-events: none; /* 允許點擊穿透到視頻 */
        }
        
        .danmaku {
            position: absolute;
            white-space: nowrap;
            font-family: "Microsoft YaHei", sans-serif;
            font-weight: bold;
            text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
            animation-name: danmaku-move;
            animation-timing-function: linear;
            animation-fill-mode: forwards;
        }
        
        @keyframes danmaku-move {
            from {
                transform: translateX(100%);
            }
            to {
                transform: translateX(-100%);
            }
        }
        
        #danmaku-form {
            margin-top: 20px;
            text-align: center;
        }
        
        #danmaku-input {
            width: 60%;
            padding: 8px;
            border-radius: 4px;
            border: 1px solid #ccc;
        }
        
        #color-picker {
            margin: 0 10px;
        }
        
        #send-btn {
            padding: 8px 16px;
            background-color: #1890ff;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }
        
        #send-btn:hover {
            background-color: #40a9ff;
        }
    </style>
</head>
<body>
    <div id="video-container">
        <video id="video-player" controls>
            <source src="your-video-url.mp4" type="video/mp4">
            Your browser does not support the video tag.
        </video>
        <div id="danmaku-container"></div>
    </div>
    
    <div id="danmaku-form">
        <input type="text" id="danmaku-input" placeholder="發(fā)送彈幕...">
        <input type="color" id="color-picker" value="#ffffff">
        <select id="font-size">
            <option value="18">小</option>
            <option value="24" selected>中</option>
            <option value="30">大</option>
        </select>
        <button id="send-btn">發(fā)送</button>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/sockjs-client@1.5.0/dist/sockjs.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/stompjs@2.3.3/lib/stomp.min.js"></script>
    <script src="danmaku.js"></script>
</body>
</html>

4.2 JavaScript實現(xiàn)

// danmaku.js
document.addEventListener('DOMContentLoaded', function() {
    // 獲取DOM元素
    const videoPlayer = document.getElementById('video-player');
    const danmakuContainer = document.getElementById('danmaku-container');
    const danmakuInput = document.getElementById('danmaku-input');
    const colorPicker = document.getElementById('color-picker');
    const fontSizeSelect = document.getElementById('font-size');
    const sendBtn = document.getElementById('send-btn');
    
    // 視頻ID(實際應(yīng)用中可能從URL或其他地方獲?。?
    const videoId = 'video123';
    
    // 用戶信息(實際應(yīng)用中可能從登錄系統(tǒng)獲取)
    const userId = 'user' + Math.floor(Math.random() * 1000);
    const username = '用戶' + userId.substring(4);
    
    // WebSocket連接
    let stompClient = null;
    
    // 連接WebSocket
    function connect() {
        const socket = new SockJS('/ws-danmaku');
        stompClient = Stomp.over(socket);
        
        stompClient.connect({}, function(frame) {
            console.log('Connected to WebSocket: ' + frame);
            
            // 訂閱當(dāng)前視頻的彈幕頻道
            stompClient.subscribe('/topic/video/' + videoId, function(response) {
                const danmaku = JSON.parse(response.body);
                showDanmaku(danmaku);
            });
            
            // 獲取歷史彈幕
            loadHistoryDanmaku();
        }, function(error) {
            console.error('WebSocket連接失敗: ', error);
            // 嘗試重新連接
            setTimeout(connect, 5000);
        });
    }
    
    // 加載歷史彈幕
    function loadHistoryDanmaku() {
        fetch(`/api/danmaku/video/${videoId}`)
            .then(response => response.json())
            .then(danmakus => {
                // 記錄歷史彈幕,用于播放到相應(yīng)時間點時顯示
                window.historyDanmakus = danmakus;
                console.log(`已加載${danmakus.length}條歷史彈幕`);
            })
            .catch(error => console.error('獲取歷史彈幕失敗:', error));
    }
    
    // 發(fā)送彈幕
    function sendDanmaku() {
        const content = danmakuInput.value.trim();
        if (!content) return;
        
        const danmaku = {
            content: content,
            color: colorPicker.value,
            fontSize: parseInt(fontSizeSelect.value),
            time: videoPlayer.currentTime,
            videoId: videoId,
            userId: userId,
            username: username
        };
        
        stompClient.send('/app/danmaku/send', {}, JSON.stringify(danmaku));
        
        // 清空輸入框
        danmakuInput.value = '';
    }
    
    // 顯示彈幕
    function showDanmaku(danmaku) {
        // 創(chuàng)建彈幕元素
        const danmakuElement = document.createElement('div');
        danmakuElement.className = 'danmaku';
        danmakuElement.textContent = danmaku.content;
        danmakuElement.style.color = danmaku.color;
        danmakuElement.style.fontSize = danmaku.fontSize + 'px';
        
        // 隨機分配軌道(垂直位置)
        const trackHeight = danmaku.fontSize + 5; // 軌道高度
        const maxTrack = Math.floor(danmakuContainer.clientHeight / trackHeight);
        const trackNumber = Math.floor(Math.random() * maxTrack);
        danmakuElement.style.top = (trackNumber * trackHeight) + 'px';
        
        // 計算動畫持續(xù)時間(基于容器寬度)
        const duration = 8 + Math.random() * 4; // 8-12秒
        danmakuElement.style.animationDuration = duration + 's';
        
        // 添加到容器
        danmakuContainer.appendChild(danmakuElement);
        
        // 動畫結(jié)束后移除元素
        setTimeout(() => {
            danmakuContainer.removeChild(danmakuElement);
        }, duration * 1000);
    }
    
    // 視頻時間更新時,顯示對應(yīng)時間點的歷史彈幕
    videoPlayer.addEventListener('timeupdate', function() {
        const currentTime = videoPlayer.currentTime;
        
        // 如果歷史彈幕已加載
        if (window.historyDanmakus && window.lastCheckedTime !== Math.floor(currentTime)) {
            window.lastCheckedTime = Math.floor(currentTime);
            
            // 檢查是否有需要在當(dāng)前時間點顯示的彈幕
            window.historyDanmakus.forEach(danmaku => {
                // 如果彈幕時間點在當(dāng)前時間的±0.5秒內(nèi)且尚未顯示
                if (Math.abs(danmaku.time - currentTime) <= 0.5 && 
                    (!window.displayedDanmakus || !window.displayedDanmakus.includes(danmaku.id))) {
                    
                    // 記錄已顯示的彈幕ID
                    if (!window.displayedDanmakus) {
                        window.displayedDanmakus = [];
                    }
                    window.displayedDanmakus.push(danmaku.id);
                    
                    // 顯示彈幕
                    showDanmaku(danmaku);
                }
            });
        }
    });
    
    // 視頻跳轉(zhuǎn)時重置已顯示彈幕記錄
    videoPlayer.addEventListener('seeking', function() {
        window.displayedDanmakus = [];
    });
    
    // 綁定發(fā)送按鈕點擊事件
    sendBtn.addEventListener('click', sendDanmaku);
    
    // 綁定輸入框回車事件
    danmakuInput.addEventListener('keypress', function(e) {
        if (e.key === 'Enter') {
            sendDanmaku();
        }
    });
    
    // 連接WebSocket
    connect();
});

五、性能優(yōu)化與擴展

5.1 性能優(yōu)化策略

1. 消息壓縮:對WebSocket消息進行壓縮,減少網(wǎng)絡(luò)傳輸量

@Configuration
public class WebSocketMessageConfig implements WebSocketMessageBrokerConfigurer {
    
    @Override
    public void configureWebSocketTransport(WebSocketTransportRegistration registry) {
        // 啟用消息壓縮
        registry.setMessageSizeLimit(128 * 1024) // 消息大小限制,防止大量彈幕導(dǎo)致的內(nèi)存問題
                .setSendBufferSizeLimit(512 * 1024) // 發(fā)送緩沖區(qū)大小限制
                .setSendTimeLimit(15 * 1000); // 發(fā)送超時限制
    }
}

2. 彈幕分頁加載:對于長視頻,分段獲取彈幕數(shù)據(jù)

@GetMapping("/video/{videoId}/paged")
public ResponseEntity<IPage<Danmaku>> getPagedDanmakus(
        @PathVariable String videoId,
        @RequestParam(defaultValue = "0") int page,
        @RequestParam(defaultValue = "100") int size) {
    
    Page<Danmaku> pageParam = new Page<>(page, size);
    QueryWrapper<Danmaku> queryWrapper = new QueryWrapper<Danmaku>()
            .eq("video_id", videoId)
            .orderByAsc("time");
    
    IPage<Danmaku> danmakus = danmakuMapper.selectPage(pageParam, queryWrapper);
    return ResponseEntity.ok(danmakus);
}

3. 前端渲染優(yōu)化:控制同時顯示的彈幕數(shù)量

// 在前端控制最大顯示彈幕數(shù)
const MAX_DANMAKU_COUNT = 100;

// 在showDanmaku函數(shù)中添加限制
function showDanmaku(danmaku) {
    // 檢查當(dāng)前彈幕數(shù)量
    const currentDanmakuCount = document.querySelectorAll('.danmaku').length;
    if (currentDanmakuCount >= MAX_DANMAKU_COUNT) {
        // 如果超過最大數(shù)量,移除最早的彈幕
        const oldestDanmaku = document.querySelector('.danmaku');
        if (oldestDanmaku) {
            oldestDanmaku.remove();
        }
    }
    
    // 原有彈幕顯示邏輯...
}

5.2 彈幕過濾增強

對于敏感內(nèi)容過濾,可以實現(xiàn)更復(fù)雜的過濾系統(tǒng):

@Service
public class ContentFilterService {
    
    private Set<String> sensitiveWords;
    
    @PostConstruct
    public void init() {
        // 從配置文件或數(shù)據(jù)庫加載敏感詞
        sensitiveWords = new HashSet<>();
        sensitiveWords.add("敏感詞1");
        sensitiveWords.add("敏感詞2");
        sensitiveWords.add("敏感詞3");
        // 可以從外部文件加載更多敏感詞
    }
    
    public String filterContent(String content) {
        if (content == null || content.isEmpty()) {
            return content;
        }
        
        String filteredContent = content;
        for (String word : sensitiveWords) {
            filteredContent = filteredContent.replaceAll(word, "***");
        }
        
        return filteredContent;
    }
    
    // 添加敏感詞
    public void addSensitiveWord(String word) {
        sensitiveWords.add(word);
    }
    
    // 移除敏感詞
    public void removeSensitiveWord(String word) {
        sensitiveWords.remove(word);
    }
}

六、完整單機演示

6.1 項目結(jié)構(gòu)

src/
├── main/
│   ├── java/
│   │   └── com/
│   │       └── example/
│   │           └── danmaku/
│   │               ├── DanmakuApplication.java
│   │               ├── config/
│   │               │   └── WebSocketConfig.java
│   │               ├── controller/
│   │               │   └── DanmakuController.java
│   │               ├── model/
│   │               │   └── Danmaku.java
│   │               ├── dto/
│   │               │   └── DanmakuDTO.java
│   │               ├── mapper/
│   │               │   └── DanmakuMapper.java
│   │               ├── service/
│   │               │   ├── DanmakuService.java
│   │               │   └── ContentFilterService.java
│   └── resources/
│       ├── application.properties
│       ├── schema.sql
│       └── static/
│           ├── index.html
│           └── danmaku.js

6.2 應(yīng)用配置

# application.properties
server.port=8080

# H2數(shù)據(jù)庫配置
spring.datasource.url=jdbc:h2:mem:danmakudb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console

# MyBatis-Plus配置
mybatis-plus.configuration.map-underscore-to-camel-case=true
mybatis-plus.type-aliases-package=com.example.danmaku.model
mybatis-plus.global-config.db-config.id-type=auto

# WebSocket配置
spring.websocket.max-text-message-size=8192
spring.websocket.max-binary-message-size=8192

6.3 數(shù)據(jù)庫初始化腳本

-- schema.sql
CREATE TABLE IF NOT EXISTS danmaku (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    content VARCHAR(255) NOT NULL,
    color VARCHAR(20) DEFAULT '#ffffff',
    font_size INT DEFAULT 24,
    time DOUBLE NOT NULL,
    video_id VARCHAR(50) NOT NULL,
    user_id VARCHAR(50) NOT NULL,
    username VARCHAR(50),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 添加一些測試數(shù)據(jù)
INSERT INTO danmaku (content, color, font_size, time, video_id, user_id, username, created_at)
VALUES
('這是第一條測試彈幕', '#ffffff', 24, 1.0, 'video123', 'user1', '測試用戶1', CURRENT_TIMESTAMP),
('這是第二條測試彈幕', '#ff0000', 24, 3.0, 'video123', 'user2', '測試用戶2', CURRENT_TIMESTAMP),
('這是第三條測試彈幕', '#00ff00', 24, 5.0, 'video123', 'user3', '測試用戶3', CURRENT_TIMESTAMP),
('這是第四條測試彈幕', '#0000ff', 24, 7.0, 'video123', 'user4', '測試用戶4', CURRENT_TIMESTAMP);

6.4 主應(yīng)用類

@SpringBootApplication
@MapperScan("com.example.danmaku.mapper")
public class DanmakuApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(DanmakuApplication.class, args);
    }
}

6.5 運行與測試

1. 啟動SpringBoot應(yīng)用:

mvn spring-boot:run

2. 訪問應(yīng)用:

http://localhost:8080/index.html

3. 查看H2數(shù)據(jù)庫控制臺:

參考application.properties中的數(shù)據(jù)庫配置屬性

http://localhost:8080/h2-console

以上就是SpringBoot實現(xiàn)實時彈幕的示例代碼的詳細內(nèi)容,更多關(guān)于SpringBoot實時彈幕的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 基于logback實現(xiàn)純java版本的SDK組件

    基于logback實現(xiàn)純java版本的SDK組件

    這篇文章主要介紹了基于logback實現(xiàn)純java版本的SDK組件,在項目開發(fā)過程中通常會使用logback作為日志記錄的依賴工具,使用方式是引入logback相關(guān)jar包,然后配置logback.xml配置文件的方式來實現(xiàn),需要的朋友可以參考下
    2023-11-11
  • java模擬http請求的錯誤問題整理

    java模擬http請求的錯誤問題整理

    本文是小編給大家整理的在用java模擬http請求的時候遇到的錯誤問題整理,以及相關(guān)分析,有興趣的朋友參考下。
    2018-05-05
  • java編程中字節(jié)流轉(zhuǎn)換成字符流的實現(xiàn)方法

    java編程中字節(jié)流轉(zhuǎn)換成字符流的實現(xiàn)方法

    下面小編就為大家?guī)硪黄猨ava編程中字節(jié)流轉(zhuǎn)換成字符流的實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-01-01
  • SpringBoot JPA實現(xiàn)增刪改查、分頁、排序、事務(wù)操作等功能示例

    SpringBoot JPA實現(xiàn)增刪改查、分頁、排序、事務(wù)操作等功能示例

    本篇文章主要介紹了SpringBoot JPA實現(xiàn)增刪改查、分頁、排序、事務(wù)操作等功能示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-03-03
  • Java中實現(xiàn)文件預(yù)覽的功能(實例代碼)

    Java中實現(xiàn)文件預(yù)覽的功能(實例代碼)

    大家都知道word,Excel,PPT實現(xiàn)在線預(yù)覽常用的方式就是先轉(zhuǎn)換成pdf,然后在進行預(yù)覽,下面給大家介紹Java中如何實現(xiàn)文件預(yù)覽的功能,需要的朋友可以參考下
    2023-05-05
  • java 獲取字節(jié)碼文件的幾種方法總結(jié)

    java 獲取字節(jié)碼文件的幾種方法總結(jié)

    這篇文章主要介紹了java 獲取字節(jié)碼文件的幾種方法總結(jié)的相關(guān)資料,這里總結(jié)了三種方法幫助大家實現(xiàn)該功能,需要的朋友可以參考下
    2017-08-08
  • 詳解java中float與double的區(qū)別

    詳解java中float與double的區(qū)別

    這篇文章主要介紹了JAVA中float與double的區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Java中的復(fù)合數(shù)據(jù)類型

    Java中的復(fù)合數(shù)據(jù)類型

    這篇文章主要介紹了Java中的復(fù)合數(shù)據(jù)類型,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Java死鎖產(chǎn)生原因及示例

    Java死鎖產(chǎn)生原因及示例

    本文主要介紹了Java死鎖產(chǎn)生原因及示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • Java基于虹軟實現(xiàn)人臉識別、人臉比對、活性檢測等

    Java基于虹軟實現(xiàn)人臉識別、人臉比對、活性檢測等

    本文主要介紹了Java基于虹軟實現(xiàn)人臉識別、人臉比對、活性檢測等,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02

最新評論