引入依赖
<dependencies>
<dependency>
<groupId>com
.alibaba
</groupId
>
<artifactId>easyexcel
</artifactId
>
<version>2.1.1</version
>
</dependency
>
<dependency>
<groupId>org
.apache
.poi
</groupId
>
<artifactId>poi
</artifactId
>
<version>3.17</version
>
</dependency
>
<dependency>
<groupId>org
.apache
.poi
</groupId
>
<artifactId>poi
-ooxml
</artifactId
>
<version>3.17</version
>
</dependency
>
</dependencies
>
创建与Excel表格对应的实体类 , 通过@ExcelProperty(index = 0)注解中的index指定字段与Excel表中的哪儿列相对应
package com
.starcpdk
.edu
.eduservice
.entity
.excel
;
import com
.alibaba
.excel
.annotation
.ExcelProperty
;
import lombok
.Data
;
@Data
public class SubjectData {
@ExcelProperty(index
= 0)
private String oneSubjectName
;
@ExcelProperty(index
= 1)
private String twoSubjectName
;
}
使用代码生成器快速构建service , controller , mapper层 , 具体使用方式参考这篇文章
package com
.starcpdk
.demo
;
import com
.baomidou
.mybatisplus
.annotation
.DbType
;
import com
.baomidou
.mybatisplus
.annotation
.IdType
;
import com
.baomidou
.mybatisplus
.generator
.AutoGenerator
;
import com
.baomidou
.mybatisplus
.generator
.config
.DataSourceConfig
;
import com
.baomidou
.mybatisplus
.generator
.config
.GlobalConfig
;
import com
.baomidou
.mybatisplus
.generator
.config
.PackageConfig
;
import com
.baomidou
.mybatisplus
.generator
.config
.StrategyConfig
;
import com
.baomidou
.mybatisplus
.generator
.config
.rules
.DateType
;
import com
.baomidou
.mybatisplus
.generator
.config
.rules
.NamingStrategy
;
import org
.junit
.Test
;
public class CodeGenerator {
@Test
public void run() {
AutoGenerator mpg
= new AutoGenerator();
GlobalConfig gc
= new GlobalConfig();
String projectPath
= System
.getProperty("user.dir");
gc
.setOutputDir("I:\\Projects\\IND_Projects\\cpdkedu\\Back_End\\cpdkedu\\cpdkedu_parent\\service\\service_edu" + "/src/main/java/");
gc
.setAuthor("姚云峰");
gc
.setOpen(false);
gc
.setFileOverride(false);
gc
.setServiceName("%sService");
gc
.setIdType(IdType
.ID_WORKER_STR
);
gc
.setDateType(DateType
.ONLY_DATE
);
gc
.setSwagger2(true);
mpg
.setGlobalConfig(gc
);
DataSourceConfig dsc
= new DataSourceConfig();
dsc
.setUrl("jdbc:mysql://localhost:3306/cpdkedu?serverTimezone=GMT+8");
dsc
.setDriverName("com.mysql.cj.jdbc.Driver");
dsc
.setUsername("root");
dsc
.setPassword("root");
dsc
.setDbType(DbType
.MYSQL
);
mpg
.setDataSource(dsc
);
PackageConfig pc
= new PackageConfig();
pc
.setParent("com.starcpdk.edu");
pc
.setModuleName("eduservice");
pc
.setController("controller");
pc
.setEntity("entity");
pc
.setService("service");
pc
.setMapper("mapper");
mpg
.setPackageInfo(pc
);
StrategyConfig strategy
= new StrategyConfig();
strategy
.setInclude("edu_subject");
strategy
.setNaming(NamingStrategy
.underline_to_camel
);
strategy
.setTablePrefix(pc
.getModuleName() + "_");
strategy
.setColumnNaming(NamingStrategy
.underline_to_camel
);
strategy
.setEntityLombokModel(true);
strategy
.setRestControllerStyle(true);
strategy
.setControllerMappingHyphenStyle(true);
mpg
.setStrategy(strategy
);
mpg
.execute();
}
}
由于使用easyExcel读操作需要使用到监听器 , 监听器是在service层new出来的 , 所以监听器SubjectExcelListener无法使用spring管理 , 因此无法使用@Autowired自动装配注入service层对象进行数据库的增删改查操作 , 那么我们该怎么解决呢?
解决方式如下:
那么我们就通过从controller传递注入的service层对象subjectService实现注入监听器中
controller层传递到service层 , service层new的监听器对象通过有参构造将subjectService传递到监听器SubjectExcelListener中.
编写controller内容 , 使用MultipartFile 上传文件 , 将上传的文件和service层的对象传到service层
package com
.starcpdk
.edu
.eduservice
.controller
;
import com
.starcpdk
.edu
.commonutils
.R
;
import com
.starcpdk
.edu
.eduservice
.service
.EduSubjectService
;
import org
.springframework
.beans
.factory
.annotation
.Autowired
;
import org
.springframework
.web
.bind
.annotation
.CrossOrigin
;
import org
.springframework
.web
.bind
.annotation
.PostMapping
;
import org
.springframework
.web
.bind
.annotation
.RequestMapping
;
import org
.springframework
.web
.bind
.annotation
.RestController
;
import org
.springframework
.web
.multipart
.MultipartFile
;
@RestController
@RequestMapping("/eduservice/subject")
@CrossOrigin
public class EduSubjectController {
@Autowired
private EduSubjectService subjectService
;
@PostMapping("addSubject")
public R
addSubject(MultipartFile file
){
subjectService
.saveSubject(file
, subjectService
);
return R
.ok();
}
}
service层书写saveSubject方法 , 通过file.getInputStream();方法获取文件的流 , 通过EasyExcel.read(in , SubjectData.class , new SubjectExcelListener(subjectService)).sheet().doRead();方法实现读excel表中数据。具体的逻辑处理在监听器中进行
package com
.starcpdk
.edu
.eduservice
.service
.impl
;
import com
.alibaba
.excel
.EasyExcel
;
import com
.starcpdk
.edu
.eduservice
.entity
.EduSubject
;
import com
.starcpdk
.edu
.eduservice
.entity
.excel
.SubjectData
;
import com
.starcpdk
.edu
.eduservice
.listener
.SubjectExcelListener
;
import com
.starcpdk
.edu
.eduservice
.mapper
.EduSubjectMapper
;
import com
.starcpdk
.edu
.eduservice
.service
.EduSubjectService
;
import com
.baomidou
.mybatisplus
.extension
.service
.impl
.ServiceImpl
;
import org
.springframework
.stereotype
.Service
;
import org
.springframework
.web
.multipart
.MultipartFile
;
import java
.io
.InputStream
;
@Service
public class EduSubjectServiceImpl extends ServiceImpl<EduSubjectMapper, EduSubject> implements EduSubjectService {
@Override
public void saveSubject(MultipartFile file
, EduSubjectService subjectService
) {
try {
InputStream in
= file
.getInputStream();
EasyExcel
.read(in
, SubjectData
.class , new SubjectExcelListener(subjectService
)).sheet().doRead();
}catch (Exception e
){
e
.printStackTrace();
}
}
}
书写监听器 , 比对excel表中的名字和级数是否存在表中进行筛选是否加入数据库 , 监听器是继承AnalysisEventListener类的 , 泛型是与excel表对应的实体类
package com
.starcpdk
.edu
.eduservice
.listener
;
import com
.alibaba
.excel
.context
.AnalysisContext
;
import com
.alibaba
.excel
.event
.AnalysisEventListener
;
import com
.baomidou
.mybatisplus
.core
.conditions
.query
.QueryWrapper
;
import com
.starcpdk
.edu
.eduservice
.entity
.EduSubject
;
import com
.starcpdk
.edu
.eduservice
.entity
.excel
.SubjectData
;
import com
.starcpdk
.edu
.eduservice
.service
.EduSubjectService
;
import com
.starcpdk
.edu
.service_base
.exceptionhandler
.MyException
;
public class SubjectExcelListener extends AnalysisEventListener<SubjectData> {
public EduSubjectService subjectService
;
public SubjectExcelListener() {}
public SubjectExcelListener(EduSubjectService subjectService
) {
this.subjectService
= subjectService
;
}
@Override
public void invoke(SubjectData subjectData
, AnalysisContext analysisContext
) {
if (subjectData
== null
){
throw new MyException(20001 , "文件数据为空");
}
EduSubject existOneSubject
= this.existOneSubject(subjectService
, subjectData
.getOneSubjectName());
if (existOneSubject
== null
){
existOneSubject
= new EduSubject();
existOneSubject
.setParentId("0");
existOneSubject
.setTitle(subjectData
.getOneSubjectName());
subjectService
.save(existOneSubject
);
}
String pid
= existOneSubject
.getId();
EduSubject existTwoSubject
= this.existTwoSubject(subjectService
, subjectData
.getTwoSubjectName(), pid
);
if (existTwoSubject
== null
){
existTwoSubject
= new EduSubject();
existTwoSubject
.setParentId(pid
);
existTwoSubject
.setTitle(subjectData
.getTwoSubjectName());
subjectService
.save(existTwoSubject
);
}
}
private EduSubject
existOneSubject(EduSubjectService subjectService
, String name
){
QueryWrapper
<EduSubject> wrapper
= new QueryWrapper<>();
wrapper
.eq("title" , name
);
wrapper
.eq("parent_id" , "0");
EduSubject oneSubject
= subjectService
.getOne(wrapper
);
return oneSubject
;
}
private EduSubject
existTwoSubject(EduSubjectService subjectService
, String name
, String pid
){
QueryWrapper
<EduSubject> wrapper
= new QueryWrapper<>();
wrapper
.eq("title" , name
);
wrapper
.eq("parent_id" , pid
);
EduSubject twoSubject
= subjectService
.getOne(wrapper
);
return twoSubject
;
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext
) {
}
}
具体思路:
Excel表中的数据分为两列 , 通过@ExcelProperty(index = 0)中的index与excel表中的列数相对应 , 下边的代码则表示excel表中的第一列的数据会赋值给oneSubjectName即以及分类中,同理二级分类也是如此
在数据库表中如何区分一级分类二级分类呢?如何让其想对应上呢?
通过id与parent_id两个字段所决定 , 一级分类的parent_id是0 , 二级分类的parent_id是一级分类相对应的id值
在监听器中通过读取excel表中数据 , 对应根据分类的名称和分类的级数去数据库查找数据 , 若查到 , 说明该分类在数据库中已存在 , 无需再次插入 , 若查询返回值为空 ,则将此条数据插入到数据库中
@ExcelProperty(index
= 0)
private String oneSubjectName
;
@ExcelProperty(index
= 1)
private String twoSubjectName
;