目录
启用禁用员工账号
需求分析
代码开发
编辑员工信息
需求分析
根据 id 查找员工设计代码开发
编辑员工信息的代码开发
公共字段的填充
问题分析
优化思路
代码开发
代码地址:苍穹外卖
启用禁用员工账号
需求分析
代码开发
Controller
@PostMapping("/status/{status}")@ApiOperation("启用禁用员工账号")public Result startOrStop(@PathVariable Integer status,Long id){log.info("启用禁用员工{},{}",status,id);employeeService.startOrStop(status,id);return Result.success();}
Service
@Overridepublic void startOrStop(Integer status, Long id) {Long userId = BaseContext.getCurrentId();Employee employee = Employee.builder().status(status).id(id).updateTime(LocalDateTime.now()).updateUser(userId).build();employeeMapper.update(employee);}
Mapper
启动员工账号,就是更改当前列的状态。我们可以复用修改员工信息的 Mapper 只更改前端传过来的状态即可。
<update id="update">UPDATE employee<set><trim suffixOverrides=","><if test="name!=null">name=#{name},</if><if test="username!=null">username=#{username},</if><if test="password!=null">password=#{password},</if><if test="phone!=null">phone=#{phone},</if><if test="sex!=null">sex=#{sex},</if><if test="idNumber!=null">id_number=#{idNumber},</if><if test="status!=null">status=#{status},</if><if test="updateTime!=null">update_time=#{updateTime},</if><if test="updateUser!=null">update_user=#{updateUser},</if></trim></set><where>id=#{id}</where></update>
编辑员工信息
需求分析
编辑员工的接口文档
我们的编辑员工的业务需求其实需要设计两个接口,在编辑员工之前需要按照 id 查找指定的编辑员工的信息。
查找员工信息的接口文档
根据 id 查找员工设计代码开发
Controller
@GetMapping("/{id}")@ApiOperation("根据id查找员工")public Result<Employee> FindById(@PathVariable Long id){log.info("根据id查找员工{}",id);Employee employee = employeeService.getById(id);return Result.success(employee);}
Serivce
@Overridepublic Employee getById(Long id) {Employee employee = employeeMapper.getById(id);employee.setPassword("*****");return employee;}
Mapper
@Select("select * from employee where id=#{id}")Employee getById(Long id);
编辑员工信息的代码开发
Controller
@PutMapping@ApiOperation("编辑员工信息")public Result update(@RequestBody EmployeeDTO employeeDTO){log.info("编辑员工信息{}",employeeDTO);employeeService.update(employeeDTO);return Result.success();}
Service
@Overridepublic void update(EmployeeDTO employeeDTO) {// 前端参数类转化成实体类Employee employee = new Employee();// 拷贝转化BeanUtils.copyProperties(employeeDTO, employee);// 设置参数employee.setUpdateTime(LocalDateTime.now());employee.setUpdateUser(BaseContext.getCurrentId());employeeMapper.update(employee);}
Mapper 与 启用禁用员工账号相同
公共字段的填充
问题分析
我们在新增或者更新信息的时候,都需要获取当前时间与用户信息;这其实是一个比较固定的代码。 如果是一个比较大的项目,就有多处需要设置这些参数。这样势必会造成代码冗余、不便于后期维护。
优化思路
分析操作类型需要设置的字段:
比如:执行 insert 操作时,需要更新四个字段;而执行 update 操作时只需要更新两个字段
于是我们可以在 Mapper 层通过 AOP 给指定方法进行拦截,自动修改公共字段
代码开发
自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {// 数据库操作类型 UPDATE INSERTOperationType value();
}
自定义切面类
@Aspect
@Component
@Slf4j
public class AutoFillAspect {// 切入点@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")public void autoFillPointCut(){}@Before("autoFillPointCut()")public void autoFill(JoinPoint joinPoint) throws Exception {log.info("开始进行公共字段的自动填充...");// 获取当前被拦截的方法上的数据库操作类型MethodSignature signature = (MethodSignature) joinPoint.getSignature(); //方法签名对象AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class); //获取方法上的注解对象OperationType operationType = autoFill.value(); //获取数据库操作类型// 获取当前被拦截方法的参数 -- 实体对象Object[] args = joinPoint.getArgs();if(args == null || args.length == 0){return;}Object entity = args[0];// 准备赋值数据LocalDateTime now = LocalDateTime.now();Long currentId = BaseContext.getCurrentId();// 根据当前不同的操作类型,为对应的属性通过反射来赋值if(operationType == OperationType.INSERT){// 通过反射获取实例对象Method setCreateTime = entity.getClass().getMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);Method setUpdateTime = entity.getClass().getMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setCreateUser = entity.getClass().getMethod(AutoFillConstant.SET_CREATE_USER, Long.class);Method setUpdateUser = entity.getClass().getMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);// 通过反射为对象赋值setCreateTime.invoke(entity,now);setUpdateTime.invoke(entity,now);setCreateUser.invoke(entity,currentId);setUpdateUser.invoke(entity,currentId);}else if(operationType == OperationType.UPDATE){// 通过反射获取实例对象Method setUpdateUser = entity.getClass().getMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);Method setUpdateTime = entity.getClass().getMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);// 通过反射为对象赋值setUpdateTime.invoke(entity,now);setUpdateUser.invoke(entity,currentId);}}
}
Mapper
需要添加注解才能在操作的时候自动填充字段
@AutoFill(value = OperationType.INSERT)void insert(Employee Employee);Page<Employee> pageQuery(EmployeePageQueryDTO employeePageQueryDTO);@AutoFill(value = OperationType.UPDATE)void update(Employee employee);
记得在所有需要自动填充的方法上面添加 autoFill 注解,并删除原来在 Service 层进行填充的冗余代码(包括 builder 里面创建实体类中填充的冗余字段)
调试一下~