本文记录了苍穹外卖项目第二天的学习内容,重点介绍了员工管理模块的开发以及ThreadLocal、PageHelper、@Builder等核心技术的应用。

这里主要涉及到了两个知识点,一个是ThreadLocal的使用,一个是全局异常处理器.
ThreadLocal是 Java 提供的线程本地变量工具类,为每个线程提供一份单独的存储空间,具有线程隔离的效果,不同的线程之间不会相互干扰,只有在同一个线程内才可以获取值。
业务场景
在新增员工时,通常需要记录“创建人”的ID(即当前登录的管理员ID)。 但在 Controller → Service → Mapper 的调用链中,如果每层都传递 userId 参数,代码会变得冗长且不优雅。
解决思路
使用ThreadLocal去存储"创建人"的ID,这样不仅可以获取相应ID,同时无需进行参数传递.
实现流程

/**
* 新增员工
*
* @param employeeDTO
*/
public void save(EmployeeDTO employeeDTO) {
//.............................
//设置当前记录创建人id和修改人id
employee.setCreateUser(BaseContext.getCurrentId());
employee.setUpdateUser(BaseContext.getCurrentId());
employeeMapper.insert(employee);
}全局异常处理器(Global Exception Handler)是Spring框架提供的一种统一处理异常的机制,它允许开发者在一个集中的地方捕获和处理应用程序中抛出的各种异常,而不是在每个控制器方法中单独处理
业务场景
在新增员工接口中,username字段在数据库层面添加了唯一约束,当尝试插入重复的用户名时,数据库会抛出SQLIntegrityConstraintViolationException异常,但抛出异常并没有做出处理
解决思路
通过使用组合注解@RestControllerAdvice解决,它的作用是可以标注一个全局异常处理器,并自动扫描所有涵盖@RestController的类,统一处理异常并返回JSON格式的相应
实现流程
业务异常处理:
@ExceptionHandler
public Result exceptionHandler(BaseException ex){
log.error("异常信息:{}", ex.getMessage());
return Result.error(ex.getMessage());
}数据库约束异常处理:
@ExceptionHandler
public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){
log.info("错误信息:{}",ex.getMessage());
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);
}
}这里所使用到的是PageHelper分页查询技术
PageHelper是一个开源的MyBatis分页插件,它通过拦截器的方式,自动在SQL语句中添加分页相关的语句,简化了分页查询的开发工作。
业务场景
当员工过多时候,一个页面中全部展示出来会显得比较乱,
实现场景
PageHelper实际上就是在建立线程变量,然后在SQL语句执行的时候进行拦截,然后替换变量,实现分页的功能。
Controller层
@GetMapping("/page")
@ApiOperation("员工分页查询")
public Result<PageResult> page(EmployeePageQueryDTO employeePageQueryDTO){
log.info("分页查询{}",employeePageQueryDTO);
PageResult pageResult=employeeService.pageQuery(employeePageQueryDTO);
return Result.success(pageResult);
}Service层
@Override
public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());
Page<Employee> page=employeeMapper.pageQuery(employeePageQueryDTO);
long total=page.getTotal();
List<Employee> records=page.getResult();
return new PageResult(total,records);
}什么是@Builder模式 Builder模式是一种创建型设计模式,它提供了一种构建复杂对象的方法。通过链式调用的方式,可以灵活地设置对象的属性。
@Builder注解的作用 @Builder是Lombok提供的注解,它会自动生成Builder模式的代码,包括静态内部类Builder,链式调用方法,和build()方法
前后对比代码
// 原始类(简化版)
@Data
@Builder
public class Employee {
private Long id;
private String name;
private String username;
private Integer status;
// ... 其他字段
}
// Lombok自动生成的代码(概念性)
public class Employee {
private Long id;
private String name;
private String username;
private Integer status;
// 私有构造函数
private Employee(Builder builder) {
this.id = builder.id;
this.name = builder.name;
this.username = builder.username;
this.status = builder.status;
}
// 静态内部Builder类
public static class Builder {
private Long id;
private String name;
private String username;
private Integer status;
// 链式调用方法
public Builder id(Long id) {
this.id = id;
return this;
}
public Builder name(String name) {
this.name = name;
return this;
}
public Builder username(String username) {
this.username = username;
return this;
}
public Builder status(Integer status) {
this.status = status;
return this;
}
// 构建方法
public Employee build() {
return new Employee(this);
}
}
// 静态builder()方法
public static Builder builder() {
return new Builder();
}
}实现场景
利用该注解的类,可以在构建对象时,有着可读性强,灵活性高的特点,但同时存在着不可变性.
// 传统方式
Employee employee = new Employee();
employee.setStatus(1);
employee.setId(100L);
// Builder方式
Employee employee = Employee.builder()
.status(1)
.id(100L)
.build();序列化是将存储对象转化成另一种通用格式,例如存储为二进制、XML、JSON等。即将一个Java对象变成二进制内容,本质上是一个byte[]数组,再将该数组通过网络传输到远程,最终存储到文件或传输到网络。
反序列化就是将该二进制内容(byte[])变回Java对象,进行使用。
本文为苍穹外卖项目学习笔记,持续更新中…
如果我的内容对你有帮助,希望可以收获你的点赞、评论、收藏。