excel异步导入功能
excel异步导入功能
框架已实现通过excel文件异步批量导入数据的功能,并具备查看错误日志的功能。
其中异步操作过程已封装,使用者只需关注excel处理逻辑即可,excel的导入使用了插件Easy Excel,具体的使用请查看Easy Excel官网https://easyexcel.opensource.alibaba.com/
同时需要把上传的excel模板先放在resource/template目录下。具体的代码架构如图:
1.接口调用
在接口中可以直接调用ExcelUtils.importExcelAsync方法进行上传
1
2
3
4
5
6
7
8
9
10
@RequestMapping(value = "/importUserInfoExcel", method = RequestMethod.POST)
public void importUserInfoExcel(@RequestParam("file") MultipartFile file) throws IOException {
ExcelUtils.importExcelAsync(
file,
"demo",
UserInfoExcelData.class,
new UserInfoDataListener(),
2,
"userInfoImport.xlsx");
}
其中importExcelAsync方法参数说明如下:
参数 | 含义 |
---|---|
multipartFile | 上传的文件 |
type | 文件类型,对应UTILITY_IMPORT_TASK表中的type字段 |
clazz | ExcelData实体的class对象 |
excelDataListener | DataListener对象 |
headRowNumber | 表头的行数,指明从第几行开始读数据 |
templateName | 模板的名称 |
2.ExcelData实体
首先需要一个excel的实体类,里面存放excel中的字段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Data
public class UserInfoExcelData extends MyBaseExcelData {
@ExcelProperty("账号")
private String account;
@ExcelProperty("密码")
private String password;
@ExcelProperty("组织名称")
private String orgName;
@ExcelProperty("年龄")
private int age;
@ExcelIgnore private String orgId;
}
如果是不必要的字段,可以用注解@ExcelIgnore忽略掉
3.DataListener
主要的逻辑操作在DataListener中,包括检查数据,保存数据等
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
public class UserInfoDataListener extends ExcelDataListener<UserInfoExcelData> {
private UserInfoService userInfoService;
private DepartmentService departmentService;
public UserInfoDataListener() {}
@Override
public void init() {
// 由于UserInfoDataListener不受spring管理,用这种方式获取bean
userInfoService = SpringBeanUtils.getBean(UserInfoService.class);
departmentService = SpringBeanUtils.getBean(DepartmentService.class);
}
@Override
public List<UserInfoExcelData> getDbData() {
// 查找所有的用户信息
List<UserInfo> userInfoList = userInfoService.list();
// 把所有用户信息添加到CachedAllDataList中
List<UserInfoExcelData> userExcelDataList = new ArrayList<>();
if (userInfoList != null && userInfoList.size() > 0) {
userInfoList.forEach(
c -> {
UserInfoExcelData userExcelData = new UserInfoExcelData();
userExcelData.setAccount(c.getAccount());
userExcelDataList.add(userExcelData);
});
}
return userExcelDataList;
}
/**
* 检查数据
*
* @param data
* @param cacheAllList
* @param context
* @return
*/
@Override
public boolean checkData(
UserInfoExcelData data, List<UserInfoExcelData> cacheAllList, AnalysisContext context) {
boolean result = true;
StringBuilder sb = new StringBuilder();
// 账号唯一
if (StringUtils.isNotBlank(data.getAccount())) {
if (cacheAllList.stream().anyMatch(c -> c.getAccount().equals(data.getAccount()))) {
result = false;
sb.append("账号重复;");
}
}
QueryWrapper<Department> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("NAME", data.getOrgName());
Department department = departmentService.getOne(queryWrapper);
if (department == null) {
result = false;
sb.append("该组织不存在;");
} else {
data.setOrgId(department.getId());
}
// 成功失败都保存信息。成功时信息设置错误信息为空。防止导出错误后,二次导入带入了错误信息,但仍错误时,确保错误信息都为本次生成信息
data.setError(sb.toString());
return result;
}
@Override
protected void saveData(List<UserInfoExcelData> dataList) {
// 新增用户信息测试数据
List<UserInfo> userList = new ArrayList<>();
for (UserInfoExcelData item : dataList) {
UserInfo user = new UserInfo();
user.setAccount(item.getAccount());
user.setPassword(item.getPassword());
user.setOrgId(item.getOrgId());
user.setAge(item.getAge());
userList.add(user);
}
userInfoService.saveBatch(userList);
}
}
- 由于DataListener不能被spring管理,所以每次使用都需要new一个,因此在DataListener中的业务Service不能直接通过@Autowired注解方式获取,需要在init方法中使用框架自带的getBean方法获取实例对象。
- 在getDbData获取数据库中所有的该类数据(如无必要,返回空对象即可),该数据返回后会存在cachedAllDataList中,cacheAllList参数用来缓存所有数据(包括新上传的数据和库中的数据),最后会用于在checkData进行数据校验,防止和数据库中的数据重复。
- 在checkData方法中可以对上传的数据进行校验,每一条数据都会调用该方法,如果有数据没有通过校验会生成包含具体错误信息的excel文件并上传到文件服务器。
- 如果checkData方法返回true最后会调用saveData方法保存所有的数据。
4.上传结果
具体的上传结果可以在UTILITY_IMPORT_TASK表中查看,上传失败的记录会有一个对应的ATTACHMENT_ID字段,可以根据该字段调用文件下载接口直接下载该文件查看具体的失败原因
1
http://xxx:xxx/services/admin/utility/attachment/download?attachmentId=b743bc27b5a4459f337d60d2e1ed2378
同时可以在前端看到
本文由作者按照
CC BY 4.0
进行授权