Spring Boot 数据可视化与图表集成
Spring Boot 数据可视化与图表集成
27.1 学习目标与重点提示
学习目标:掌握Spring Boot数据可视化与图表集成的核心概念与使用方法,包括数据可视化的定义与特点、图表工具的定义与特点、Spring Boot与图表工具的集成、Spring Boot的实际应用场景,学会在实际开发中处理数据可视化与图表集成问题。
重点:数据可视化的定义与特点、图表工具的定义与特点、Spring Boot与图表工具的集成、Spring Boot的实际应用场景。
27.2 数据可视化与图表工具概述
数据可视化与图表工具是Java开发中的重要组件。
27.2.1 数据可视化的定义
定义:数据可视化是指将数据通过图表、地图、仪表盘等形式直观地展示出来,帮助用户更好地理解和分析数据。
作用:
- 提高数据的可读性。
- 帮助用户发现数据中的规律。
- 支持快速决策。
常见的数据可视化工具:
- ECharts:ECharts是百度开源的一个数据可视化库。
- Highcharts:Highcharts是一个基于JavaScript的数据可视化库。
- D3.js:D3.js是一个基于JavaScript的数据可视化库。
- Tableau:Tableau是一个商业数据可视化工具。
✅ 结论:数据可视化是指将数据通过图表、地图、仪表盘等形式直观地展示出来,作用是提高数据的可读性、帮助用户发现数据中的规律、支持快速决策。
27.2.2 图表工具的定义
定义:图表工具是一种用于创建和展示图表的软件工具,用于数据可视化。
作用:
- 实现图表的创建。
- 实现图表的展示。
- 提高数据的可视化效果。
常见的图表工具:
- ECharts:ECharts是百度开源的一个数据可视化库。
- Highcharts:Highcharts是一个基于JavaScript的数据可视化库。
- D3.js:D3.js是一个基于JavaScript的数据可视化库。
- Tableau:Tableau是一个商业数据可视化工具。
✅ 结论:图表工具是一种用于创建和展示图表的软件工具,作用是实现图表的创建、展示、提高数据的可视化效果。
27.3 Spring Boot与图表工具的集成
Spring Boot与图表工具的集成是Java开发中的重要内容。
27.3.1 集成ECharts的步骤
定义:集成ECharts的步骤是指使用Spring Boot与ECharts集成的方法。
步骤:
- 创建Spring Boot项目。
- 添加所需的依赖。
- 配置ECharts。
- 创建数据访问层。
- 创建业务层。
- 创建控制器类。
- 创建前端页面。
- 测试应用。
示例:
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文件中的配置:
# 服务器端口 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/ 实体类:
publicclassProduct{privateLong id;privateString productId;privateString productName;privatedouble price;privateint sales;publicProduct(){}publicProduct(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方法publicLonggetId(){return id;}publicvoidsetId(Long id){this.id = id;}publicStringgetProductId(){return productId;}publicvoidsetProductId(String productId){this.productId = productId;}publicStringgetProductName(){return productName;}publicvoidsetProductName(String productName){this.productName = productName;}publicdoublegetPrice(){return price;}publicvoidsetPrice(double price){this.price = price;}publicintgetSales(){return sales;}publicvoidsetSales(int sales){this.sales = sales;}@OverridepublicStringtoString(){return"Product{"+"id="+ id +",+ productId +'\''+",+ productName +'\''+", price="+ price +", sales="+ sales +'}';}}Repository接口:
importorg.springframework.stereotype.Repository;importjava.util.ArrayList;importjava.util.List;importjava.util.stream.Collectors;@RepositorypublicclassProductRepository{privateList<Product> products =newArrayList<>();publicProductRepository(){ products.add(newProduct(1L,"P001","手机",1000.0,100)); products.add(newProduct(2L,"P002","电脑",5000.0,50)); products.add(newProduct(3L,"P003","电视",3000.0,80)); products.add(newProduct(4L,"P004","手表",500.0,200)); products.add(newProduct(5L,"P005","耳机",300.0,150));}publicList<Product>getAllProducts(){return products;}publicProductgetProductById(Long id){return products.stream().filter(product -> product.getId().equals(id)).findFirst().orElse(null);}publicvoidaddProduct(Product product){ product.setId((long)(products.size()+1)); products.add(product);}publicvoidupdateProduct(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());}}publicvoiddeleteProduct(Long id){ products.removeIf(product -> product.getId().equals(id));}}Service类:
importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;importjava.util.List;@ServicepublicclassProductService{@AutowiredprivateProductRepository productRepository;publicList<Product>getAllProducts(){return productRepository.getAllProducts();}publicProductgetProductById(Long id){return productRepository.getProductById(id);}publicvoidaddProduct(Product product){ productRepository.addProduct(product);}publicvoidupdateProduct(Product product){ productRepository.updateProduct(product);}publicvoiddeleteProduct(Long id){ productRepository.deleteProduct(id);}}控制器类:
importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Controller;importorg.springframework.ui.Model;importorg.springframework.web.bind.annotation.*;importjava.util.List;@Controller@RequestMapping("/api/products")publicclassProductController{@AutowiredprivateProductService productService;@GetMapping("/")publicStringgetAllProducts(Model model){List<Product> products = productService.getAllProducts(); model.addAttribute("products", products);return"product-list";}@GetMapping("/{id}")publicStringgetProductById(@PathVariableLong id,Model model){Product product = productService.getProductById(id); model.addAttribute("product", product);return"product-detail";}@GetMapping("/add")publicStringaddProductForm(Model model){ model.addAttribute("product",newProduct());return"product-form";}@PostMapping("/add")publicStringaddProduct(@ModelAttributeProduct product){ productService.addProduct(product);return"redirect:/api/products/";}@GetMapping("/edit/{id}")publicStringeditProductForm(@PathVariableLong id,Model model){Product product = productService.getProductById(id); model.addAttribute("product", product);return"product-form";}@PostMapping("/edit/{id}")publicStringeditProduct(@PathVariableLong id,@ModelAttributeProduct product){ product.setId(id); productService.updateProduct(product);return"redirect:/api/products/";}@GetMapping("/delete/{id}")publicStringdeleteProduct(@PathVariableLong id){ productService.deleteProduct(id);return"redirect:/api/products/";}}前端页面(product-list.html):
<!DOCTYPEhtml><htmllang="zh-CN"xmlns:th="http://www.thymeleaf.org"><head><metacharset="UTF-8"><title>产品列表</title><scriptsrc="https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js"></script></head><body><h1>产品列表</h1><ahref="/api/products/add">添加产品</a><tableborder="1"><thead><tr><th>ID</th><th>产品ID</th><th>产品名称</th><th>价格</th><th>销量</th><th>操作</th></tr></thead><tbody><trth:each="product : ${products}"><tdth:text="${product.id}"></td><tdth:text="${product.productId}"></td><tdth:text="${product.productName}"></td><tdth:text="${product.price}"></td><tdth:text="${product.sales}"></td><td><ath:href="@{/api/products/edit/{id}(id=${product.id})}">编辑</a><ath:href="@{/api/products/delete/{id}(id=${product.id})}">删除</a></td></tr></tbody></table><h2>产品销量图表</h2><divid="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('[('+ product.productName +')]'); productSales.push('[('+ product.sales +')]');</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: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:[(' + product.sales + ')],name:'[('+ product.productName +')']},</th:block>]}]};// 渲染图表 option && myChart.setOption(option);</script></body></html>应用启动类:
importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublicclassEChartsApplication{publicstaticvoidmain(String[] args){SpringApplication.run(EChartsApplication.class, args);}}测试类:
importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.boot.test.web.client.TestRestTemplate;importorg.springframework.boot.web.server.LocalServerPort;importstaticorg.assertj.core.api.Assertions.assertThat;@SpringBootTest(webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)classEChartsApplicationTests{@LocalServerPortprivateint port;@AutowiredprivateTestRestTemplate restTemplate;@TestvoidcontextLoads(){}@TestvoidtestGetAllProducts(){String response = restTemplate.getForObject("http://localhost:"+ port +"/api/products/",String.class);assertThat(response).contains("产品列表");}}✅ 结论:集成ECharts的步骤包括创建Spring Boot项目、添加所需的依赖、配置ECharts、创建数据访问层、创建业务层、创建控制器类、创建前端页面、测试应用。
27.4 Spring Boot的实际应用场景
在实际开发中,Spring Boot数据可视化与图表集成的应用场景非常广泛,如:
- 实现产品信息的图表展示。
- 实现用户信息的图表展示。
- 实现订单信息的图表展示。
- 实现销售数据的图表展示。
示例:
importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Controller;importorg.springframework.ui.Model;importorg.springframework.web.bind.annotation.*;importjava.util.List;@Controller@RequestMapping("/api/products")classProductController{@AutowiredprivateProductService productService;@GetMapping("/")publicStringgetAllProducts(Model model){List<Product> products = productService.getAllProducts(); model.addAttribute("products", products);return"product-list";}@GetMapping("/{id}")publicStringgetProductById(@PathVariableLong id,Model model){Product product = productService.getProductById(id); model.addAttribute("product", product);return"product-detail";}@GetMapping("/add")publicStringaddProductForm(Model model){ model.addAttribute("product",newProduct());return"product-form";}@PostMapping("/add")publicStringaddProduct(@ModelAttributeProduct product){ productService.addProduct(product);return"redirect:/api/products/";}@GetMapping("/edit/{id}")publicStringeditProductForm(@PathVariableLong id,Model model){Product product = productService.getProductById(id); model.addAttribute("product", product);return"product-form";}@PostMapping("/edit/{id}")publicStringeditProduct(@PathVariableLong id,@ModelAttributeProduct product){ product.setId(id); productService.updateProduct(product);return"redirect:/api/products/";}@GetMapping("/delete/{id}")publicStringdeleteProduct(@PathVariableLong id){ productService.deleteProduct(id);return"redirect:/api/products/";}}@ServiceclassProductService{@AutowiredprivateProductRepository productRepository;publicList<Product>getAllProducts(){return productRepository.getAllProducts();}publicProductgetProductById(Long id){return productRepository.getProductById(id);}publicvoidaddProduct(Product product){ productRepository.addProduct(product);}publicvoidupdateProduct(Product product){ productRepository.updateProduct(product);}publicvoiddeleteProduct(Long id){ productRepository.deleteProduct(id);}}@RepositoryclassProductRepository{privateList<Product> products =newArrayList<>();publicProductRepository(){ products.add(newProduct(1L,"P001","手机",1000.0,100)); products.add(newProduct(2L,"P002","电脑",5000.0,50)); products.add(newProduct(3L,"P003","电视",3000.0,80)); products.add(newProduct(4L,"P004","手表",500.0,200)); products.add(newProduct(5L,"P005","耳机",300.0,150));}publicList<Product>getAllProducts(){return products;}publicProductgetProductById(Long id){return products.stream().filter(product -> product.getId().equals(id)).findFirst().orElse(null);}publicvoidaddProduct(Product product){ product.setId((long)(products.size()+1)); products.add(product);}publicvoidupdateProduct(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());}}publicvoiddeleteProduct(Long id){ products.removeIf(product -> product.getId().equals(id));}}@SpringBootApplicationpublicclassEChartsApplication{publicstaticvoidmain(String[] args){SpringApplication.run(EChartsApplication.class, args);}}// 测试类@SpringBootTest(webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)classEChartsApplicationTests{@LocalServerPortprivateint port;@AutowiredprivateTestRestTemplate restTemplate;@TestvoidcontextLoads(){}@TestvoidtestGetAllProducts(){String response = restTemplate.getForObject("http://localhost:"+ port +"/api/products/",String.class);assertThat(response).contains("产品列表");}}输出结果:
- 访问http://localhost:8080/api/products/:返回产品列表页面,包含产品销量图表。
- 点击“添加产品”:跳转到添加产品页面。
- 点击“编辑”:跳转到编辑产品页面。
- 点击“删除”:删除产品。
✅ 结论:在实际开发中,Spring Boot数据可视化与图表集成的应用场景非常广泛,需要根据实际问题选择合适的图表工具。
总结
本章我们学习了Spring Boot数据可视化与图表集成,包括数据可视化的定义与特点、图表工具的定义与特点、Spring Boot与图表工具的集成、Spring Boot的实际应用场景,学会了在实际开发中处理数据可视化与图表集成问题。其中,数据可视化的定义与特点、图表工具的定义与特点、Spring Boot与图表工具的集成、Spring Boot的实际应用场景是本章的重点内容。从下一章开始,我们将学习Spring Boot的其他组件、微服务等内容。