<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.7</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
建立一个类,然后往模板里输入类,sheet就是excel中那个sheet
主要就是用到了几个类。
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class ExcalWrite {
@Test
public void simpleWriteTest(){
String fileName = "d:/excel/simpleWrite.xlsx"; //需要提前新建目录
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
EasyExcel.write(fileName, ExcalStudentDto.class).sheet("新的模板").doWrite(data());
//sheet是写到ecal的那个sheet里面去
}
//辅助方法
private List<ExcalStudentDto> data(){
List<ExcalStudentDto> list = new ArrayList<>();
//算上标题,做多可写65536行
//超出:java.lang.IllegalArgumentException: Invalid row number (65536) outside allowable range (0..65535)
for (int i = 0; i < 65535; i++) {
ExcalStudentDto data = new ExcalStudentDto();
data.setName("Helen" + i);
data.setBirthday(new Date());
data.setSalary(123456.1234);
list.add(data);
}
return list;
}
}
用LIst对数据进行插入。
xlsx最多写1048575行数据
直接在类上加注解,可以很好修改放在表里数据的名字
建立一个类作为监听器,时时刻刻监听端口的,数据变化情况
package com.atguigu.easyexcel.listener;
@Slf4j
public class ExcelStudentDTOListener extends AnalysisEventListener<ExcelStudentDTO> {
/**
* 这个每一条数据解析都会来调用
*/
@Override
public void invoke(ExcelStudentDTO data, AnalysisContext context) {
log.info("解析到一条数据:{}", data);
}
/**
* 所有数据解析完成了 都会来调用
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
log.info("所有数据解析完成!");
}
}
读数据的操作
@Test
public void simpleReadXlsx() {
String fileName = "d:/excel/simpleWrite.xlsx";
// 这里默认读取第一个sheet
EasyExcel.read(fileName, ExcalStudentDto.class, new ExcelStudentDTOListener()).sheet().doRead();
}
首先,我们要创立对应的实体类,数据交换类,用来当做模型存储数据
一般放在pojo中,这个东西。
別忘了创建一个监听器,用来监听数据
监听器必须继承AnalysisEventListener
注意有泛型,泛型里面必须放,我们要存储和交换的数据模型类
监听器实现这个方法就行
package com.atguigu.srb.core.listener;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.atguigu.srb.core.pojo.dto.ExcelDictDTO;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ExcelDictDTOListener extends AnalysisEventListener<ExcelDictDTO> {
/**
*遍历每一行的记录
* @param data
* @param context
*/
@Override
public void invoke(ExcelDictDTO data, AnalysisContext context) {
log.info("解析到一条记录: {}", data);
}
/**
* 所有数据解析完成了 都会来调用
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
log.info("所有数据解析完成!");
}
}
在服務层写清楚我们的需求
路径通过一个InputStream传递进去
在Controller中上传
package com.atguigu.srb.core.controller.admin;
import com.atguigu.srb.core.service.DictService;
import com.atguigu.srb.exception.BusinessException;
import com.atguigu.srb.result.R;
import com.atguigu.srb.result.ResponseEnum;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
@CrossOrigin //检查跨域
@Api(tags = "数字字典")
@RestController
@RequestMapping("/admin/core/dict")
public class AdminDictController {
@Resource
DictService dictService;
@Resource
R r;
@PostMapping("/import")
@ApiOperation("数据批量导入")
public R batchImport(@ApiParam(value = "数据字典文件",required = true)
@RequestParam("file")MultipartFile file){
//拿到一个外面传递进来的InputStream地址
InputStream inputStream = null;
try {
inputStream = file.getInputStream();
dictService.importData(inputStream);
//数据上传成功
return r.ok().message("数据字典批量导入成功");
} catch (IOException e) {
throw new BusinessException(ResponseEnum.UPLOAD_ERROR,e);
}
dictService.importData(inputStream);
}
}
监听器部分优化:
package com.atguigu.srb.core.listener;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.atguigu.srb.core.pojo.dto.ExcelDictDTO;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ExcelDictDTOListener extends AnalysisEventListener<ExcelDictDTO> {
/**
*遍历每一行的记录
* @param data
* @param context
*/
@Override
public void invoke(ExcelDictDTO data, AnalysisContext context) {
log.info("解析到一条记录: {}", data);
}
/**
* 所有数据解析完成了 都会来调用
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
log.info("所有数据解析完成!");
}
}
监听器这里,每次读一条数据data就给封装好,然后往上传递(走一遍流程),读一条,往上传递一次,走一遍流程,效率非常低,我们是不是可以选择,在监听器这个环节,我们读一个List的,将数据存储到一定量在上传?
防止XML沒裝對位置,可以放這麽一個東西
<build>
<!-- 项目打包时会将java目录中的*.xml文件也进行打包 -->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml
false
一定要在taget里,看看xml的字节码进来了没有,如果没进来记得mvn去clean一下
clean完了再去看看target进来了没。
然后重新clean,看看target里有没有xml