『博客开发日记-后台』之导出用户数据接口的实现

本文最后更新于 2026年5月21日 上午

导出用户数据接口的实现


导出用户数据接口的需求

需求和获取用户列表接口一样

需要注意的是

导出数据中 sex 和 status 要转换成更易读的中文


代码实现

AdminUserController

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

@GetMapping("/export")
@PreAuthorize("@ps.hasPermission('sys:user:export')")
@SystemLog(businessName = "导出评论数据")
@ApiOperation(value = "导出评论数据", notes = "导出评论数据")
@ApiImplicitParams({
@ApiImplicitParam(name = "pageNum", value = "页号", dataType = "int", paramType = "query"),
@ApiImplicitParam(name = "pageSize", value = "每页数量", dataType = "int", paramType = "query")
})
public void exportUser(Integer pageNum, Integer pageSize, @Valid UserListDto userListDto, HttpServletResponse response)
{
try {
//调用服务层获取导出数据
ResponseResult result = adminUserService.exportUser(pageNum, pageSize, userListDto);

//检查结果
if (result.getCode() != 200 || result.getData() == null) {
throw new RuntimeException("获取导出数据失败");
}

//获取导出数据列表
@SuppressWarnings("unchecked")
List<UserExportVo> exportData = (List<UserExportVo>) result.getData();

//检查数据是否为空
if (exportData.isEmpty()) {
throw new RuntimeException("没有可导出的数据");
}

//生成文件名+时间(格式:评论数据_20260503_143056)
String fileName = "用户数据_" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());

//使用工具类导出Excel
ExcelExportUtil.exportExcel(response, exportData, UserExportVo.class, fileName, "用户数据");

} catch (Exception e) {
//异常处理:只有在响应流未被写入时才能返回JSON错误
e.printStackTrace();

//检查响应是否已提交
if (!response.isCommitted()) {
try {
response.reset();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");

ResponseResult result = ResponseResult.errorResult(
AppHttpCodeEnum.SYSTEM_ERROR.getCode(),
"导出失败: " + e.getMessage()
);
WebUtils.renderString(response, JSON.toJSONString(result));
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}

创建一些常量

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 性别:弟弟
*/
public static final String SEX_MAN = "0";
/**
* 性别:妹妹
*/
public static final String SEX_WOMEN = "1";
/**
* 性别:隐藏
*/
public static final String SEX_HIDE = "2";

创建 UserExportVo

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
/**
* 用户数据导出VO
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserExportVo
{
@ColumnWidth(10)
@ExcelProperty("用户id")
@ApiModelProperty(value = "用户id", example = "1")
@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER)
private Long id;

@ColumnWidth(15)
@ExcelProperty("用户名")
@ApiModelProperty(value = "用户名", example = "云梦泽")
@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER)
private String username;

@ColumnWidth(15)
@ExcelProperty("昵称")
@ApiModelProperty(value = "昵称", example = "云梦泽")
@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER)
private String nickname;

@ColumnWidth(10)
@ExcelProperty("性别")
@ApiModelProperty(value = "用户性别,(0 男,1 女,2 隐藏)", example = "0")
@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER)
private String sex;

@ColumnWidth(15)
@ExcelProperty("部门名称")
@ApiModelProperty(value = "部门名称", example = "测试不")
@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER)
private String deptName;

@ColumnWidth(15)
@ExcelProperty("角色名称")
@ApiModelProperty(value = "角色名称,多个使用英文逗号(,)分割", example = "系统管理员")
@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER)
private String roleNames;

@ColumnWidth(30)
@ExcelProperty("邮箱")
@ApiModelProperty(value = "用户邮箱", example = "2962933152@qq.com")
@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER)
private String email;

@ColumnWidth(25)
@ExcelProperty("手机号")
@ApiModelProperty(value = "手机号", example = "18329384753")
@JSONField(name = "mobile")//转换成 mobile 再响应给前端
@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER)
private String phone;

@ColumnWidth(15)
@ExcelProperty("账号状态")
@ApiModelProperty(value = "账号状态(0 正常,1 停用)", example = "0")
@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER)
private String status;

@ColumnWidth(20)
@ExcelProperty("创建时间")
@ApiModelProperty(value = "创建时间", example = "2026-05-20 21:58:53")
@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER)
private Date createTime;

}

在 AdminUserServiceImpl 中

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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
//导出用户数据
@Override
public ResponseResult exportUser(Integer pageNum, Integer pageSize, UserListDto userListDto)
{
//构建查询条件
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();

//当前登录用户
LoginUser loginUser = SecurityUtils.getLoginUser();
Long currentUserId = null;
if (loginUser != null) {
currentUserId = loginUser.getSysUser().getId();
}

//超级管理员可以看到全部 普通用户按数据权限限制
if (!Objects.equals(currentUserId, 1L)) {
List<SysRole> roles = sysRoleService.selectRolesByUserId(currentUserId);
Integer maxDataScope = roles.stream()
.map(SysRole::getDataScope)
.filter(Objects::nonNull)
.min(Integer::compareTo)
.orElse(4);

//全部数据
if (!Objects.equals(maxDataScope, 1))
{
if (Objects.equals(maxDataScope, 2)) {
//部门及子部门数据
List<Long> deptIds = sysDeptService.selectDeptAndChildrenIds(Long.valueOf(loginUser.getSysUser().getDeptId()));
queryWrapper.in(SysUser::getDeptId, deptIds.stream().map(String::valueOf).toList());
} else if (Objects.equals(maxDataScope, 3)) {
//本部门数据
queryWrapper.eq(SysUser::getDeptId, loginUser.getSysUser().getDeptId());
} else if (Objects.equals(maxDataScope, 4)) {
//本人数据
queryWrapper.eq(SysUser::getCreateBy, currentUserId);
} else if (Objects.equals(maxDataScope, 5)) {
//自定义部门数据
List<Long> deptIds = new ArrayList<>();
for (SysRole role : roles) {
if (Objects.equals(role.getDataScope(), 5)) {
LambdaQueryWrapper<com.mengze.domain.entity.SysRoleDept> deptWrapper = new LambdaQueryWrapper<>();
deptWrapper.eq(com.mengze.domain.entity.SysRoleDept::getRoleId, role.getId())
.select(com.mengze.domain.entity.SysRoleDept::getDeptId);
List<com.mengze.domain.entity.SysRoleDept> roleDeptList = sysRoleDeptService.list(deptWrapper);
deptIds.addAll(roleDeptList.stream().map(com.mengze.domain.entity.SysRoleDept::getDeptId).toList());
}
}
if (!deptIds.isEmpty()) {
queryWrapper.in(SysUser::getDeptId, deptIds.stream().map(String::valueOf).toList());
}
}
}
}

//根据关键子查询(用户名,昵称,手机号)
if (StringUtils.hasText(userListDto.getKeywords())) {
queryWrapper.and(wrapper -> wrapper
.like(SysUser::getUsername, userListDto.getKeywords())
.or()
.like(SysUser::getNickname, userListDto.getKeywords())
.or()
.like(SysUser::getPhone, userListDto.getKeywords())
);
}

//根据状态筛选
if (StringUtils.hasText(userListDto.getStatus())){
queryWrapper.eq(SysUser::getStatus, userListDto.getStatus());
}

//按部门id查询
if (StringUtils.hasText(userListDto.getDeptId())) {
queryWrapper.eq(SysUser::getDeptId, userListDto.getDeptId());
}

//按创建时间查询
if (userListDto.getCreateTime() != null && userListDto.getCreateTime().size() == 2)
{
//补全当天完整时间,因为前端只传 2026-04-01 不完整
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

Date startTime = sdf.parse(userListDto.getCreateTime().get(0) + " 00:00:00");
Date endTime = sdf.parse(userListDto.getCreateTime().get(1) + " 23:59:59");

queryWrapper.between(SysUser::getCreateTime, startTime, endTime);
} catch (ParseException e) {
throw new RuntimeException("创建时间格式不正确", e);
}
}

//根据创建时间降序排序
queryWrapper.orderByDesc(SysUser::getCreateTime);

//根据是否传入分页参数决定查询方式
List<SysUser> users;
if (pageNum != null && pageSize != null && pageNum > 0 && pageSize > 0) {
//分页查询
Page<SysUser> page = new Page<>(pageNum, pageSize);
sysUserMapper.selectPage(page, queryWrapper);
users = page.getRecords();
} else {
//查询所有符合条件的用户
users = sysUserMapper.selectList(queryWrapper);
}

//转换为导出VO
List<UserExportVo> userExportVos = new ArrayList<>();
if (users != null && !users.isEmpty()) {
userExportVos = users.stream()
.map(sysUser -> {
UserExportVo vo = BeanCopyUtils.copyBean(sysUser, UserExportVo.class);

//填充性别
vo.setSex(convertSex(sysUser.getSex()));

//填充用户状态
vo.setStatus(convertUserStatus(sysUser.getStatus()));

//填充部门信息
if (StringUtils.hasText(sysUser.getDeptId())) {
try {
SysDept dept = sysDeptService.getById(Long.valueOf(sysUser.getDeptId()));
if (dept != null) {
vo.setDeptName(dept.getName());
}
} catch (NumberFormatException ignored) {
vo.setDeptName(sysUser.getDeptId());
}
}

//填充角色信息
List<String> roleNames = sysRoleService.selectRoleNameByUserId(sysUser.getId());
if (roleNames != null && !roleNames.isEmpty()) {
vo.setRoleNames(String.join(",", roleNames));
}

return vo;
})
.collect(Collectors.toList());
}

return ResponseResult.okResult(userExportVos);
}

private String convertSex(String sex)
{
if (Objects.equals(sex, SystemConstants.SEX_MAN)) {
return "弟弟";
}
if (Objects.equals(sex, SystemConstants.SEX_WOMEN)) {
return "妹妹";
}
if (Objects.equals(sex, SystemConstants.SEX_HIDE)) {
return "隐藏";
}
return sex;
}

private String convertUserStatus(String status)
{
if (Objects.equals(status, SystemConstants.USER_STATUS_NORMAL)) {
return "正常";
}
if (Objects.equals(status, SystemConstants.USER_STATUS_BANNED)) {
return "已封禁";
}
return status;
}




PS:该系列只做为作者学习开发项目做的笔记用

不一定符合读者来学习,仅供参考


预告

后续会记录博客的开发过程

每次学习会做一份笔记来进行发表

“一花一世界,一叶一菩提”


版权所有 © 2026 云梦泽
欢迎访问我的个人网站:https://hgt12.github.io/


『博客开发日记-后台』之导出用户数据接口的实现
http://example.com/2026/05/21/『博客开发日记-后台』之导出用户数据接口的实现/
作者
云梦泽
发布于
2026年5月21日
更新于
2026年5月21日
许可协议