EasyExcel和Echarts的碰撞
题外话:最近在学习EasyExcel知识的时候,就想着如何把Excel数据导入我们的数据库里面,然后再如何把Excel表格里面的数据再更加直观的在网页中显示出来,这时候脑海里就突然想试试Echarts,于是就开始了这个小实验
附上语雀笔记,这里有完整的代码介绍:https://www.yuque.com/xiaoqian-paazl/pwc7tt/etdca557p256wzre?singleDoc#
先附上我的实现效果叭✿✿ヽ(°▽°)ノ✿




1、了解EasyExcel
在开始小实验之前,我们要先了解一下什么是EasyExcel。在我们处理Excel表格的时候,Apache先给了我们一个工具来使用就是poi,这个poi写起来有点繁杂,甚至繁琐,还占用内存,容易OOM,这时候阿里就基于POI开发出EasyExcel,用起来还是很方便的(还有一个hutool-poi也可以处理,但是我还没仔细学习)具体使用可以参考EasyExcel官方文档:https://easyexcel.opensource.alibaba.com/docs/current/
附上Echarts文档:https://echarts.apache.org/handbook/zh/basics/download/
1、前端主要核心代码
通过ajax发送请求,用户点击上传按钮后,前端JavaScript代码将文件通过AJAX请求发送到后端的 /api/upload 接口,这是进行将前端页面上的文件上传表单选择要导入的Excel文件。请求处理 :前端使用jQuery的AJAX功能,将MultipartFile类型的文件数据发送到后端。
▼text复制代码$.ajax({ url: '/api/upload', type: 'POST', data: formData, contentType: false, processData: false, success: function(response) { document.getElementById('message').textContent = '上传成功!'; document.getElementById('message').style.color = 'green'; // 上传成功后重新加载图表 loadCharts(); }, error: function() { document.getElementById('message').textContent = '上传失败,请重试'; document.getElementById('message').style.color = 'red'; } }); });
▼plain复制代码// 加载图表数据 function loadCharts() { $.ajax({ url: '/api/employees', type: 'GET', success: function(employees) { // 处理工资图表 updateSalaryChart(employees); // 处理员工统计图表 updateCountChart(employees); }, error: function() { console.error('获取员工数据失败'); } }); }
这里就是Echarts知识
▼plain复制代码// 更新工资图表 function updateSalaryChart(employees) { const names = employees.map(emp => emp.name); const salaries = employees.map(emp => emp.salary); salaryChart.setOption({ title: { text: '员工工资对比', left: 'center' }, tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } }, xAxis: { type: 'category', data: names, axisLabel: { rotate: 45 } }, yAxis: { type: 'value', name: '工资' }, series: [{ data: salaries, type: 'bar', itemStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ {offset: 0, color: '#83bff6'}, {offset: 0.5, color: '#188df0'}, {offset: 1, color: '#188df0'} ]) } }] }); }
▼plain复制代码// 更新员工薪资图表 function updateCountChart(employees) { const names = employees.map(emp => emp.name); const salaries = employees.map(emp => emp.salary); countChart.setOption({ title: { text: '员工薪资折线图', left: 'center' }, tooltip: { trigger: 'axis' }, xAxis: { type: 'category', data: names }, yAxis: { type: 'value', name: '工资' }, series: [{ data: salaries, type: 'line', smooth: true, itemStyle: { color: '#ff7f50' }, areaStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ {offset: 0, color: 'rgba(255,127,80,0.8)'}, {offset: 1, color: 'rgba(255,127,80,0.1)'} ]) } }] }); }
2、后端代码
2.1 Controller层
▼plain复制代码@RestController @RequestMapping("/api") public class MyController { @GetMapping("/") public String index() { return "index"; // 指向resources/static/index.html } @Resource private EmployeeService employeeService; @PostMapping("/upload") @ResponseBody public String upload(MultipartFile file) throws IOException { EasyExcel.read(file.getInputStream(), Employee.class, new EmployeeListener(employeeService)).sheet().doRead(); return "success"; } // 获取所有员工数据,用于ECharts展示 @GetMapping("/employees") public List<Employee> getAllEmployees() { return employeeService.getAllEmployees(); } }
当我们在前端点击上传文件之后,ajax发送请求,调用upload接口,这时候就初始化EasyExcel :控制器调用 EasyExcel.read() 方法,传入以下参数:
○ 文件输入流( file.getInputStream() )
○ 目标实体类类型( Employee.class )
○ 自定义监听器实例( new EmployeeListener(employeeService) )
在创建监听器时,通过构造函数注入了 EmployeeService 实例,以便后续进行数据库操作
2.2 Service层
▼plain复制代码public interface EmployeeService extends IService<Employee> { /** * 批量导入员工数据 * @param employees 员工数据列表 * @return 是否导入成功 */ boolean importEmployees(List<Employee> employees); /** * 获取所有员工数据 * @return 员工数据列表 */ List<Employee> getAllEmployees(); }
▼plain复制代码@Service public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements EmployeeService{ /** * 批量导入员工数据 * @param employees 员工数据列表 * @return 是否导入成功 */ @Override @Transactional(rollbackFor = Exception.class) public boolean importEmployees(List<Employee> employees) { if (employees == null || employees.isEmpty()) { return false; } // 使用MyBatis-Plus的批量插入方法,提高插入效率 return this.saveBatch(employees, 1000); // 每批处理1000条数据 } /** * 获取所有员工数据 * @return 员工数据列表 */ @Override public List<Employee> getAllEmployees() { return this.list(); } }
2.3📕监听器设置(重点!!)
- 逐行读取 :EasyExcel逐行读取Excel数据,每读取一行就调用 EmployeeListener 的 invoke 方法。
- 数据收集 : invoke 方法将解析后的Employee对象添加到临时集合 employeeArrayList 中。
- 批量处理 :当集合大小达到设定的批处理阈值(BATCH_SIZE=100)时,触发批量插入操作:
- 调用 employeeService.importEmployees(employeeArrayList) 方法
- 清空集合,为下一批数据做准备
▼plain复制代码/** * 自定义监听器读数据 */ public class EmployeeListener implements ReadListener<Employee> { private static final int BATCH_SIZE = 100; private ArrayList<Employee> employeeArrayList = new ArrayList<>(BATCH_SIZE); private EmployeeService employeeService; // 无参构造函数,Spring需要 public EmployeeListener() { // 实际使用中会通过有参构造函数注入employeeService } // 有参构造函数,用于注入EmployeeService public EmployeeListener(EmployeeService employeeService) { this.employeeService = employeeService; } //invoke 是每读一行数据,都会调用这个方法 @Override public void invoke(Employee employee, AnalysisContext analysisContext) { //将读取到的这一行添加到集合 employeeArrayList.add(employee); //判断是否达到缓存量 if (employeeArrayList.size() >= BATCH_SIZE) { //调用service层的批量导入方法 employeeService.importEmployees(employeeArrayList); employeeArrayList = new ArrayList<>(BATCH_SIZE); } } // 读完整个excel之后,都会调用这个方法 @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { if (employeeArrayList.size() > 0) { //调用service层的批量导入方法 employeeService.importEmployees(employeeArrayList); employeeArrayList = new ArrayList<>(BATCH_SIZE); } } }
2.4 domain层
ExcelProperty是EasyExcel中用于匹配excel和实体类的匹配,也就是我们Excel表格第一行的各列表头
▼plain复制代码/** * * @TableName employee */ @TableName(value ="employee") @Data public class Employee { /** * 员工编号 */ @ExcelProperty("员工编号") @TableId(type = IdType.AUTO) private Integer id; /** * 员工姓名 */ @ExcelProperty("员工姓名") private String name; /** * 入职时间 */ @ExcelProperty("入职时间") private Date date; /** * 员工工资 */ @ExcelProperty("员工工资") private BigDecimal salary; }
3、总结
这是我第一次在编程导航写的文章,可能说的不太清楚,具体学习还得参考官方文档,这是我突然想到的一个小实验,利用EasyExcel来操控Excel,然后将Excel数据保存到数据库,以及如何将Excel表格里面的数据更好地显示到前端界面上,这里过程中还使用了ai辅助帮忙,总之有一些小小的收获,把自己的小想法也分享给大家。Thanks♪(・ω・)ノ
