本文已参与「新人创作礼」活动,一起开启掘金创作之路。
今天在学习尚硅谷的课堂项目的导入导出Excel功能,在这里记录下使用EasyExcel的学习心得,和各位同学交流。如果对EasyExcel不是很熟悉的同学,可以参考这篇文章。本文的持久层框架是mybatisplus。
1.EasyExcel的导出功能
分析:其实导出Excel表格其实有两个步骤,一个是下载,一个是用EasyExcel将数据写到Excel里面,所以我们的实现步骤如下:
- 设置下载文件类型 mime类型
- 设置响应头信息Content-disposition。作用是:无论是什么格式文件都以下载方式打开
导入相关依赖:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.1</version>
</dependency>
准备相关数据库:
数据库的样子如下所示
准备相关的实体类:
数据表对应的实体类,@ApiModel @ApiModelProperty是swagger的注解,大家可以忽略这些注解
@Data
@ApiModel(description = "Subject")
@TableName("subject")
public class Subject {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "id")
private Long id;
@ApiModelProperty(value = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@TableField("create_time")
private Date createTime;
@ApiModelProperty(value = "更新时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@TableField("update_time")
private Date updateTime;
@ApiModelProperty(value = "逻辑删除(1:已删除,0:未删除)")
@JsonIgnore
@TableLogic
@TableField("is_deleted")
private Integer isDeleted;
@ApiModelProperty(value = "其他参数")
@TableField(exist = false)
private Map<String,Object> param = new HashMap<>();
@ApiModelProperty(value = "类别名称")
@TableField("title")
private String title;
@ApiModelProperty(value = "父ID")
@TableField("parent_id")
private Long parentId;
@ApiModelProperty(value = "排序字段")
@TableField("sort")
private Integer sort;
@ApiModelProperty(value = "是否包含子节点")
@TableField(exist = false)
private boolean hasChildren;
}
与Excel表格对应的实体类,如下所示:
@ExcelProperty的value值在进行写操作的时候起作用,它的作用是给创建的Excel表格设置表头。@ExcelProperty的index值在进行读操作的时候起作用,它的作用是指明Excel表格的列,index=0代表Excel表格里的第一列,index=2代表Excel表格里的第二列。
@Data
public class SubjectEeVo {
@ExcelProperty(value = "id" ,index = 0)
private Long id;
@ExcelProperty(value = "课程分类名称" ,index = 1)
private String title;
@ExcelProperty(value = "上级id" ,index = 2)
private Long parentId;
@ExcelProperty(value = "排序" ,index = 3)
private Integer sort;
}
controller代码:
是下载所以这个方法不需要什么返回值。
@Autowired
private SubjectService subjectService;
//课程分类导出
@GetMapping("exportData")
public void exportData(HttpServletResponse response){
subjectService.exportData(response);
}
service接口和service接口实现类代码
void exportData(HttpServletResponse response);
service接口实现类主要功能就是下载以及将数据写到Excel表格。response.setContentType("application/vnd.ms-excel"),这行代码的作用是设置微软的Excel的数据类型。String fileName = URLEncoder.encode("课程分类", "UTF-8");这行代码的作用是设置下载文件的名字。 BeanUtils.copyProperties(类1,类2)是spring提供的方法,可以将类1的属性的值复制给类2的属性,前提是这两个类有属性是一样的,属性一样的才会复制。
//课程分类导出
@Override
public void exportData(HttpServletResponse response) {
try {
//设置下载信息,设置数据格式
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String fileName = URLEncoder.encode("课程分类", "UTF-8");//你会发现你下载的文件叫课程分类
response.setHeader("Content-disposition", "attachment;filename="+ fileName + ".xlsx");
//查询课程分类表所有数据
List<Subject> subjectList = baseMapper.selectList(null);
//将List<Subject> 转换成 List<SubjectEeVo>,因为实体类Subject和SubjectEeVo属性不同,SubjectEeVo才是我们要写进Excel
List<SubjectEeVo> subjectEeVoList = new ArrayList<>();
for (Subject subject: subjectList) {
SubjectEeVo subjectEeVo = new SubjectEeVo();
/*subjectEeVo.setId(subject.getId());
subjectEeVo.setParentId(subject.getParentId());*/
//可以将数据进行复制。找到属性一致的,进行复制。这是spring框架提供的,如果不喜欢,可以用上面传统的方式
BeanUtils.copyProperties(subject,subjectEeVo);
subjectEeVoList.add(subjectEeVo);
}
//EasyExcel写操作
EasyExcel.write(response.getOutputStream(), SubjectEeVo.class)
.sheet("课程分类")
.doWrite(subjectEeVoList);
}catch (Exception e){
throw new GgktException(20001,"导出异常");
}
}
上述就是主要的逻辑代码,完成以后,我们可以用过浏览器来访问对应的接口,结果如下所示:
2.EasyExcel的导入功能
导入功能其实就是上传功能,当文件上传之后,再用EasyExcel读取数据并存入数据库。
controller代码:
我是用swagger测试上传导入功能的,所以这里有@ApiOperation。MultipartFile是spring提供的参数,因为我们要进行上传,所以需要这个参数。
//课程分类导出
@ApiOperation("课程分类导入")
@PostMapping("importData")
public Result importData(MultipartFile file){
subjectService.importData(file);
return Result.ok(null);
}
service接口和service接口实现类代码:
void importData(MultipartFile file);
service接口实现类里面注入的SubjectListener是监听器。看过我前面提到的文章的同学,会发现那篇文章调用监听器是直接new一个监听器对象,我们现在是在spring的框架里面,所以我们不能这样做了,我们采用自动注入的方式。
@Autowired
private SubjectListener subjectListener;
//课程分类导入
@Override
public void importData(MultipartFile file) {
try {
EasyExcel.read(file.getInputStream(),SubjectEeVo.class,subjectListener).sheet().doRead();
} catch (IOException e) {
throw new GgktException(20001,"导入失败");
}
}
监听器实现类
这个监听器主要是将Excel表格内容读取出来,并添加到数据库表。
@Component
public class SubjectListener extends AnalysisEventListener<SubjectEeVo> {
//注入mapper
@Autowired
private SubjectMapper subjectMapper;
//从第二行开始,逐行读取表格内容
@Override
public void invoke(SubjectEeVo subjectEeVo, AnalysisContext analysisContext) {
Subject subject = new Subject();
//SubjectEeVo转换成Subject,Subject是数据库表的实体类
BeanUtils.copyProperties(subjectEeVo,subject);
//添加
subjectMapper.insert(subject);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
mapper类其实很简单,因为我们采用的是mybatisplus框架,所以很多方法已经实现好了。
@Repository
public interface SubjectMapper extends BaseMapper<Subject> {
}
实验结果如下图:
这是要导入的数据
导入过程
导入结果