如何用SpringBoot+Thymeleaf+Echart生成好看的柱状图,折线图,饼状图
一、前言
上篇文章我们用POI技术读取Excel并生成了相应的图表。但是实际的效果比较一般,因为本身WPS生成图表就比较简单,如果用程序操作远比人工耗时费力,效果远不如一些付费模板。如下图所示:
然后我就想到前端不是有一个简单易上手的Echart.js是专门做图表。所以就用它去做图表生成,后台数据解析还是用springBoot+Ajax+POI工具类。这样实现的效果就会好看和实用很多。来看一下效果图。
二、准备数据
1、首先新建一个xls统计表。
2、数据填充
手机型号 测评分数 销售数量
OPPO Reno9 Pro+ 5G 1210365 7523423
Xiaomi 12 Pro天现版 1187600 343242
ROG游戏手机6 天现至尊版 1187449 535362
一加 Ace Pro 1183234 83234
小米12S Pro 1176850 2346625
Redmi K50 至尊版 1172517 4324324
Xiaomi 12S 1164309 3424234
联想救者 Y90 1164235 234434
小米MIX FOLD 2 1164109 32423432
iQo0 10 Pro 1151258 9403424
三、前端代码
<!DOCTYPE html>
<html>
<head><meta charset="utf-8" /><title>ECharts</title><!-- 引入刚刚下载的 ECharts 文件 --><!-- <script src="https://cdn.staticfile.org/jquery/3.6.1/jquery.min.js"></script>--><!-- 引入 echarts.js --><!-- <script src="https://cdn.staticfile.org/echarts/5.3.0/echarts.min.js"></script>--><script src="./js/echarts.min.js"></script><script src="./js/jquery-3.6.1.min.js"></script></head>
<body>
<div id="title" style="width:1200px;height:100px"></div>
<!-- 为 ECharts 准备一个定义了宽高的 DOM -->
<div id="line" style="width: 1200px;height:800px;"></div>
<div id="pie" style="width: 1200px;height:800px;"></div>
<div id="bak" style="width:200px;height:100px"></div>
<div id="bar" style="width: 1200px;height:800px;"></div><script type="text/javascript">var title = echarts.init(document.getElementById('title'));// 基于准备好的dom,初始化echarts实例var myChart = echarts.init(document.getElementById('bar'));var pieChart = echarts.init(document.getElementById('pie'));var lineChart = echarts.init(document.getElementById('line'));var titleOption = {graphic: {elements: [{type: 'text',left: 'center',top: 'center',style: {text: '手机性能统计图',fontSize: 50,fontWeight: 'bold',lineDash: [0, 200],lineDashOffset: 0,fill: 'transparent',stroke: '#000',lineWidth: 1},keyframeAnimation: {duration: 3000,loop: true,keyframes: [{percent: 0.7,style: {fill: 'transparent',lineDashOffset: 200,lineDash: [200, 0]}},{// Stop for a while.percent: 0.8,style: {fill: 'transparent'}},{percent: 1,style: {fill: 'gray'}}]}}]}};$.ajax({type:"post",async:true,url:"/getData",dataType:"json",success:function (data) {if (data) {// 指定图表的配置项和数据var barOption = {title: {text: '手机性能柱状统计图'},tooltip: {},legend: {data: ['手机性能柱状统计图']},xAxis: {data: data[0].key,},yAxis: {},color: '#fac858',series: [{name: '评测分数',type: 'bar',data: data[0].value,}]};// 指定图表的配置项和数据var lineOption = {title: {text: '折线柱状统计图'},tooltip: {},legend: {data: ['品牌销量', '品牌评测分数']},xAxis: {data: data[0].key,},yAxis: {type: "log",},series: [{name: '品牌销量',type: 'line',data: data[1].value}, {name: '品牌评测分数',type: 'line',data: data[0].value}]};var pieOption = {title: {text: '品牌销量占比饼状图'},tooltip: {trigger: 'item'},legend: {top: '85%',left: 'center'},series: [{name: '品牌销量占比饼状图',type: 'pie',radius: ['30%', '70%'],avoidLabelOverlap: false,itemStyle: {borderRadius: 10,borderColor: '#fff',borderWidth: 2},label: {show: false,position: 'center'},emphasis: {label: {show: true,fontSize: 40,fontWeight: 'bold'}},labelLine: {show: false},data: data[2]}]};title.setOption(titleOption);// 使用刚指定的配置项和数据显示图表。myChart.setOption(barOption);lineChart.setOption(lineOption);pieChart.setOption(pieOption);}},error:function (errorMsg) {alert("图表请求数据失败!");myChart.hideLoading();totalChart.hideLoading();lineChart.hideLoading();pieChart.hideLoading();}
});
</script>
</body>
</html>
其中需要注意的是js依赖文件可以本地下载好引用本地。–适用于内网
或者将注释打开,直接从互联网依赖。–适用于外网
使用div布局,绑定各组件变量
标题组件定义
ajax异步请求及组件定义
绑定组件及ajax请求失败的处理方式。
四、后端代码
还是创建一个springboot功能。
1、配置文件application.yaml
server:port: 9999
resources:static-locations: classpath:/templates/, classpath:/static/
thymeleaf:prefix: classpath:/templates/ #thģ������·��suffix: .htmlmode: HTML5encoding: UTF-8cache: false
2、pom依赖
<?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><groupId>com.icbc</groupId><artifactId>echartdemo</artifactId><version>1.0-SNAPSHOT</version><name>boottest</name><!-- FIXME change it to the project's website --><url>http://www.example.com</url><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.7.RELEASE</version></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.7</maven.compiler.source><maven.compiler.target>1.7</maven.compiler.target><poi-version>3.11</poi-version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.lucee</groupId><artifactId>jsch</artifactId><version>0.1.53</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.25</version></dependency><!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.25</version><!-- <scope>test</scope> --></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.11</version></dependency><dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId><version>1.14</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId><version>4.1.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-scratchpad</artifactId><version>4.1.2</version></dependency><dependency><groupId>org.apache.xmlbeans</groupId><artifactId>xmlbeans</artifactId><version>3.1.0</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>ooxml-schemas</artifactId><version>1.4</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.36</version></dependency></dependencies><build><pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --><plugins><!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle --><plugin><artifactId>maven-clean-plugin</artifactId><version>3.1.0</version></plugin><!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging --><plugin><artifactId>maven-resources-plugin</artifactId><version>3.0.2</version></plugin><plugin><artifactId>maven-compiler-plugin</artifactId><version>3.8.0</version></plugin><plugin><artifactId>maven-surefire-plugin</artifactId><version>2.22.1</version></plugin><plugin><artifactId>maven-jar-plugin</artifactId><version>3.0.2</version></plugin><plugin><artifactId>maven-install-plugin</artifactId><version>2.5.2</version></plugin><plugin><artifactId>maven-deploy-plugin</artifactId><version>2.8.2</version></plugin><!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle --><plugin><artifactId>maven-site-plugin</artifactId><version>3.7.1</version></plugin><plugin><artifactId>maven-project-info-reports-plugin</artifactId><version>3.0.0</version></plugin></plugins></pluginManagement><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target></configuration></plugin></plugins></build>
</project>
3、在resource下创建templates目录,并将html放入
4、启动类
package com.icbc.echartdemo;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class EchartdemoApplication {public static void main(String[] args) {SpringApplication.run(EchartdemoApplication.class, args);}}
5、excel数据处理工具类
package com.icbc.echartdemo;import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xddf.usermodel.PresetColor;
import org.apache.poi.xddf.usermodel.XDDFColor;
import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xssf.usermodel.*;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTDLbls;import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;/*** ClassName: ExcelChartUtils <br/>* Description: 导出excel中绘制图表<br/>* date: 2022/11/17 11:39<br/>** @author DELL<br />* @since JDK 1.8*/
public class ExcelChartUtils2 {public static final String READ_FILE_PATH = "C:\\Users\\Administrator\\Desktop\\统计.xls";public static void main(String[] args) throws IOException {ExcelChartUtils2 excelChartUtils=new ExcelChartUtils2();XSSFWorkbook wb = new XSSFWorkbook();
// String sheetName = "当月业务量统计";
// String sheetName2 = "本周高频报错业务统计";
// String sheetName3 = "本周高频报错占比统计";
// excelChartUtils.exportLineDiagram(wb,sheetName2);
// excelChartUtils.exportPieDirgram(wb,sheetName3);
// excelChartUtils.exportBarDiagram(wb,sheetName);}public void exportPieDirgram(XSSFWorkbook wb,String sheetName){XSSFSheet sheet = wb.createSheet(sheetName);// 创建一个画布XSSFDrawing drawing = sheet.createDrawingPatriarch();// 前四个默认0,[0,4]:从0列4行开始;[7,20]:到7列20行结束// 默认宽度(14-8)*12XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 0, 30, 40);// 创建一个chart对象XSSFChart chart = drawing.createChart(anchor);// 标题chart.setTitleText("高频报错占比统计");// 标题是否覆盖图表chart.setTitleOverlay(false);// 图例位置XDDFChartLegend legend = chart.getOrAddLegend();legend.setPosition(LegendPosition.TOP_RIGHT);//解析数据Map<String, List<String>> dataMap = ExcelChartUtils2.getData(READ_FILE_PATH,3,0,6);;List<String> keylist = dataMap.get("key");List<String> valueList = dataMap.get("value");List<Integer> vList = new ArrayList<>();for(int i = 0;i<valueList.size();i++){if(valueList.get(i).isEmpty()){vList.add(0);}else{vList.add(Integer.valueOf(valueList.get(i).split("\\.")[0]));}}//XDDFDataSource<String> countries = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(0, 0, 0, 6));//从指定表格中的位置上获取对应数据XDDFCategoryDataSource countries = XDDFDataSourcesFactory.fromArray(keylist.toArray(new String[keylist.size()]));// 数据1,单元格范围位置[1, 0]到[1, 6]// XDDFNumericalDataSource<Double> area = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 1, 0, 6));XDDFNumericalDataSource<Integer> area = XDDFDataSourcesFactory.fromArray(vList.toArray(new Integer[vList.size()]));// XDDFChartData data = chart.createData(ChartTypes.PIE3D, null, null);XDDFChartData data = chart.createData(ChartTypes.PIE, null, null);// 设置为可变颜色data.setVaryColors(true);// 图表加载数据data.addSeries(countries, area);// 绘制chart.plot(data);CTDLbls dLbls = chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).addNewDLbls();dLbls.addNewShowVal().setVal(false);dLbls.addNewShowLegendKey().setVal(false);dLbls.addNewShowCatName().setVal(true);// 类别名称dLbls.addNewShowSerName().setVal(false);dLbls.addNewShowPercent().setVal(true);// 百分比dLbls.addNewShowLeaderLines().setVal(true);// 引导线dLbls.setSeparator("\n");// 分隔符为分行符dLbls.addNewDLblPos().setVal(org.openxmlformats.schemas.drawingml.x2006.chart.STDLblPos.Enum.forString("inEnd"));// 数据标签内// 打印图表的xml// System.out.println(chart.getCTChart());}public void exportLineDiagram(XSSFWorkbook wb,String sheetName) throws IOException {FileOutputStream fileOut = null;XSSFSheet sheet = wb.createSheet(sheetName);// 创建一个画布XSSFDrawing drawing = sheet.createDrawingPatriarch();// 前四个默认0,[0,5]:从0列5行开始;[7,26]:到7列26行结束// 默认宽度(14-8)*12XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 0, 30, 40);// 创建一个chart对象XSSFChart chart = drawing.createChart(anchor);// 标题chart.setTitleText("高频报错业务统计");// 标题覆盖chart.setTitleOverlay(false);// 图例位置XDDFChartLegend legend = chart.getOrAddLegend();legend.setPosition(LegendPosition.TOP);// 分类轴标(X轴),标题位置XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.LEFT);// bottomAxis.setTitle("国家");// 值(Y轴)轴,标题位置XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.BOTTOM);// leftAxis.setTitle("面积大小");Map<String, List<String>> dataMap = ExcelChartUtils2.getData(READ_FILE_PATH,3,2,6);List<String> keylist = dataMap.get("key");List<String> valueList = dataMap.get("value");List<Integer> vList = new ArrayList<>();for(int i = 0;i<valueList.size();i++){if(valueList.get(i).isEmpty()){vList.add(0);}else{vList.add(Integer.valueOf(valueList.get(i).split("\\.")[0]));}}
// keylist.remove(0);
// valueList.remove(0);// CellRangeAddress(起始行号,终止行号, 起始列号,终止列号)// 分类轴标(X轴)数据,单元格范围位置[0, 0]到[0, 6]//XDDFDataSource<String> countries = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(0, 0, 0, 6));//从指定表格中的位置上获取对应数据XDDFCategoryDataSource countries = XDDFDataSourcesFactory.fromArray(keylist.toArray(new String[keylist.size()]));// 数据1,单元格范围位置[1, 0]到[1, 6]// XDDFNumericalDataSource<Double> area = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 1, 0, 6));XDDFNumericalDataSource<Integer> area = XDDFDataSourcesFactory.fromArray(vList.toArray(new Integer[vList.size()]));// bar:条形图,XDDFLineChartData bar = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);// 设置为可变颜色bar.setVaryColors(false);// 如果需要设置成自己想要的颜色,这里可变颜色要设置成false// 图表加载数据,条形图XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) bar.addSeries(countries, area);// 条形图例标题series1.setTitle("业务量统计", null);XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(PresetColor.BLUE));// 条形图,填充颜色series1.setFillProperties(fill);// 绘制chart.plot(bar);// CTBarSer ser = chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(0);// CTLegend legend2 = chart.getCTChartSpace().getChart().getLegend();//更详细的图例设置// 打印图表的xmlSystem.out.println(chart.getCTChart());}public String exportBarDiagram(XSSFWorkbook wb,String sheetName) throws IOException {FileOutputStream fileOut = null;try {XSSFSheet sheet = wb.createSheet(sheetName);// 创建一个画布XSSFDrawing drawing = sheet.createDrawingPatriarch();// 前四个默认0,[0,5]:从0列5行开始;[7,26]:到7列26行结束// 默认宽度(14-8)*12XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 0, 30, 40);// 创建一个chart对象XSSFChart chart = drawing.createChart(anchor);// 标题chart.setTitleText("业务量统计");// 标题覆盖chart.setTitleOverlay(false);// 图例位置XDDFChartLegend legend = chart.getOrAddLegend();legend.setPosition(LegendPosition.TOP);// 分类轴标(X轴),标题位置XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);// bottomAxis.setTitle("国家");// 值(Y轴)轴,标题位置XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);// leftAxis.setTitle("面积大小");Map<String, List<String>> dataMap = ExcelChartUtils2.getData(READ_FILE_PATH,4,2,6);List<String> keylist = dataMap.get("key");List<String> valueList = dataMap.get("value");List<Integer> vList = new ArrayList<>();for(int i = 0;i<valueList.size();i++){if(valueList.get(i).isEmpty()){vList.add(0);}else{vList.add(Integer.valueOf(valueList.get(i).split("\\.")[0]));}}
// keylist.remove(0);
// valueList.remove(0);// CellRangeAddress(起始行号,终止行号, 起始列号,终止列号)// 分类轴标(X轴)数据,单元格范围位置[0, 0]到[0, 6]//XDDFDataSource<String> countries = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(0, 0, 0, 6));//从指定表格中的位置上获取对应数据XDDFCategoryDataSource countries = XDDFDataSourcesFactory.fromArray(keylist.toArray(new String[keylist.size()]));// 数据1,单元格范围位置[1, 0]到[1, 6]// XDDFNumericalDataSource<Double> area = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 1, 0, 6));XDDFNumericalDataSource<Integer> area = XDDFDataSourcesFactory.fromArray(vList.toArray(new Integer[vList.size()]));// bar:条形图,XDDFBarChartData bar = (XDDFBarChartData) chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);// 设置为可变颜色bar.setVaryColors(false);// 如果需要设置成自己想要的颜色,这里可变颜色要设置成false// 条形图方向,纵向/横向:纵向bar.setBarDirection(BarDirection.COL);// 图表加载数据,条形图1XDDFBarChartData.Series series1 = (XDDFBarChartData.Series) bar.addSeries(countries, area);// 条形图例标题series1.setTitle("业务量统计", null);XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(PresetColor.BLUE));// 条形图,填充颜色series1.setFillProperties(fill);// 绘制chart.plot(bar);// CTBarSer ser = chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(0);// CTLegend legend2 = chart.getCTChartSpace().getChart().getLegend();//更详细的图例设置// 打印图表的xmlSystem.out.println(chart.getCTChart());// 将输出写入excel文件// String filename = "排行榜前七的国家.xlsx";// out = new FileOutputStream(getAbsoluteFile(filename));String filename = encodingFilename();fileOut = new FileOutputStream("E:\\"+File.separator+filename);wb.write(fileOut);} catch (Exception e) {e.printStackTrace();} finally {wb.close();if (fileOut != null) {fileOut.close();}}return "success";}public static Map<String,List<String>> getData(String filePath, int sheetIndex,int keyNum,int valueNum){Map<String, List<String>> resMap = new HashMap<>();FileInputStream fis = null;HSSFWorkbook workbook = null;List<String> keylist = new ArrayList();List<String> valueList = new ArrayList<>();try {fis = new FileInputStream(filePath);workbook = new HSSFWorkbook(fis);Sheet sheet = workbook.getSheetAt(sheetIndex);Row row;Cell cell;for (int i = 1; i < sheet.getLastRowNum(); i++) {row = sheet.getRow(i);cell = row.getCell(keyNum); // 0 is the column indexSystem.out.println(cell.getStringCellValue());keylist.add(cell.getStringCellValue());cell = row.getCell(valueNum); // 0 is the column indexdouble numericCellValue;if(cell.getCellType().equals(CellType.NUMERIC)){numericCellValue = cell.getNumericCellValue();}else {numericCellValue = Double.valueOf(cell.getStringCellValue());}valueList.add( String.valueOf(numericCellValue) );}System.out.println("name:"+keylist);System.out.println("value:"+valueList);workbook.close();fis.close();} catch (IOException e) {e.printStackTrace();}
// resMap.put("key",keylist.toArray(new String[keylist.size()]));
// resMap.put("value",valueList.toArray(new String[valueList.size()]));resMap.put("key",keylist);resMap.put("value",valueList);return resMap;}/*** 编码文件名*/public String encodingFilename(){String filename = UUID.randomUUID().toString() + ".xlsx";//String filename = "20230222.xlsx";return filename;}/*** 获取下载路径** @param filename 文件名称*/public String getAbsoluteFile(String filename){String downloadPath = "d://";File desc = new File(downloadPath);if (!desc.getParentFile().exists()){desc.getParentFile().mkdirs();}return downloadPath;}
}
6、controller处理类
package com.icbc.echartdemo;import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;import java.util.ArrayList;
import java.util.List;
import java.util.Map;import static com.icbc.echartdemo.ExcelChartUtils2.READ_FILE_PATH;/*** @Author stalin* @Desc Echarts入门案例*/
@RestController
public class EchartController {@RequestMapping(value = "/echarts", method = RequestMethod.GET)@ResponseBodypublic ModelAndView echarts() {//test为在为你的html文件名字,SpringBoot会自动找到这个html文件return new ModelAndView("echart");}@RequestMapping("/getData")@ResponseBodypublic JSONArray getData() {List<ReportData> dataList = new ArrayList<>();Map<java.lang.String, List<java.lang.String>> dataMap = ExcelChartUtils2.getData(READ_FILE_PATH, 0, 0, 1);JSONArray arr = new JSONArray();JSONObject obj = new JSONObject();obj.put("key", dataMap.get("key"));obj.put("value", dataMap.get("value"));Map<java.lang.String, List<java.lang.String>> dataMap2 = ExcelChartUtils2.getData(READ_FILE_PATH, 0, 0, 2);arr.clear();arr.add(obj);JSONObject obj2 = new JSONObject();obj2.put("key", dataMap2.get("key"));obj2.put("value", dataMap2.get("value"));arr.add(obj2);JSONArray array = new JSONArray();List<String> key = dataMap.get("key");List<String> value = dataMap.get("value");for (int i = 0; i < key.size(); i++) {JSONObject o = new JSONObject();o.put("name", key.get(i));o.put("value", value.get(i));array.add(o);}arr.add(array);return arr;}// @RequestMapping(value = "/index", method = RequestMethod.GET)
// @ResponseBody
// public ModelAndView index() {
// //test为在为你的html文件名字,SpringBoot会自动找到这个html文件
// return new ModelAndView("index");
// }
}
注意:html名字与要返回的ModelAndView名字要一致。否则后端程序会找不到对应的页面。
然后启动项目即可。
相关文章:

如何用SpringBoot+Thymeleaf+Echart生成好看的柱状图,折线图,饼状图
一、前言 上篇文章我们用POI技术读取Excel并生成了相应的图表。但是实际的效果比较一般,因为本身WPS生成图表就比较简单,如果用程序操作远比人工耗时费力,效果远不如一些付费模板。如下图所示: 然后我就想到前端不是有一个简单易…...
LeetCode819. 最常见的单词(python)
题目 给定一个段落 (paragraph) 和一个禁用单词列表 (banned)。返回出现次数最多,同时不在禁用列表中的单词。 题目保证至少有一个词不在禁用列表中,而且答案唯一。 禁用列表中的单词用小写字母表示,不含标点符号。段落中的单词不区分大小写。…...

【深入理解C指针】经典笔试题——指针和数组
🔹内容专栏:【C语言】进阶部分 🔹本文概括:一些指针和数组笔试题的解析 。 🔹本文作者:花香碟自来_ 🔹发布时间:2023.3.12 目录 一、指针和数组练习题 1. 一维数组 2. 字符数组 …...
雷达散射截面
雷达散射截面(Radar Cross Section, RCS)是表征目标散射强弱的物理量。 σ = 4 π R 2 ∣ E s ∣ 2 ∣ E i ∣ 2 \sigma = 4\pi R^2 \frac{|E_s |^2}{|E_i|^2}...
希腊棺材之谜——复盘
文章目录梗概推导伪解答虽然花费6-8小时来看小说,是一件很奢侈的事情。但是再荒诞的事情终归有它背后的逻辑链条。这正如Ellery所坚持的那样,逻辑为王。希腊棺材之谜是Ellery Queen首次展露头角, 因此作者特地给他安排了3次伪解答和1次真解答…...

CentOS的下载和安装
文章目录前言一、CentOS的下载二、如何下载1.选择下载版本2.选择isos3.点击isos后,进入如下页面,接着点击X86_644.一般选择下面框住的进行下载三、安装软件选择设置接着进行分区设置设置网络和主机名前言 在学习Linux时,记录下CentOS的安装 …...

new bing的chatGPT如何解析英文论文pdf
昨天我的new bing申请下来了,有了聊天的界面: 但是解析pdf的英文文献,还是不行,没有对话窗口。就问了一下chatGPT,方案如下: 要使用New Bing解析PDF文献,你需要以下几个步骤: 1&a…...

学会这12个Python装饰器,让你的代码更上一层楼
学会这12个Python装饰器,让你的代码更上一层楼 Python 装饰器是个强大的工具,可帮你生成整洁、可重用和可维护的代码。某种意义上说,会不会用装饰器是区分新手和老鸟的重要标志。如果你不熟悉装饰器,你可以将它们视为将函数作为输…...

企业使用ERP的好处
ERP系统是企业管理信息系统的简称,它是以信息技术为手段,以物流、资金流、信息流为主线,以企业的核心业务流程为对象,建立的一套适用于企业管理的、高效的企业管理信息系统。它是通过科学方法和计算机信息技术,将企业运…...
【QT】如何获取屏幕(桌面)的大小或分辨率
目录1. QDesktopWidget 获取系统屏幕大小2. QScreen 获取系统屏幕大小3. geometry() 与 availableGeometry() 的区别1. QDesktopWidget 获取系统屏幕大小 QDesktopWidget 提供了详细的位置信息,其能够自动返回窗口在用户窗口的位置和应用程序窗口的位置 QDesktopW…...
ETL工具的选择
正确选择 ETL 工具,可以从 ETL 对平台的支持、对数据源的支持、数据转换功能、管理 和调度功能、集成和开放性、对元数据管理等功能出发,具体如下。 支持平台 随着各种应用系统数据量的飞速增长和对业务可靠性等要求的不断提高,人们对数据抽…...

SpringBoot仿天猫商城java web购物网站的设计与实现
1,项目介绍 基于 SpringBoot 的仿天猫商城拥有两种角色,分别为管理员和用户。 迷你天猫商城是一个基于SSM框架的综合性B2C电商平台,需求设计主要参考天猫商城的购物流程。 后端页面兼容IE10及以上现代浏览器,Chrome,Edge,Firebox…...
C#基础教程22 文件的输入与输出
C# 文件的输入与输出 一个 文件 是一个存储在磁盘中带有指定名称和目录路径的数据集合。当打开文件进行读写时,它变成一个 流。 从根本上说,流是通过通信路径传递的字节序列。有两个主要的流:输入流 和 输出流。输入流用于从文件读取数据(读操作),输出流用于向文件写入数…...
Ubuntu18.04 python 开发usb通信
一、安装环境 1.安装pip sudo python3 get-pip.py 或 sudo -i apt update apt install python3-pip 确定pip是否安装成功: xxx-desktop:~$ pip3 --versionpip 9.0.1 from /usr/lib/python3/dist-packages (python 3.6)2.安装pyusb pip3 install pyusb --use…...

RabbitMq 消息确认机制详解 SpringCloud
1 消息可靠性 消息从发送,到消费者接收,会经理多个过程,其中的每一步都可能导致消息丢失. #### 2 常见的丢失原因 发送时丢失: 生产者发送的消息未送达exchange 消息到达exchange后未到达queueMQ宕机,queue将消息丢失 consumer…...
后台导航布局
五、后台导航实例 参考链接: 页面后台导航制作 如何实现html后台导航iframe点击换url(代码) 如何消除html页面下边和右边的滚动条 html页面有多个滚动条时的优化 页面出现不必要的滚动条,怎么调试? 一个页面有两…...

设计模式——抽象工厂模式(创建型)
一、介绍抽象工厂模式是一种创建型设计模式, 它能创建一系列相关的对象, 而无需指定其具体类。问题假设你正在开发一款家具商店模拟器。 你的代码中包括一些类, 用于表示:一系列相关产品, 例如 椅子Chair 、 沙发Sofa和…...

Java面试题--SpringMVC的执行流程
概要 SpringMVC是一种基于MVC(Model-View-Controller)框架的Web应用开发框架。下面是SpringMVC的详细执行流程。 客户端向DispatcherServlet发送请求。DispatcherServlet收到请求后,根据HandlerMapping(处理器映射)找…...

c# 32位程序突破2G内存限制
起因 在开发过程中,由于某些COM组件只能在32位程序下运行,程序不得不在X86平台下生成。而X86的32位程序默认内存大小被限制在2G。由于程序中可能存在大数量处理,期间对象若没有及时释放或则回收,内存占用达到了1.2G左右ÿ…...

【C语言】指针详解总结
指针1. 指针是什么2. 指针和指针类型2.1 指针-整数2.2 指针的解引用3. 野指针3.1 野指针成因3.2 如何规避野指针4. 指针运算4.1 指针-整数4.2 指针-指针4.3 指针的关系运算5. 指针和数组6. 二级指针7. 指针数组1. 指针是什么 指针是什么? 指针理解的2个要点…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...

Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...

UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...

让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...

Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...

网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...