【测试开发】知识点-使用EasyExcel,实现excel导出和导入

上篇介绍了下EasyExcel的读写excel文件的使用,现在利用它来实现项目中的excel文件导出和导入的功能。

现在有一个字典列表,要把里面的数据实现导出和导入。

一、实现导出

既然是整合到项目里,跟之前的练习还是有些区别的。说是导出功能,实际上也算是个下载的操作。

1. 实现后端接口

controller 类中增加导出数据字典的控制器方法。

@Api(value = "数据字典的接口")
@RestController
@RequestMapping("/admin/cmn/dict")
@CrossOrigin
public class DictController {
    @Autowired
    private DictService dictService;

    // 导出数据字典接口
    @GetMapping("exportData")
    public void exportDict(HttpServletResponse response) {
        dictService.exportDictData(response);
    }

    // 根据id查询子数据列表
    @ApiOperation(value = "根据id查询子数据列表")
    @GetMapping("findChildData/{id}")
    public Result findChildData(@PathVariable Long id) {
        List<Dict> list = dictService.findChildData(id);
        return Result.ok(list);
    }
}

这里方法exportDict中传参是HttpServletResponse response,为了方便做下载操作。

然后DictService接口中增加对应的方法exportDictData

public interface DictService extends IService<Dict> {
    List<Dict> findChildData(Long id);
   
    void exportDictData(HttpServletResponse response);
}

接着就是到DictServiceImpl类中实现exportDictData方法了:

    // 导出数据字典接口
    @Override
    public void exportDictData(HttpServletResponse response) {
        try {
            // 设置下载信息
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            String fileName = "dict";
            response.setHeader("Content-disposition", "attachment;filename="+ fileName + ".xlsx");
            // 查询库里的数据
            List<Dict> dictList = baseMapper.selectList(null);
            // Dict 转成 DictEeVo
            List<DictEeVo> dictEeVoList = new ArrayList<>(dictList.size());
            for (Dict dict: dictList) {
                DictEeVo dictEeVo = new DictEeVo();
                BeanUtils.copyProperties(dict, dictEeVo);
                dictEeVoList.add(dictEeVo);
            }
            // 调用方法,进行写操作,这里使用输出流
            EasyExcel.write(response.getOutputStream(), DictEeVo.class).sheet("dict").doWrite(dictEeVoList);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

做的事情主要是3件:

  • 先设置下载信息
  • 查询库里的数据
  • 使用EasyExcel.write方法把查出来的数据写到excel文件中

另外,Dict对应的是表里的实体类,DictEeVo则是excel内容的实体类。

调用EasyExcel.write的时候要传入的是DictEeVo类型,而数据库查出来的是Dict,所以有了异步转换的操作。

2. 实现前端

前端可以很简单的实现,通过一个<a>标签就可以:

    <a href="http://localhost:8202/admin/cmn/dict/exportData" target="_blank">
        <el-button type="text"> 导出</el-button>
    </a>

target="_blank"是为了打开新的标签页。

测试下:

二、实现导入

1. 实现后端接口

继续增加导入的控制器方法:

    // 导入数据字典
    @PostMapping("importData")
    public Result importDict(MultipartFile file) {
        dictService.importDictData(file);
        return Result.ok();
    }

这里参入是MultipartFile file用于获取上传的文件。

跟上面一样的套路,一直到实现importDictData方法。

    @Override
    public void importDictData(MultipartFile file) {

    }

不过目前里面还写不了,因为需要先去写一个监听器。

public class DictListener extends AnalysisEventListener<DictEeVo> {
    private DictMapper dictMapper;

    public DictListener(DictMapper dictMapper) {
        this.dictMapper = dictMapper;
    }

    // 一行一行读取
    @Override
    public void invoke(DictEeVo dictEeVo, AnalysisContext analysisContext) {
        // 调用方法,添加到数据库表里
        Dict dict = new Dict();
        // dictEeVo 转换成 dict
        BeanUtils.copyProperties(dictEeVo, dict);
        dictMapper.insert(dict);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {

    }
}

注意这里面的一个细节,因为在invoke方法中,一行行读取后,我需要把这每行的数据添加到数据库中,那么自然需要用到dictMapper

那么我这个监听器里如何才可以支持传入dictMapper呢?其中一个方法就是通过有参构造方法来注入:

    private DictMapper dictMapper;

    public DictListener(DictMapper dictMapper) {
        this.dictMapper = dictMapper;
    }

现在监听器完成,继续完成importDictData方法:

    @Override
    public void importDictData(MultipartFile file) {
        try {
            EasyExcel.read(file.getInputStream(), DictEeVo.class, new DictListener(baseMapper)).sheet().doRead();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

new DictListener(baseMapper))这里在传入监听器的时候里面就要带上dictMapper,这里放的是baseMapper也可以。

2. 实现前端整合

添加导入按钮,绑定@click调用上传方法。

<el-button type="text" @click="importData"> 导入</el-button>

点击导入后跳出对话框,增加友好度。

  • :multiple: 表示是否上传多个文件,这里用单个
    *:on-success: 文件上传成功会调用的方法
  • :action:请求的接口路径

对应里面的方法:

        //导入数据字典
        importData() {
            this.dialogImportVisible = true
        },
        //上传成功调用
        onUploadSuccess() {
            //关闭弹框
            this.dialogImportVisible = false
            //刷新页面
            this.getDictList(1)
        },

准备一份数据测试一下:

上传成功。

查看数据库里数据正确。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章