Spring Boot 集成 ECharts 实现数据可视化实战
在开发后台管理系统时,我们经常需要将枯燥的数据转化为直观的图表。Spring Boot 配合 ECharts 是 Java 生态中非常经典的组合,既能利用后端强大的业务处理能力,又能发挥前端图表库的交互优势。
核心工具选型
数据可视化的本质是将抽象数据具象化。常见的工具有 ECharts、Highcharts 和 D3.js 等。对于国内项目,ECharts 因其文档完善、社区活跃且对中文支持友好,通常是首选。它基于 JavaScript,轻量级且功能强大,非常适合嵌入到 Web 应用中。
项目搭建与依赖配置
首先,我们需要创建一个标准的 Spring Boot 项目。为了渲染页面,推荐使用 Thymeleaf 模板引擎,这样可以直接在后端传递数据给前端。
在 pom.xml 中添加以下核心依赖:
<dependencies>
<!-- Web 模块 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Thymeleaf 模板引擎 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- 测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
同时,在 application.properties 中配置一下服务器端口和 Thymeleaf 缓存(开发环境建议关闭):
server.port=8080
spring.thymeleaf.cache=false
spring.thymeleaf.mode=HTML
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.suffix=.html
spring.thymeleaf.prefix=classpath:/templates/
后端数据层设计
为了让示例更聚焦于可视化逻辑,这里使用内存列表模拟数据库。实际项目中请替换为 JPA 或 MyBatis。
实体类 Product
public class Product {
private Long id;
private String productId;
private String productName;
private double price;
private int sales;
public Product() {}
public Product(Long id, String productId, String productName, double price, int sales) {
this.id = id;
this.productId = productId;
this.productName = productName;
this.price = price;
this.sales = sales;
}
// Getter 和 Setter 方法省略,保持标准规范即可
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getProductId() { return productId; }
public void setProductId(String productId) { this.productId = productId; }
public String getProductName() { return productName; }
public void setProductName(String productName) { this.productName = productName; }
public double getPrice() { return price; }
public void setPrice(double price) { this.price = price; }
public int getSales() { return sales; }
public void setSales(int sales) { this.sales = sales; }
}
仓储层 (Repository)
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.List;
@Repository
public class ProductRepository {
private List<Product> products = new ArrayList<>();
public ProductRepository() {
products.add(new Product(1L, "P001", "手机", 1000.0, 100));
products.add(new Product(2L, "P002", "电脑", 5000.0, 50));
products.add(new Product(3L, "P003", "电视", 3000.0, 80));
products.add(new Product(4L, "P004", "手表", 500.0, 200));
products.add(new Product(5L, "P005", "耳机", 300.0, 150));
}
public List<Product> getAllProducts() {
return products;
}
}
服务层 (Service)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ProductService {
@Autowired
private ProductRepository productRepository;
public List<Product> getAllProducts() {
return productRepository.getAllProducts();
}
}
控制器 (Controller)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.List;
@Controller
@RequestMapping("/api/products")
public class ProductController {
@Autowired
private ProductService productService;
@GetMapping("/")
public String listProducts(Model model) {
List<Product> products = productService.getAllProducts();
model.addAttribute("products", products);
return "product-list";
}
}
前端页面与图表渲染
这是最关键的一步。我们需要引入 ECharts 的 CDN 资源,并在 HTML 中定义容器,最后通过 JavaScript 将后端传来的数据填充进去。
Thymeleaf 模板 (product-list.html)
<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>产品销量看板</title>
<!-- 引入 ECharts -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js"></script>
</head>
<body>
<h1>产品销量统计</h1>
<!-- 图表容器 -->
<div id="salesChart" style="width: 800px; height: 400px;"></div>
<script>
// 初始化图表实例
var chartDom = document.getElementById('salesChart');
var myChart = echarts.init(chartDom);
// 准备数据:从后端传入的列表中解析
var productNames = [];
var productSales = [];
// 注意:这里使用了 Thymeleaf 语法遍历后端对象
<th:block th:each="product : ${products}">
productNames.push('<span th:text="${product.productName}"></span>');
productSales.push(<span th:text="${product.sales}"></span>);
</th:block>
var option = {
title: {
text: '各产品销量分布',
left: 'center'
},
tooltip: {
trigger: 'item'
},
legend: {
orient: 'vertical',
right: 10,
top: 'center'
},
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: [
<th:block th:each="product : ${products}">
{value: <span th:text="${product.sales}"></span>, name: '<span th:text="${product.productName}"></span>'},
</th:block>
]
}]
};
// 渲染图表
if (option && typeof option === 'object') {
myChart.setOption(option);
}
</script>
</body>
</html>
运行与验证
启动应用后访问 http://localhost:8080/api/products/,你将看到一个动态加载的产品列表以及右侧的饼图。点击饼图中的扇区,还能看到具体的数值高亮效果。
这种模式不仅适用于产品销量,用户活跃度、订单状态占比等场景都可以复用。关键在于后端提供结构化的 JSON 数据,前端负责将其映射为图表配置项。

