苍穹外卖开发日志Day02——员工管理
2025.06.04
苍穹外卖开发日志Day02——员工管理
- 员工管理包含以下功能:
- 新增员工
- 员工分页查询
- 启用禁用员工账号
- 编辑员工
一、新增员工
1.1 新增员工——功能开发
- 产品原型
- 接口设计
- 数据库设计(employee表)
- 代码开发
- 当前端提交的数据和实体类中对应的属性差别较大时,建议使用DTO来封装数据
- 注意点:需要在ServiceImpl中将DTO转换为实体类,并设置其他属性
1.1.1 EmployeeDTO
1 |
|
1.1.2 EmployeeController
1 | /* |
1.1.3 EmployeeServiceImpl
1 | /* |
1.1.4 EmployeeMapper
1 | /* |
1.2 新增员工——功能测试
- 直接测试

- 问题:返回401,原因是未登录,所以在测试过程中jwt令牌校验不通过
- 解决方法:
- 先使用登录接口获取jwt令牌

- 然后添加Header全局参数

- 最后再次测试新增员工接口,测试成功!

- 前后端联调测试
- 数据库结果
1.3 新增员工——代码完善
-
当前存在的问题
- 录入的用户名已存在。抛出异常后没有处理
- 新增员工时创建人id和修改人id设置为了固定值
-
解决方法
- 问题1:在GlobalExceptionHander中处理异常信息:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18/**
* 捕获SQL异常
* @param ex
* @return
*/
public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){
// Duplicate entry 'zhangsan' for key 'employee.idx_username'
String message = ex.getMessage();
if(message.contains("Duplicate entry")){
String username = message.split(" ")[2];
String msg = username + MessageConstant.ALREADY_EXIST;
return Result.error(msg);
}else {
// 返回未知错误
return Result.error(MessageConstant.UNKNOWN_ERROR);
}
} - 测试结果
- 问题2:在ServiceImpl中获取当前登录用户id
- ThreadLocal并不是一个Thread,而是Thread的局部变量
- ThreadLocal为每个线程提供单独一份存储空间,具有线程隔离效果,只有在线程内才能获取到对应的值,线程外不能访问
- ThreadLocal常用方法:
- public void set(T value):设置当前线程的线程局部变量的值
- public T get():返回当前线程所对应的线程局部变量的值
- public void remove():移除当前线程的线程局部变量
- 使用ThreadLocal存储当前登录用户id
- 工具类BaseContext.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public class BaseContext {
public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
public static void setCurrentId(Long id) {
threadLocal.set(id);
}
public static Long getCurrentId() {
return threadLocal.get();
}
public static void removeCurrentId() {
threadLocal.remove();
}
}- 在登录接口中设置当前登录用户id JwtTokenAdminInterceptor.java
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/**
* jwt令牌校验的拦截器
*/
public class JwtTokenAdminInterceptor implements HandlerInterceptor {
private JwtProperties jwtProperties;
/**
* 校验jwt
*
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//判断当前拦截到的是Controller的方法还是其他资源
if (!(handler instanceof HandlerMethod)) {
//当前拦截到的不是动态方法,直接放行
return true;
}
//1、从请求头中获取令牌
String token = request.getHeader(jwtProperties.getAdminTokenName());
//2、校验令牌
try {
log.info("jwt校验:{}", token);
Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());
log.info("当前员工id:", empId);
BaseContext.setCurrentId(empId);
//3、通过,放行
return true;
} catch (Exception ex) {
//4、不通过,响应401状态码
response.setStatus(401);
return false;
}
}
}- EmployeeServiceImpl.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21/*
* 新增员工
* */
public void save(EmployeeDTO employeeDTO) {
Employee employee = new Employee();
// 属性拷贝
BeanUtils.copyProperties(employeeDTO, employee);
// 设置账号状态
employee.setStatus(StatusConstant.ENABLE);
// 设置密码,默认123456
employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));
// 设置创建时间和更新时间,创建人和更新人,后期需要改为当前登录用户id
employee.setCreateTime(LocalDateTime.now());
employee.setUpdateTime(LocalDateTime.now());
employee.setCreateUser(BaseContext.getCurrentId());
employee.setUpdateUser(BaseContext.getCurrentId());
employeeMapper.insert(employee);
}
- 问题1:在GlobalExceptionHander中处理异常信息:
二、员工分页查询
2.1 员工分页查询——功能开发
- 产品原型
- 接口设计
- 注意点:
- 分页查询需要使用PageHelper插件进行分页处理
- PageHelper.startPage方法底层也是使用ThreadLocal来存储分页信息,然后直接拼接在SQL语句中,所以SQL语句中不需要使用limit关键字
- 测试时需要注意token有效期
2.1.1 EmployeePageQueryDTO
1 |
|
2.1.2 PageResult
1 | /** |
2.1.3 EmployeeController
1 | /** |
2.1.4 EmployeeServiceImpl
1 | /** |
2.1.5 EmployeeMapper
1 | /** |
2.1.6 EmployeeMapper.xml
1 | <select id="pageQuery" resultType="com.sky.entity.Employee"> |
2.2 员工分页查询——功能测试
- 直接测试
2.3 员工分页查询——代码完善
- 当前存在的问题
- 查询结果中时间格式有问题

- 解决方法
- 方法一:在实体类中使用@JsonFormat注解进行格式化
- Employee.java
1
2
private LocalDateTime createTime; - 方法二:在WebMvcConfiguration中扩展Spring MVC的消息转换器,统一对日期进行格式化处理
- WebMvcConfiguration.java
1
2
3
4
5
6
7
8
9
10
11
12
13/**
* 扩展Spring MVC框架的消息转换器
* @param converters
*/
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
log.info("扩展消息转换器...");
// 创建一个消息转换器对象
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
// 需要为消息转换器设置一个对象转换器,对象转换器可以将java对象序列化为json对象
converter.setObjectMapper(new JacksonObjectMapper());
// 将自己的消息转换器加入到容器中,并设置优先级(索引)
converters.add(0, converter);
}
- 方法一:在实体类中使用@JsonFormat注解进行格式化
- 最终效果
三、启用禁用员工账号
3.1 启用禁用员工账号——功能开发
- 产品原型
- 业务规则
- 可以对状态为“启用”的员工账号进行“禁用”操作
- 可以对状态为“禁用”的员工账号进行“启用”操作
- 状态为“禁用”的员工账号不能登录系统
- 接口设计
- 注意点
- ServiceImpl中传递Employee对象给Mapper
- Mapper中使用xml文件进行动态SQL拼接,这样不仅可以用来更新status,还可以更新其他属性
3.1.1 EmployeeController
1 | /** |
3.1.2 EmployeeServiceImpl
1 | /** |
3.1.3 EmployeeMapper
1 | /** |
3.1.4 EmployeeMapper.xml
1 | <update id="update" parameterType="Employee"> |
3.2 启用禁用员工账号——功能测试
- 直接测试
- 在进行测试时使用body传递参数时一直报错404

- 原因是使用Apifox测试时,路径参数需要在Path中传递,不能在body中传递
- 最终测试效果
四、编辑员工
4.1 编辑员工——功能开发
- 产品原型
- 需求分析:编辑员工涉及到两个接口
- 根据id查询员工信息
- 编辑员工信息
- 接口设计
- 注意点
- 在查询员工信息时需要将密码设置为******,防止泄露用户隐私,设置之后前端接收到的数据就是:

- 在查询员工信息时需要将密码设置为******,防止泄露用户隐私,设置之后前端接收到的数据就是:
4.1.1 EmployeeController
1 | /** |
4.1.2 EmployeeServiceImpl
1 | /** |
4.1.3 EmployeeMapper
1 | /** |
4.2 编辑员工——功能测试
- 直接测试
- 查询员工信息

- 编辑员工信息



















