跳到主要内容
Spring Boot 集成 ECharts 实现数据可视化实战 | 极客日志
Java java
Spring Boot 集成 ECharts 实现数据可视化实战 Spring Boot 结合 ECharts 进行数据可视化的完整流程。涵盖项目依赖配置、后端实体与控制器开发、以及前端 Thymeleaf 模板与 JavaScript 图表渲染。通过实际案例展示如何从内存数据获取产品销量信息,并在页面上动态生成饼图,提升数据分析效率。
落日余晖 发布于 2026/3/22 更新于 2026/5/6 4 浏览Spring Boot 集成 ECharts 实现数据可视化实战
在 Java 开发中,将后端数据直观地展示出来往往能极大提升用户体验。Spring Boot 配合前端图表库(如 ECharts)是构建管理后台或数据分析页面的经典组合。本文将带你从零开始,完成一个基于 Spring Boot + Thymeleaf + ECharts 的产品销量可视化项目。
环境准备与依赖配置
首先,我们需要创建一个标准的 Spring Boot Web 项目。核心依赖包括 Web 启动器、Thymeleaf 模板引擎以及测试工具。
pom.xml
<dependencies >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-web</artifactId >
</dependency >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-thymeleaf</artifactId >
</dependency >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-test</ >
test
artifactId
<scope >
</scope >
</dependency >
</dependencies >
# 服务器端口
server.port=8080
# Thymeleaf 配置
spring.thymeleaf.cache=false
spring.thymeleaf.mode=HTML
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.suffix=.html
spring.thymeleaf.prefix=classpath:/templates/
后端数据层构建 为了演示方便,这里使用内存列表模拟数据库操作。实际项目中请替换为 MyBatis 或 JPA。
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;
}
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; }
@Override
public String toString () {
return "Product{" +
"id=" + id +
", productId='" + productId + '\'' +
", productName='" + productName + '\'' +
", price=" + price +
", sales=" + sales +
'}' ;
}
}
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;
}
public Product getProductById (Long id) {
return products.stream().filter(product -> product.getId().equals(id)).findFirst().orElse(null );
}
public void addProduct (Product product) {
product.setId((long ) (products.size() + 1 ));
products.add(product);
}
public void updateProduct (Product product) {
Product existingProduct = getProductById(product.getId());
if (existingProduct != null ) {
existingProduct.setProductId(product.getProductId());
existingProduct.setProductName(product.getProductName());
existingProduct.setPrice(product.getPrice());
existingProduct.setSales(product.getSales());
}
}
public void deleteProduct (Long id) {
products.removeIf(product -> product.getId().equals(id));
}
}
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();
}
public Product getProductById (Long id) {
return productRepository.getProductById(id);
}
public void addProduct (Product product) {
productRepository.addProduct(product);
}
public void updateProduct (Product product) {
productRepository.updateProduct(product);
}
public void deleteProduct (Long id) {
productRepository.deleteProduct(id);
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Controller
@RequestMapping("/api/products")
public class ProductController {
@Autowired
private ProductService productService;
@GetMapping("/")
public String getAllProducts (Model model) {
List<Product> products = productService.getAllProducts();
model.addAttribute("products" , products);
return "product-list" ;
}
@GetMapping("/{id}")
public String getProductById (@PathVariable Long id, Model model) {
Product product = productService.getProductById(id);
model.addAttribute("product" , product);
return "product-detail" ;
}
@GetMapping("/add")
public String addProductForm (Model model) {
model.addAttribute("product" , new Product ());
return "product-form" ;
}
@PostMapping("/add")
public String addProduct (@ModelAttribute Product product) {
productService.addProduct(product);
return "redirect:/api/products/" ;
}
@GetMapping("/edit/{id}")
public String editProductForm (@PathVariable Long id, Model model) {
Product product = productService.getProductById(id);
model.addAttribute("product" , product);
return "product-form" ;
}
@PostMapping("/edit/{id}")
public String editProduct (@PathVariable Long id, @ModelAttribute Product product) {
product.setId(id);
productService.updateProduct(product);
return "redirect:/api/products/" ;
}
@GetMapping("/delete/{id}")
public String deleteProduct (@PathVariable Long id) {
productService.deleteProduct(id);
return "redirect:/api/products/" ;
}
}
前端页面与图表渲染 前端使用 Thymeleaf 模板引擎,结合 ECharts 进行数据可视化。注意 JS 代码中的变量需要通过 Thymeleaf 标签注入。
templates/product-list.html
<!DOCTYPE html >
<html lang ="zh-CN" xmlns:th ="http://www.thymeleaf.org" >
<head >
<meta charset ="UTF-8" >
<title > 产品列表</title >
<script src ="https://cdn.jsdelivr.net/npm/[email protected] /dist/echarts.min.js" > </script >
</head >
<body >
<h1 > 产品列表</h1 >
<a href ="/api/products/add" > 添加产品</a >
<table border ="1" >
<thead >
<tr >
<th > ID</th >
<th > 产品 ID</th >
<th > 产品名称</th >
<th > 价格</th >
<th > 销量</th >
<th > 操作</th >
</tr >
</thead >
<tbody >
<tr th:each ="product : ${products}" >
<td th:text ="${product.id}" > </td >
<td th:text ="${product.productId}" > </td >
<td th:text ="${product.productName}" > </td >
<td th:text ="${product.price}" > </td >
<td th:text ="${product.sales}" > </td >
<td >
<a href ="@{/api/products/edit/{id}(id=${product.id})}" > 编辑</a >
<a href ="@{/api/products/delete/{id}(id=${product.id})}" > 删除</a >
</td >
</tr >
</tbody >
</table >
<h2 > 产品销量图表</h2 >
<div id ="salesChart" style ="width: 800px;height: 400px;" > </div >
<script >
var chartDom = document .getElementById ('salesChart' );
var myChart = echarts.init (chartDom);
var option;
var productNames = [];
var productSales = [];
<th:block th:each ="product : ${products}" >
productNames.push('<span > ' + product.productName + '</span > ');
productSales.push(<span > ' + product.sales + '</span > ');
</th:block >
option = {
title : {
text : '产品销量图表' ,
left : 'center'
},
tooltip : {
trigger : 'item'
},
legend : {
orient : 'vertical' ,
right : 10 ,
top : 'center'
},
series : [{
name : '销量' ,
type : 'pie' ,
radius : ['40%' , '70%' ],
avoidLabelOverlap : ,
: {
: ,
: ,
:
},
: {
: ,
:
},
: {
: {
: ,
: ,
:
}
},
: {
:
},
: [
]
}]
};
option && myChart. (option);
</script >
</body >
</html >
运行与验证 启动应用后访问 http://localhost:8080/api/products/,你将看到产品列表表格以及下方的动态饼图。点击'添加'、'编辑'或'删除'按钮即可对数据进行 CRUD 操作,图表也会随之实时更新。
这种模式非常适合内部管理系统或数据看板开发,既利用了 Spring Boot 的后端能力,又发挥了 ECharts 强大的前端渲染性能。
false
itemStyle
borderRadius
10
borderColor
'#fff'
borderWidth
2
label
show
false
position
'center'
emphasis
label
show
true
fontSize
20
fontWeight
'bold'
labelLine
show
false
data
<th:block th:each ="product : ${products}" >
{value: <span > ' + product.sales + '</span > ', name: '<span > ' + product.productName + '</span > '},
</th:block >
setOption
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online