项目要求将excel文件中的课程数据传到数据库中,并且excel中的数据使分类的。
0.前言
整个流程介绍
现在controller中声名路径,通过调用方法saveSubject()来上传excel文件,在service中创建saveSubject()中,在serviceImpl中实现此方法,saveSubject中调用EasyExcel的read方法
,此方法必须实现监听器SubjectExcelListener,在监听器中来读取excel数据,是一行一行的读取的。根据文件的特点,第一分类和第二分类的名字不能重复,传入的名字为空则加入,不为空则拒绝添加。所以,设置一个方法来解决这个问题,设比如前端为第一分类,vue为第二分类,每个名都有一个id和一个parent_id,第一分类的parent_id就是0,第二分类的p_id就是第一分类的id,通过传入的名称和p_id=0通过subjectService.getOne(wrapper);此方法判断第一分类是否为空,判断第二分类同样的方法。添加的时候来调用这两个方法来判断第一分类和第二分类是否添加。
还有因为SubjectExcelListener不能交给spring管理,需要 自己new,不能注入其他对象,所以要自己传入serviceimpl,具体是实现代码中已经写了
1.用代码生成器生成所需要文件夹及java文件
具体在这篇如何使用代码生成器
用代码生成器也创建了与数据库所对应的实体类
注意:时间使用的自动填充机制
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("edu_subject")
@ApiModel(value="Subject对象", description="课程科目")
public class Subject implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "课程类别ID")
@TableId(value = "id", type = IdType.ID_WORKER_STR)
private String id;
@ApiModelProperty(value = "类别名称")
private String title;
@ApiModelProperty(value = "父ID")
private String parentId;
@ApiModelProperty(value = "排序字段")
private Integer sort;
@ApiModelProperty(value = "创建时间")
@TableField(fill = FieldFill.INSERT)
private Date gmtCreate;
@ApiModelProperty(value = "更新时间")
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date gmtModfied;
}
2.创建controller
@RestController
@CrossOrigin//跨域问题
@RequestMapping("/eduservice/subject")
public class SubjectController {
@Autowired
private SubjectService subjectService;
//添加课程分类
//获取上传的文件,把文件内容读出来
@PostMapping("addSubject")
public UnResult addSubject(MultipartFile file){
//上传excel文件
subjectService.saveSubject(file,subjectService);
return UnResult.ok();
}
}
3.创建与excel表对应的实体类
index=0就是第一列,index=1就是第二列
/**
* @author ZhangTao
* @date 2021/4/22 15:31
* @note:创建和excel对应的实体类
*
* 就是excel中的表头一级分类,二级分类中的列
*/
@Data
public class SubjectData {
@ExcelProperty(index = 0)
private String oneSubjectName;
@ExcelProperty(index = 1)
private String twoSubjectName;
}
4.在service中写接口,serviceimpl写实现方法
public interface SubjectService extends IService<Subject> {
//添加课程分类
void saveSubject(MultipartFile file,SubjectService subjectService);
}
因为使读文件EasyExcel中要使用监听器来进行读文件,第四步写监听器
@Service
public class SubjectServiceImpl extends ServiceImpl<SubjectMapper, Subject> implements SubjectService {
@Override
public void saveSubject(MultipartFile file,SubjectService subjectService) {
try {
//文件输入流
InputStream in=file.getInputStream();
//调用方法进行读取
//吧service直接注入进来为了后面能使用
//因为在listener中不能注入service所以在这个serviceiimpl中,通过listener使service注入进去,为了在listener中能够使用service中的发方法save/
EasyExcel.read(in, SubjectData.class,new SubjectExcelListener(subjectService)).sheet().doRead();
}catch(Exception e){
e.printStackTrace();
}
}
}
5.写监听器
/**
* @author ZhangTao
* @date 2021/4/22 15:42
* @note:监听器
*
* /因为SubjectExcelListener不能交给spring管理,需要 自己new,不能注入其他对象
* 不能实现数据库的操作
*
*前面service中已经在listener中注入了service,
*/
public class SubjectExcelListener extends AnalysisEventListener<SubjectData> {
public SubjectService subjectService;
//创建有参无参构造器为了后面能做添加操作,
public SubjectExcelListener(SubjectService subjectService) {
this.subjectService = subjectService;
}
public SubjectExcelListener(){
}
@Override
public void invoke(SubjectData subjectData, AnalysisContext analysisContext) {
if(subjectData==null){
throw new GuliException(20001,"文件数据为空");
}
//从第二行开始读
//一行一行的读取,每次读取的两个值,第一个值是一级分类,第二个是二级分类
//判断一级分类是否为空
Subject existOneSubject = this.existOneSubject(subjectService,subjectData.getOneSubjectName());
//为空就是没有相同的一级分类,则进行添加
if(existOneSubject==null){//没有相同的一级分类
existOneSubject=new Subject();
existOneSubject.setParentId("0");
existOneSubject.setTitle(subjectData.getOneSubjectName());//刚传进去的一级分类名
subjectService.save(existOneSubject);//前面做了很多就是为了能使用subjectService调用save方法,
}
//获取一节分类的id值
//二级分类的pareat——id就是一级分类的id值
String pid=existOneSubject.getId();
//添加二级分类
//判断二级分类是否重复
Subject existTwoSubject = this.existTwoSubject(subjectService,subjectData.getTwoSubjectName(),pid);
if(existTwoSubject==null){//没有相同的一级分类
existTwoSubject=new Subject();
existTwoSubject.setParentId(pid);
existTwoSubject.setTitle(subjectData.getTwoSubjectName());//一级分类名
subjectService.save(existTwoSubject);
}
}
//判断一级分类不能重复添加
//使根据传进去的name和0(代表着使一级分类)//判断表中是否有值
//没有值的话返回为null
private Subject existOneSubject(SubjectService subjectService,String name){
QueryWrapper<Subject> wrapper=new QueryWrapper<>();
wrapper.eq("title",name);
wrapper.eq("parent_id",0);
Subject oneSubject=subjectService.getOne(wrapper);//getOne根据 Wrapper,查询一条记录
return oneSubject;
}
// //判断二级分类不能重复添加
private Subject existTwoSubject(SubjectService subjectService,String name,String pid){
QueryWrapper<Subject> wrapper=new QueryWrapper<>();
wrapper.eq("title",name);
wrapper.eq("parent_id",pid);
Subject twoSubject=subjectService.getOne(wrapper);
return twoSubject;
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
测试
用的是swagger来测试