在当今数字化的商业世界中,外卖行业蓬勃发展,苍穹外卖项目作为其中的一个典型代表,其代码质量和结构足够优秀。
在苍穹外卖项目中,Day02 的开发阶段是项目成长的关键节点,深入探究这一天的代码结构,为后续的开发、维护以及性能优化提供坚实的基础和清晰的方向。
Controller层:
Controller 层承担着接收和处理 HTTP 请求的重任,对前端传来的数据进行初步校验,确保数据的合法性和完整性,防止无效或错误的数据进入系统。
例如,在该项目的新增员工功能中,当接收到前端发送的新增员工请求时,它会依据特定的规则检查 EmployeeDTO中的各个字段,如确保姓名不为空且长度符合要求,手机号格式准确无误等。只有通过校验的数据才会被放行,传递给 Service 层进行进一步的业务处理;若校验不通过,则立即返回包含详细错误信息的响应,告知前端用户具体的错误所在,以便用户及时修正。
新增员工代码如下:
java
@RestController
@RequestMapping("/admin/employee")
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
@PostMapping("/save")
public Result saveEmployee(@RequestBody EmployeeDTO employeeDTO) {
// 调用Service层方法保存员工信息
employeeService.save(employeeDTO);
return Result.success();
}
}
在上述代码中, @RestController注解明确了这是一个用于处理RESTful风格请求并返回JSON数据的控制器类。@RequestMapping为该控制器类定义了统一的请求路径前缀,使得接口具有清晰的层级结构和规范性。
通过@RequestBody注解对传入的EmployeeDTO进行参数校验,确保数据的准确性,然后将其传递给 EmployeeService的 save 方法,整个过程简洁明了,清晰地展示了请求的接收与初步处理流程。
Service 层:
Service负责协调各个模块,组织和执行复杂的业务操作,在新增员工的业务流程中,它首先要将从Controller层接收的EmployeeDTO转换为Employee实体对象。
java
@Service
public class EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
public void save(EmployeeDTO employeeDTO) {
Employee employee = new Employee();
// 属性拷贝,将DTO中的部分属性复制到Employee实体对象
BeanUtils.copyProperties(employeeDTO, employee);
// 设置创建时间等额外属性
employee.setCreateTime(new Date());
employee.setUpdateTime(new Date());
employeeMapper.insert(employee);
}
}
在 save方法中,首先实例化Employee实体对象,借助BeanUtils工具类高效地完成属性拷贝,将 EmployeeDTO中的相关属性值复制到Employee中,避免了手动逐个赋值的繁琐过程。
随后,通过调用new Date()为Employee对象设置创建时间和更新时间,确保数据的完整性和时效性。最后,调用EmployeeMapper的insert方法将员工数据插入到数据库中。
Mapper 层:
Mapper 层专注于与数据库的交互,负责将Service层的业务需求转化为具体的 SQL 语句操作,确保数据在数据库中的增删改查执行。
以新增员工为例,EmployeeMapper接口中定义的insert方法对应的 SQL 语句能够将传入的 Employee实体对象中的各个属性值插入到数据库的employee表相应字段中,而在分页查询场景下, selectByPage方法对应的 SQL 语句则展现出强大的灵活性和适应性,它会根据传入的员工姓名等查询条件,使用动态 SQL 技术,如通过 <if> 标签判断条件是否存在,动态地添加WHERE 子句和模糊查询条件( LIKE '%?%' ),确保能够从数据库中获取符合条件的员工记录列表。
java
@Mapper
public interface EmployeeMapper {
int insert(Employee employee);
List<Employee> selectByPage(EmployeePageQueryDTO queryDTO);
}
以上为insert与selectByPage在mapper中的实现,这还不够,我们还需要xml映射:
XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3.dtd">
<mapper namespace="com.example.demo.mapper.EmployeeMapper">
<insert id="insert" keyProperty="id" useGeneratedKeys="true">
insert into employee (name, age, gender, phone, position, create_time, update_time)
values (#{name}, #{age}, #{gender}, #{phone}, #{position}, #{createTime}, #{updateTime})
</insert>
<select id="selectByPage" resultMap="EmployeeResultMap">
select * from employee
<where>
<if test="name!= null and name!= ''">
and name like concat('%', #{name}, '%')
</if>
</where>
</select>
</mapper>
Entity 层:
Entity 层将数据库中的表结构与 Java 代码紧密地连接在一起,主要负责将数据库表中的每一行数据抽象成一个具体的 Java 对象,即实体类。
代码示例:
java
@Data
public class Employee {
private Long id;
private String name;
private Integer age;
private String gender;
private String phone;
private String position;
private Date createTime;
private Date updateTime;
}
Employee实体类的属性与数据库employee表中的各个字段一一对应,精准地映射到表中的各个字段,并且通过提供规范的getter和setter方法(@Data),使得其他层能够方便、安全地访问和修改这些数据属性。
数据传输对象(DTO)结构:
项目中巧妙运用了多个DTO 类,如 EmployeeDTO 、 EmployeePageQueryDTO 等,这些DTO 在前端与后端以及不同层之间高效地传输数据。以EmployeeDTO为例,只包含前端需要传递给后端以及后端需要反馈给前端的关键信息,在新增员工的场景中, EmployeeDTO有姓名、性别、年龄、电话、职位等用户在前端表单中填写的核心字段,大大减少了数据传输过程中的不必要开销,提高了数据传输的效率和速度。
示例代码:
java
@Data
public class EmployeeDTO {
private String name;
private Integer age;
private String gender;
private String phone;
private String position;
}
异常处理结构:
项目构建了一个全局异常处理类,通过@ControllerAdvice注解全方位地捕捉整个项目中所有控制器抛出的异常,确保系统在面对各种突发情况时能够保持稳定和可靠。在这个类中,利用@ExceptionHandler注解标注各个方法,每个方法都针对特定类型的异常进行处理。
例如,当新增员工操作触发SQLIntegrityConstraintViolationException (数据库完整性约束被违反)时,全局异常处理类将这些精心包装好的错误信息封装成一个包含错误码和错误描述的 Result对象返回给前端,使得前端用户能够清晰地了解到操作失败的原因。
总结:
通过对苍穹外卖项目 Day02 代码结构的深入剖析,我们清晰地看到了一个结构严谨、层次分明且高效协作的代码体系,分层架构的设计使得各层职责明确。
随着项目的不断发展和业务需求的日益复杂,代码结构也需要持续优化。例如,可以进一步优化数据库查询语句,引入更高效的缓存机制以提升数据访问速度,对代码中的重复逻辑进行更深入的重构以提高代码的复用性和可维护性。同时,加强单元测试和集成测试的覆盖范围,确保代码的稳定性和正确性,为项目的长期发展奠定更加坚实的基础。总之,Day02 的代码结构为项目的后续演进提供了一个良好的开端,但也需要我们持续关注和不断改进,以适应不断变化的业务环境和技术挑战。