0、记录三个瑕疵功能:
1、员工修改密码问题
问题:员工管理页面无法修改密码
造成原因:前端请求中携带的参数不全,只携带了newPassword和oldPassword并没有携带需要修改员工的Id,导致无法定位修改哪位员工的密码
接口文档:
2、按类型查找分类问题
问题:按照类型查找的请求进入了分页查找的controller
造成原因:请求路径错误
接口文档中请求路径:/admin/category/list
实际请求路径:/admin/category/page
3、删除操作和分页查询问题
问题:删除某页最后一条数据后,会继续显示当前空数据页
造成原因:后端在删除当前页最后一条数据后,自动调用分页查询,并传入当前为null的页码分页查询
1、分类管理页面
整体逻辑和员工管理差不多,也是只涉及到CRUD且没有什么特殊的逻辑和知识点,因此这里不多叙述
2、公共字段自动填充
引出:
由于对员工信息的增、改操作都会涉及到对creatTime、createUser、updateTime、updateUser信息补充,因此这部分重复冗余的代码可以想办法提取出来处理。
解决:
通过之前Spring的学习我们知道AOP面向切面编程可以实现在不改动原代码的情况下增强或修改代码的功能,因此使用AOP切面编程。
整体思路:
- 创建自定义注解类
- 创建切面类
- 将mapper层的update和insert操作作为连接点进行aop操作
- 在切面类中选择Before通知操作
2.1自定义注解类
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
//1、设置一个value用来区分是什么操作
OperationType value();
}
主要操作:
- 添加@Target设置该注解标记的位置在方法上
- 添加@Retention设置注解生效范围
- OperationType value() 表示设置注解的值为OperationType类型,之后切面类可以通过该值判断是对什么连接点进行操作
2.2创建切面类
@Component
@Aspect
@Slf4j
public class AutoFillAspect {
@Pointcut("execution (* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
public void path(){}
@Before("path()")
public void Before(JoinPoint joinPoint) throws Exception {
//0、日志打印操作
log.info("公共字段自动注入");
//1、获取原始签名
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//2、获取原始签名上的注解
AutoFill annotation = signature.getMethod().getAnnotation(AutoFill.class);
//3、获取注解类型
OperationType operationType = annotation.value();
//4、获取对象和Class类
Object[] args = joinPoint.getArgs();
Class<?> clazz = args[0].getClass();
//5、通过反射获取方法
//5.1、如果是Update操作则只需要填充updateTime和updateUser
Method updateTime = clazz.getMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
Method updateUser = clazz.getMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
updateTime.invoke(args[0],LocalDateTime.now());
updateUser.invoke(args[0],BaseContext.getCurrentId());
//5.2、如果是Insert操作则还需要填充createTime和createUser
if(operationType == OperationType.INSERT){
Method createUser = clazz.getMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
Method createTime = clazz.getMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
createTime.invoke(args[0],LocalDateTime.now());
createUser.invoke(args[0], BaseContext.getCurrentId());
}
}
}
主要操作:
- @Component 将该类交给IOC管理
- @Aspect 标记该类为切面类
- @Pointcut 中抽取切入点表达式到path()方法,这样之后使用相同的切入点表示式只需要使用path()方法即可
- @Before 表示该通知为Before类型,执行在连接点之前
2.3连接点
@AutoFill(OperationType.INSERT)
@Insert("insert into employee values(null,#{name},#{username}" +
",#{password},#{phone},#{sex},#{idNumber},#{status},#{createTime},#{updateTime},#{createUser},#{updateUser})")
void save(Employee employee);
@AutoFill(OperationType.UPDATE)
void update(Employee employee);
在mapper层的update和insert操作上添加@AutoFill标记为连接点