本文目录导读:

我来为您提供一个完整的Java数据大屏实现案例,使用Spring Boot + ECharts + WebSocket实现实时数据展示。
项目结构
data-screen/
├── pom.xml
├── src/main/java/com/example/datascreen/
│ ├── DataScreenApplication.java
│ ├── controller/
│ │ └── DataController.java
│ ├── service/
│ │ ├── DataService.java
│ │ └── RealTimeDataService.java
│ ├── config/
│ │ ├── WebSocketConfig.java
│ │ └── CorsConfig.java
│ └── model/
│ └── DataModel.java
└── src/main/resources/
├── application.yml
└── static/
├── index.html
├── css/style.css
└── js/
├── echarts.min.js
└── dashboard.js
pom.xml
<?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
http://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>2.7.0</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>data-screen</artifactId>
<version>1.0.0</version>
<name>data-screen</name>
<description>数据大屏展示系统</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<!-- 数据库连接 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
应用主类
package com.example.datascreen;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class DataScreenApplication {
public static void main(String[] args) {
SpringApplication.run(DataScreenApplication.class, args);
}
}
数据模型
package com.example.datascreen.model;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
@Data
public class DataModel {
// 实时数据
private Integer totalSales; // 总销售额
private Integer totalOrders; // 总订单数
private Integer activeUsers; // 活跃用户数
private Integer conversionRate; // 转化率
// 图表数据
private List<Map<String, Object>> trendData; // 趋势数据
private List<Map<String, Object>> categoryData; // 分类数据
private List<Map<String, Object>> regionData; // 地区数据
private List<Map<String, Object>> realtimeData; // 实时数据
// 排名数据
private List<Map<String, Object>> productRanking; // 产品排名
private List<Map<String, Object>> sellerRanking; // 商家排名
// 时间戳
private LocalDateTime updateTime;
// 饼图数据
private List<Map<String, Object>> channelData; // 渠道数据
private List<Map<String, Object>> ageDistribution; // 年龄分布
}
数据服务
package com.example.datascreen.service;
import com.alibaba.fastjson.JSON;
import com.example.datascreen.model.DataModel;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
@Service
public class DataService {
private DataModel dataModel;
private final Map<String, Object> dataCache = new HashMap<>();
private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
@PostConstruct
public void init() {
dataModel = new DataModel();
}
/**
* 获取大屏数据
*/
public Map<String, Object> getDashboardData() {
Map<String, Object> result = new HashMap<>();
// 生成模拟数据
result.put("totalSales", ThreadLocalRandom.current().nextInt(800, 1200));
result.put("totalOrders", ThreadLocalRandom.current().nextInt(5000, 8000));
result.put("activeUsers", ThreadLocalRandom.current().nextInt(10000, 15000));
result.put("conversionRate", ThreadLocalRandom.current().nextDouble(2.5, 5.0) / 100);
// 趋势图数据
result.put("trendData", generateTrendData());
// 分类数据
result.put("categoryData", generateCategoryData());
// 地区数据
result.put("regionData", generateRegionData());
// 产品排名
result.put("productRanking", generateProductRanking());
// 渠道数据
result.put("channelData", generateChannelData());
// 时间
result.put("updateTime", LocalDateTime.now().format(formatter));
return result;
}
/**
* 生成趋势数据(最近7天)
*/
private List<Map<String, Object>> generateTrendData() {
List<Map<String, Object>> list = new ArrayList<>();
String[] dates = {"周一", "周二", "周三", "周四", "周五", "周六", "周日"};
int[] values = {120, 200, 150, 80, 70, 110, 130};
int[] values2 = {80, 150, 100, 60, 50, 90, 100};
for (int i = 0; i < dates.length; i++) {
Map<String, Object> map = new HashMap<>();
map.put("name", dates[i]);
map.put("value", values[i]);
map.put("value2", values2[i]);
list.add(map);
}
return list;
}
/**
* 生成分类数据
*/
private List<Map<String, Object>> generateCategoryData() {
List<Map<String, Object>> list = new ArrayList<>();
String[] categories = {"电子产品", "服装", "食品", "家居", "美妆", "图书"};
String[] colors = {"#5470c6", "#91cc75", "#fac858", "#ee6666", "#73c0de", "#3ba272"};
for (int i = 0; i < categories.length; i++) {
Map<String, Object> map = new HashMap<>();
map.put("name", categories[i]);
map.put("value", ThreadLocalRandom.current().nextInt(100, 500));
map.put("color", colors[i]);
list.add(map);
}
return list;
}
/**
* 生成地区数据
*/
private List<Map<String, Object>> generateRegionData() {
List<Map<String, Object>> list = new ArrayList<>();
String[] regions = {"北京", "上海", "广州", "深圳", "杭州", "成都", "武汉"};
int[][] coordinates = {
{116.46, 39.92}, {121.48, 31.22}, {113.23, 23.16},
{114.07, 22.62}, {120.19, 30.26}, {104.06, 30.67}, {114.29, 30.59}
};
for (int i = 0; i < regions.length; i++) {
Map<String, Object> map = new HashMap<>();
map.put("name", regions[i]);
map.put("value", ThreadLocalRandom.current().nextInt(50, 200));
map.put("coordinate", coordinates[i]);
list.add(map);
}
return list;
}
/**
* 生成产品排名
*/
private List<Map<String, Object>> generateProductRanking() {
List<Map<String, Object>> list = new ArrayList<>();
String[] products = {"iPhone 15", "华为Mate60", "小米14", "OPPO Find X7",
"三星S24", "荣耀Magic6", "vivo X100", "一加12"};
for (int i = 0; i < products.length; i++) {
Map<String, Object> map = new HashMap<>();
map.put("name", products[i]);
map.put("value", ThreadLocalRandom.current().nextInt(1000, 5000));
list.add(map);
}
// 按销量排序
list.sort((a, b) -> ((Integer) b.get("value")).compareTo((Integer) a.get("value")));
return list;
}
/**
* 生成渠道数据
*/
private List<Map<String, Object>> generateChannelData() {
List<Map<String, Object>> list = new ArrayList<>();
String[] channels = {"线上商城", "实体店", "直播带货", "社交电商", "跨境电商"};
for (int i = 0; i < channels.length; i++) {
Map<String, Object> map = new HashMap<>();
map.put("name", channels[i]);
map.put("value", ThreadLocalRandom.current().nextInt(20, 100));
list.add(map);
}
return list;
}
/**
* 实时数据推送(WebSocket)
*/
public String getRealtimeData() {
Map<String, Object> data = getDashboardData();
return JSON.toJSONString(data);
}
}
WebSocket配置
package com.example.datascreen.config;
import com.example.datascreen.service.DataService;
import com.alibaba.fastjson.JSON;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;
import org.springframework.web.socket.config.annotation.*;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Component
public class WebSocketConfig implements WebSocketConfigurer {
@Autowired
private DataService dataService;
private static final CopyOnWriteArrayList<WebSocketSession> sessions =
new CopyOnWriteArrayList<>();
private static final Map<String, WebSocketSession> sessionMap = new ConcurrentHashMap<>();
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new TextWebSocketHandler() {
@Override
public void afterConnectionEstablished(WebSocketSession session) {
sessions.add(session);
sessionMap.put(session.getId(), session);
System.out.println("连接建立: " + session.getId());
}
@Override
protected void handleTextMessage(WebSocketSession session,
TextMessage message) throws Exception {
// 处理客户端发送的消息
String payload = message.getPayload();
System.out.println("收到消息: " + payload);
// 发送响应
session.sendMessage(new TextMessage(
JSON.toJSONString(dataService.getDashboardData())));
}
@Override
public void afterConnectionClosed(WebSocketSession session,
CloseStatus status) {
sessions.remove(session);
sessionMap.remove(session.getId());
System.out.println("连接关闭: " + session.getId());
}
@Override
public void handleTransportError(WebSocketSession session,
Throwable exception) {
sessions.remove(session);
sessionMap.remove(session.getId());
}
}, "/websocket").setAllowedOrigins("*");
}
/**
* 定时推送数据(每5秒)
*/
@Scheduled(fixedRate = 5000)
public void sendRealtimeData() {
if (sessions.isEmpty()) return;
String data = dataService.getRealtimeData();
TextMessage message = new TextMessage(data);
for (WebSocketSession session : sessions) {
try {
if (session.isOpen()) {
synchronized (session) {
session.sendMessage(message);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
控制器
package com.example.datascreen.controller;
import com.example.datascreen.service.DataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequestMapping("/api/data")
@CrossOrigin
public class DataController {
@Autowired
private DataService dataService;
/**
* 获取大屏数据
*/
@GetMapping("/dashboard")
public Map<String, Object> getDashboardData() {
return dataService.getDashboardData();
}
/**
* 获取实时数据
*/
@GetMapping("/realtime")
public Map<String, Object> getRealtimeData() {
return dataService.getDashboardData();
}
/**
* 获取统计数据
*/
@GetMapping("/statistics")
public Map<String, Object> getStatistics() {
return dataService.getDashboardData();
}
}
application.yml
server:
port: 8080
spring:
application:
name: data-screen
datasource:
url: jdbc:mysql://localhost:3306/data_screen?useUnicode=true&characterEncoding=utf-8
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
# 自定义配置
data:
screen:
# 刷新频率(毫秒)
refresh-rate: 5000
前端大屏页面
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">大数据可视化大屏</title>
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.4/dist/jquery.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: #091828;
color: #fff;
font-family: "Microsoft YaHei", sans-serif;
min-height: 100vh;
overflow: hidden;
}
.dashboard {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
grid-template-rows: 70px 1fr 1fr;
gap: 10px;
padding: 20px;
height: 100vh;
background: linear-gradient(180deg, #0a1929 0%, #091828 100%);
}
/* 大屏标题 */
.header {
grid-column: 1 / -1;
text-align: center;
padding: 15px;
background: linear-gradient(90deg, transparent, rgba(0, 150, 255, 0.3), transparent);
box-shadow: 0 4px 20px rgba(0, 150, 255, 0.2);
}
.header h1 {
font-size: 32px;
background: linear-gradient(90deg, #ff6b6b, #ffd93d);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 30px rgba(255, 107, 107, 0.3);
}
/* 图表容器 */
.chart-container {
background: rgba(0, 20, 40, 0.6);
border: 1px solid #1a3a5c;
border-radius: 8px;
padding: 15px;
box-shadow: 0 0 20px rgba(0, 100, 200, 0.1);
}
.chart-container .title {
font-size: 16px;
margin-bottom: 10px;
color: #00d4ff;
border-left: 3px solid #00d4ff;
padding-left: 10px;
}
/* 数字卡片 */
.stat-cards {
grid-column: 1 / -1;
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 10px;
}
.stat-card {
background: rgba(0, 20, 40, 0.8);
border: 1px solid #1a3a5c;
border-radius: 8px;
padding: 15px;
text-align: center;
transition: all 0.3s;
}
.stat-card:hover {
transform: translateY(-5px);
box-shadow: 0 5px 20px rgba(0, 150, 255, 0.3);
}
.stat-card .value {
font-size: 28px;
font-weight: bold;
background: linear-gradient(90deg, #00d4ff, #0066ff);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.stat-card .label {
font-size: 14px;
color: #8ab4f8;
margin-top: 5px;
}
/* 地图容器 */
#mapChart {
grid-column: 2;
grid-row: 2 / 4;
}
/* 滚动消息 */
.scroll-message {
position: fixed;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
color: #00d4ff;
font-size: 12px;
animation: scroll 10s linear infinite;
}
@keyframes scroll {
0% { opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { opacity: 0; }
}
/* 动画效果 */
@keyframes glowing {
0% { box-shadow: 0 0 5px rgba(0, 150, 255, 0.5); }
50% { box-shadow: 0 0 20px rgba(0, 150, 255, 0.8); }
100% { box-shadow: 0 0 5px rgba(0, 150, 255, 0.5); }
}
.glowing {
animation: glowing 2s infinite;
}
/* 自适应 */
@media (max-width: 768px) {
.dashboard {
grid-template-columns: 1fr;
gap: 5px;
}
.stat-cards {
grid-template-columns: repeat(2, 1fr);
}
#mapChart {
grid-column: 1;
grid-row: auto;
}
}
</style>
</head>
<body>
<div class="dashboard">
<!-- 头部标题 -->
<div class="header">
<h1>📊 电商大数据可视化大屏</h1>
</div>
<!-- 顶部统计卡片 -->
<div class="stat-cards">
<div class="stat-card">
<div class="value" id="totalSales">0</div>
<div class="label">总销售额(万)</div>
</div>
<div class="stat-card">
<div class="value" id="totalOrders">0</div>
<div class="label">总订单数</div>
</div>
<div class="stat-card">
<div class="value" id="activeUsers">0</div>
<div class="label">活跃用户</div>
</div>
<div class="stat-card">
<div class="value" id="conversionRate">0%</div>
<div class="label">转化率</div>
</div>
</div>
<!-- 左侧图表 -->
<div class="chart-container">
<div class="title">销售趋势</div>
<div id="trendChart" style="width: 100%; height: 90%;"></div>
</div>
<!-- 中间图表 -->
<div class="chart-container" id="mapChart">
<div class="title">销售地区分布</div>
<div id="regionMap" style="width: 100%; height: 90%;"></div>
</div>
<!-- 右侧图表 -->
<div class="chart-container">
<div class="title">销售渠道分析</div>
<div id="channelChart" style="width: 100%; height: 90%;"></div>
</div>
<!-- 左下角图表 -->
<div class="chart-container">
<div class="title">商品分类</div>
<div id="categoryChart" style="width: 100%; height: 90%;"></div>
</div>
<!-- 右下角图表 -->
<div class="chart-container">
<div class="title">产品销量排名</div>
<div id="rankingChart" style="width: 100%; height: 90%;"></div>
</div>
<div class="scroll-message">数据更新时间:<span id="updateTime"></span> | 数据每5秒自动刷新</div>
</div>
<script src="/js/dashboard.js"></script>
</body>
</html>
前端JavaScript
// dashboard.js
$(document).ready(function() {
// 初始化所有图表
initCharts();
// 连接WebSocket
connectWebSocket();
// 定时刷新数据
setInterval(updateData, 5000);
});
// 图表实例
let trendChart, regionMap, channelChart, categoryChart, rankingChart;
function initCharts() {
// 趋势图
trendChart = echarts.init(document.getElementById('trendChart'));
trendChart.setOption({
tooltip: { trigger: 'axis' },
legend: { data: ['销售额', '订单量'], textStyle: { color: '#fff' } },
grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
xAxis: {
type: 'category',
data: [],
axisLine: { lineStyle: { color: '#1a3a5c' } },
axisLabel: { color: '#fff' }
},
yAxis: {
type: 'value',
axisLine: { lineStyle: { color: '#1a3a5c' } },
axisLabel: { color: '#fff' },
splitLine: { lineStyle: { color: '#1a3a5c' } }
},
series: [
{
name: '销售额',
type: 'line',
smooth: true,
data: [],
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1,
[{ offset: 0, color: 'rgba(0, 212, 255, 0.3)' },
{ offset: 1, color: 'rgba(0, 212, 255, 0)' }])
}
},
{
name: '订单量',
type: 'line',
smooth: true,
data: [],
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1,
[{ offset: 0, color: 'rgba(255, 107, 107, 0.3)' },
{ offset: 1, color: 'rgba(255, 107, 107, 0)' }])
}
}
]
});
// 地区地图
regionMap = echarts.init(document.getElementById('regionMap'));
regionMap.setOption({
tooltip: { trigger: 'item', formatter: '{b}: {c}' },
visualMap: {
min: 0,
max: 200,
text: ['高', '低'],
calculable: true,
inRange: { color: ['#50a3ba', '#eac736', '#d94e5d'] }
},
series: [{
type: 'map',
map: 'china',
roam: true,
label: { show: true },
data: []
}]
});
// 渠道分析(饼图)
channelChart = echarts.init(document.getElementById('channelChart'));
channelChart.setOption({
tooltip: { trigger: 'item', formatter: '{a} <br/>{b}: {c} ({d}%)' },
legend: { orient: 'vertical', right: 10, textStyle: { color: '#fff' } },
series: [{
name: '销售渠道',
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: false,
itemStyle: { borderRadius: 10, borderColor: '#fff', borderWidth: 2 },
label: { show: false, position: 'center' },
emphasis: {
label: { show: true, fontSize: 20, fontWeight: 'bold' }
},
data: []
}]
});
// 商品分类(柱状图)
categoryChart = echarts.init(document.getElementById('categoryChart'));
categoryChart.setOption({
tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
xAxis: {
type: 'category',
data: [],
axisLabel: { color: '#fff', rotate: 30 },
axisLine: { lineStyle: { color: '#1a3a5c' } }
},
yAxis: {
type: 'value',
axisLabel: { color: '#fff' },
splitLine: { lineStyle: { color: '#1a3a5c' } }
},
series: [{
name: '销售额',
type: 'bar',
data: [],
itemStyle: {
borderRadius: [5, 5, 0, 0],
color: new echarts.graphic.LinearGradient(0, 0, 0, 1,
[{ offset: 0, color: '#00d4ff' },
{ offset: 1, color: '#0066ff' }])
}
}]
});
// 产品排名(横向柱状图)
rankingChart = echarts.init(document.getElementById('rankingChart'));
rankingChart.setOption({
tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
grid: { left: '3%', right: '10%', bottom: '3%', containLabel: true },
xAxis: {
type: 'value',
axisLabel: { color: '#fff' },
splitLine: { lineStyle: { color: '#1a3a5c' } }
},
yAxis: {
type: 'category',
data: [],
axisLabel: { color: '#fff' },
axisLine: { lineStyle: { color: '#1a3a5c' } }
},
series: [{
name: '销量',
type: 'bar',
data: [],
itemStyle: {
borderRadius: [0, 5, 5, 0],
color: new echarts.graphic.LinearGradient(0, 0, 1, 0,
[{ offset: 0, color: '#ff6b6b' },
{ offset: 1, color: '#ffd93d' }])
}
}]
});
}
function updateData() {
$.ajax({
url: '/api/data/dashboard',
type: 'GET',
dataType: 'json',
success: function(data) {
renderData(data);
},
error: function() {
console.log('请求数据失败');
}
});
}
function renderData(data) {
if (!data) return;
// 更新统计卡片
animateNumber($('#totalSales'), 0, data.totalSales, 1000);
animateNumber($('#totalOrders'), 0, data.totalOrders, 1000);
animateNumber($('#activeUsers'), 0, data.activeUsers, 1000);
let rate = (data.conversionRate * 100).toFixed(2);
$('#conversionRate').text(rate + '%');
// 更新时间
$('#updateTime').text(data.updateTime);
// 更新图表
updateCharts(data);
}
function updateCharts(data) {
// 更新趋势图
if (data.trendData) {
trendChart.setOption({
xAxis: { data: data.trendData.map(item => item.name) },
series: [
{ data: data.trendData.map(item => item.value) },
{ data: data.trendData.map(item => item.value2) }
]
});
}
// 更新地区地图
if (data.regionData) {
regionMap.setOption({
series: [{
data: data.regionData.map(item => ({
name: item.name,
value: item.value
}))
}]
});
}
// 更新渠道饼图
if (data.channelData) {
channelChart.setOption({
series: [{ data: data.channelData }]
});
}
// 更新商品分类
if (data.categoryData) {
categoryChart.setOption({
xAxis: { data: data.categoryData.map(item => item.name) },
series: [{ data: data.categoryData.map(item => item.value) }]
});
}
// 更新产品排名
if (data.productRanking) {
rankingChart.setOption({
yAxis: { data: data.productRanking.map(item => item.name) },
series: [{ data: data.productRanking.map(item => item.value) }]
});
}
}
// 数字动画
function animateNumber($element, start, end, duration) {
let current = start;
let step = (end - start) / (duration / 50);
let timer = setInterval(function() {
current += step;
if (current >= end) {
current = end;
clearInterval(timer);
}
$element.text(Math.round(current).toLocaleString());
}, 50);
}
// WebSocket连接
function connectWebSocket() {
const socket = new WebSocket('ws://' + window.location.host + '/websocket');
socket.onopen = function() {
console.log('WebSocket连接成功');
};
socket.onmessage = function(event) {
let data = JSON.parse(event.data);
renderData(data);
};
socket.onclose = function() {
console.log('WebSocket连接关闭');
// 断线重连
setTimeout(connectWebSocket, 5000);
};
socket.onerror = function(error) {
console.log('WebSocket错误:', error);
};
}
运行与部署
打包运行
# 打包 mvn clean package -DskipTests # 运行 java -jar target/data-screen-1.0.0.jar
访问地址
http://localhost:8080
功能特点
- 实时数据展示:通过WebSocket实现数据的实时推送
- 多种图表类型:折线图、柱状图、饼图、地图等
- 动态数字效果:数字变化的动态展示
- 响应式设计:适配不同屏幕尺寸
- 自动刷新:定时获取最新数据
- 美观的UI设计:科技感十足的大屏样式
扩展建议
- 数据库集成:使用MySQL存储真实业务数据
- 多数据源:支持Kafka、Flink等实时数据源
- 权限控制:添加用户认证和权限管理
- 告警功能:添加数据异常预警
- 更多图表:添加雷达图、仪表盘等更多可视化组件
- 数据导出:支持数据报表导出功能
- 多屏幕适配:支持多屏拼接显示
这个数据大屏案例可以直接运行,适合学习大数据可视化和WebSocket实时通信开发,您可以根据实际需求修改数据和样式。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播