目录
管理端开发
准备工作:
前端
双击nginx.exe运行前端项目
后端
接口文档:使用工具Apifox导入api接口文档,这里给的数据是从YAPI导出的
导入初始化工程:common(公共功能模块)、pojo(处理数据的接收、返回,就是为了更好封装数据)、server(处理接口)
加载maven依赖
yml配置:mysql服务地址、密码
JDK版本: 11
数据库
导入sky.sql脚本
启动后端服务运行

员工相关接口开发
分页查询员工信息
@Override
public Result<PageResult> pageEmployee(String name, Integer page, Integer pageSize) {
// 开启分页查询
PageHelper.startPage(page, pageSize);
// 动态条件查询
Page<Employee> employeeList = employeeMapper.pageEmployee(name);
PageResult pageResult = new PageResult(employeeList.getTotal(), employeeList.getResult());
return Result.success(pageResult);
}
使用PageHelper工具类开启分页查询,PageHelper会在执行sql前进行拦截并且拼接分页sql,然后进行查询时返回数据类型为Page<>,这样返回的该对象会包含总记录数、总页数、当前页码、每页记录数等分页信息。
禁用员工账号
修改员工信息
public void UpdateStatus(Integer status, Long id) {
Employee employee = Employee
.builder()
.id(id).status(status)
.build();
employeeMapper.updateStatus(employee);
}
虽然可以直接传入禁用和员工id进行禁用,可将其封装为Entity类再进行修改,这样两个Service就可以调用同一个mapper来完成更新。
新增员工
@Override
public void save(EmployeeDTO employeeDTO) {
Employee employee = new Employee();
BeanUtils.copyProperties(employeeDTO, employee);
String password = DigestUtils.md5DigestAsHex(DEFAULT_PASSWORD.getBytes());// 默认密码进行md5加密
employee.setPassword(password);
employee.setStatus(StatusConstant.ENABLE);
employee.setCreateTime(LocalDateTime.now());
employee.setUpdateTime(LocalDateTime.now());
employee.setCreateUser(BaseContext.getCurrentId());
employee.setUpdateUser(BaseContext.getCurrentId());
employeeMapper.save(employee);
}
可以看到这里有大量重复冗余的代码,就是将当前时间和用户id信息传入进employee。并且在以后的更新和新增操作还要重复写这些代码
解决:AOP
// 枚举类
public enum OperationType {
/**
* 更新操作
*/
UPDATE,
/**
* 插入操作
*/
INSERT
}
//第一步:自定义注解,用于标识需要进行公共字段填充的方法
//元注解,用于指定被注解的元素类型, 这里指方法
@Target(ElementType.METHOD)
//在运行时仍然保留,通过反射机制在运行时获取注解信息。意味着在程序运行过程中,可以使用 Java 的反射 API 来检查某个方法是否被 AutoFill 注解标记,以及获取注解中定义的属性值。
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
//定义需要自动填充的字段, 数据库操作的类型 update 、insert
OperationType value();
}
// 第二步:自定义切面类,用于拦截加入自定义注解的方法
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
public void autoFillPointCut() {
}
// 在 autoFillPointCut 所定义的切入点的目标方法执行前执行
@Before("autoFillPointCut()")
public void autoFill(JoinPoint joinPoint) {
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();
try {
if (operationType == OperationType.INSERT) {
// 为实体对象各个属性赋值
invokeSetMethod(entity, AutoFillConstant.SET_CREATE_TIME, now);
invokeSetMethod(entity, AutoFillConstant.SET_CREATE_USER, currentId);
invokeSetMethod(entity, AutoFillConstant.SET_UPDATE_TIME, now);
invokeSetMethod(entity, AutoFillConstant.SET_UPDATE_USER, currentId);
} else if (operationType == OperationType.UPDATE) {
// 为实体对象各个属性赋值
invokeSetMethod(entity, AutoFillConstant.SET_UPDATE_TIME, now);
invokeSetMethod(entity, AutoFillConstant.SET_UPDATE_USER, currentId);
}
} catch (Exception e) {
log.error("自动填充数据时发生异常", e);
}
}
private void invokeSetMethod(Object entity, String methodName, Object value) throws Exception {
Method method = entity.getClass().getDeclaredMethod(methodName, value.getClass());
method.invoke(entity, value);
}
}
// 第三步:在Mapper的方法加上自定义注解
@AutoFill(value = OperationType.UPDATE)
void updateStatus(Employee employee);
@AutoFill(value = OperationType.INSERT)
void save(Employee employee);
Gitee管理代码
远程仓库
Gitee 官网(https://gitee.com/),点右上角 “+” 选 “新建仓库”,复制 HTTPS 或 SSH 地址。
本地仓库
idea点击 “VCS”,选 “Import into Version Control”→“Create Git Repository”,选项目根目录确认。
关联
点击 “VCS”→“Git”→“Remotes”,点 “+”,“Name” 填 “origin”,“URL” 粘贴 Gitee 复制的地址,测试连接后确认。
提交到本地仓库And推送到远程仓库
提交(Commit) 、推送(Push)
分类接口开发
代码功能基本和员工管理类似,不做概述
1892

被折叠的 条评论
为什么被折叠?



