新增员工
1.接收前端提交的数据
- 前端提交过来的是json格式,所以有@RequestBody注解
- @PostMapping后没有写地址是因为在Controller最初就已经写了"/admin/employee",看接口设计中可以知道本身新增员工就是用的这个接口
// EmpolyeeController.java
/**
* 新增员工
*
* @param employeeDTO
* @return
*/
@PostMapping // 路径“/admin/employee”,class上面28行已经加过了,所以只要注解就行了
@ApiOperation("新增员工")
public Result save(@RequestBody EmployeeDTO employeeDTO) // 用EmployeeDTO接收前端发过来的数据,返回用Result封装
{
// @RequestBody:注解,前端提交过来的是json格式的数据
log.info("新增员工:{}", employeeDTO);
employeeService.save(employeeDTO); // 调用,传入employeeDTO
return Result.success();
}
2.实现新增员工的方法
- BeanUtils.copyProperties实现属性拷贝
- DigestUtils.md5DigestAsHex实现明文转为密文
- 不要直接用常数写在代码中,应该用constant文件管理
/**
* 新增员工业务方法
* @param employeeDTO
*/
public void save(EmployeeDTO employeeDTO) {
// 调用持久层Mapper,把数据插进去,传过来的还是DTO,但是传给实体层,还是用实体Employee
Employee employee = new Employee();
// 设置employee实体的属性值,对象属性拷贝,一次性将所有属性拷贝过来
BeanUtils.copyProperties(employeeDTO, employee); // 从employeeDTO拷贝到employee,两边是属性名得一致
// employee中的部分属性employeeDTO中没有,需要手动设置
// 设置账号状态,1表示正常
employee.setStatus(StatusConstant.ENABLE); // 避免硬编码
// 设置密码,新增员工默认密码123456,存的是md5加密后的,默认密码也设置了个常量
employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));
// 设置创建时间和修改时间 - 系统时间
employee.setCreateTime(LocalDateTime.now());
employee.setUpdateTime(LocalDateTime.now());
// 修改当期记录创建人ID和修改人ID
// TODO 后期需要改成当前用户登录的ID
employee.setCreateUser(10L); // 先写死,后面完善
employee.setUpdateUser(10L);
employeeMapper.insert(employee);
}
3.EmployeeMapper中声明insert方法
- 这里一定要设置能识别mysql,不然有报错,而且必须连接数据库
- 数据库导入后记得刷新一下,不然也许会报错
- SQL语句必须写对
/**
* 插入员工数据
* @param employee
*/
@Insert("insert into employee (name, username, password, phone, sex, id_number, create_time, update_time, create_user, update_user, status) " +
"values " +
"(#{name}, #{username}, #{password}, #{phone}, #{sex}, #{idNumber}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser}, #{status})")
void insert(Employee employee);
4.测试
- 在测试时,会出现测试报错,这是因为JWT令牌校验失败,导致EmployeeController的save方法没有被调用
- 需要将合法的token添加到全局参数中
- 在接口调试那边添加JWT令牌,不然就一直报401
- 令牌过期的话就用相同方式,重新生成令牌
5.完善
仍存在的问题:
- 如果录入的用户名已经存在,抛出异常后没有处理
- 新增员工时,创建人id和修改人id设置为了固定值
5.1重复录入异常处理
// GlobalExceptionHandler.java
/**
* 处理SQL异常
* @param ex
* @return
*/
@ExceptionHandler
public Result exceptionHandler(SQLIntegrityConstraintViolationException ex) {
String message = ex.getMessage(); // 获取异常信息
if(message.contains("Duplicate entry")){
String[] split = message.split(" ");
String username = split[2]; // 获取重复的用户名
String msg = username + MessageConstant.ALREADY_EXISTS; // 重复插入错误
return Result.error(msg);
}else { // 未知错误
return Result.error(MessageConstant.UNKNOWN_ERROR); // 未知错误
}
}
5.2创建人id和修改人id
- 登录成功过后,会生成JWT返回给前端,而通过JWT可以解析出当前登录员工的id
- 通过在拦截器中解析出当前登录员工id,并放入线程局部变量中
- 客户端每次发起的请求,都是一个单独的线程 → 每一次请求过来,在拦截器那边取出用户id,存到线程空间里,后面执行save()的时候就可以通过线程空间取出用户id
/**
* 校验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); // 将当前用户id放到ThreadLocal空间里,加的是这句
//3、通过,放行
return true;
} catch (Exception ex) {
//4、不通过,响应401状态码
response.setStatus(401);
return false;
}
}
/**
* 新增员工业务方法
* @param employeeDTO
*/
public void save(EmployeeDTO employeeDTO) {
// 调用持久层Mapper,把数据插进去,传过来的还是DTO,但是传给实体层,还是用实体Employee
Employee employee = new Employee();
// 设置employee实体的属性值,对象属性拷贝,一次性将所有属性拷贝过来
BeanUtils.copyProperties(employeeDTO, employee); // 从employeeDTO拷贝到employee,两边是属性名得一致
// employee中的部分属性employeeDTO中没有,需要手动设置
// 设置账号状态,1表示正常
employee.setStatus(StatusConstant.ENABLE); // 避免硬编码
// 设置密码,新增员工默认密码123456,存的是md5加密后的,默认密码也设置了个常量
employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));
// 设置创建时间和修改时间 - 系统时间
employee.setCreateTime(LocalDateTime.now());
employee.setUpdateTime(LocalDateTime.now());
// 完善部分:
// 修改当期记录创建人ID和修改人ID
employee.setCreateUser(BaseContext.getCurrentId()); // 从ThreadLocal空间里取出当前用户id
employee.setUpdateUser(BaseContext.getCurrentId());
employeeMapper.insert(employee);
}