本文目录导读:

针对 Java 功能结构案例的规整,核心在于遵循清晰的分层架构(通常是 MVC 或其变体)和统一的命名规范,案例代码应具备可读性、可测试性和可扩展性。
以下是规整 Java 功能结构案例的标准化步骤和具体示例。
核心原则
- 按功能(业务领域)分包,而非按层分包:这是与早期项目最大的区别,将相关的 Controller、Service、DAO、DTO 放在同一个包下。
- 单一职责:一个类、一个方法只做一件事。
- 依赖倒置:依赖抽象(接口),而非具体实现。
- 清晰的层次划分:严格区分 Request/Response(应用层)、Service(业务层)、Repository(数据层)。
标准项目结构(包结构)
假设一个“用户管理”模块:
src/main/java/com/example/demo/ │ ├── config/ # 配置类(全局,非功能模块) │ └── WebMvcConfig.java │ ├── common/ # 通用工具、异常、常量(全局) │ ├── exception/ │ │ ├── GlobalExceptionHandler.java │ │ └── BusinessException.java │ ├── result/ │ │ └── Result.java # 统一响应体 │ └── util/ │ └── StringUtils.java │ ├── modules/ # 功能模块(核心) │ ├── user/ # 🎯 用户模块 │ │ ├── controller/ # 1. 控制层 │ │ │ └── UserController.java │ │ ├── service/ # 2. 服务层 │ │ │ ├── UserService.java (接口) │ │ │ └── impl/ │ │ │ └── UserServiceImpl.java (实现) │ │ ├── repository/ # 3. 数据访问层 │ │ │ └── UserRepository.java │ │ ├── entity/ # 4. 数据实体(与DB对应) │ │ │ └── User.java │ │ ├── dto/ # 5. 数据传输对象(专门给API用) │ │ │ ├── request/ │ │ │ │ └── UserCreateRequest.java │ │ │ └── response/ │ │ │ └── UserResponse.java │ │ └── converter/ # 6. 对象转换器(可选,可用MapStruct代替) │ │ └── UserConverter.java │ │ │ └── order/ # 另一个功能模块 │ ├── controller/ │ └── ... │ └── Application.java # 启动类
为什么这样规整?
- 高内聚:用户的所有代码都在
user包内,修改用户功能只需关注这一个目录。 - 低耦合:
user模块不直接依赖order模块的具体类,只依赖其接口或 DTO。 - 易于维护:新同事接手时,能快速定位业务逻辑。
具体代码层级规整(以“创建用户”为例)
Controller 层(控制层):只负责接收参数和返回结果
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public Result<UserResponse> createUser(@RequestBody @Valid UserCreateRequest request) {
// 1. 调用业务层
UserResponse response = userService.createUser(request);
// 2. 返回统一格式
return Result.success(response);
}
}
Request/Response(请求/响应):完全独立,不包含业务逻辑
// UserCreateRequest.java (入参校验)
@Data
public class UserCreateRequest {
@NotBlank(message = "用户名不能为空")
@Size(min = 4, max = 20, message = "用户名长度需在4-20字符之间")
private String username;
@Email(message = "邮箱格式不正确")
private String email;
private String phone;
}
// UserResponse.java (出参,不暴露敏感字段)
@Data
public class UserResponse {
private Long id;
private String username;
private String email;
private String phone;
private LocalDateTime createdAt;
}
Service 层(业务层):核心业务逻辑,使用接口 + 实现类
// UserService.java (接口)
public interface UserService {
UserResponse createUser(UserCreateRequest request);
}
// UserServiceImpl.java (实现)
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private UserConverter userConverter; // 对象转换器
@Override
public UserResponse createUser(UserCreateRequest request) {
// 1. 业务校验(如检查用户名是否已存在)
if (userRepository.existsByUsername(request.getUsername())) {
throw new BusinessException(400, "用户名已存在");
}
// 2. 转换 Request -> Entity
User user = userConverter.toEntity(request);
// 3. 调用数据层保存
User savedUser = userRepository.save(user);
// 4. 转换 Entity -> Response
return userConverter.toResponse(savedUser);
}
}
Repository 层(数据访问层):只包含数据库操作,使用 Spring Data JPA/MyBatis-Plus
// UserRepository.java
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
boolean existsByUsername(String username);
}
Entity 实体层:与数据库表字段一一对应,使用 JPA 注解
// User.java
@Entity
@Table(name = "sys_user")
@Data
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true)
private String username;
private String email;
private String phone;
@Column(updatable = false)
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
@PrePersist
protected void onCreate() {
this.createdAt = LocalDateTime.now();
this.updatedAt = LocalDateTime.now();
}
}
Converter(对象转换器):避免手动写 get/set,推荐使用 MapStruct
// UserConverter.java (MapStruct)
@Mapper(componentModel = "spring")
public interface UserConverter {
User toEntity(UserCreateRequest request);
UserResponse toResponse(User user);
}
规整清单(Checklist)
在提交代码前,请逐一检查:
| 类别 | 要求 | 示例 |
|---|---|---|
| 命名规则 | 类名使用 PascalCase,变量/方法使用 camelCase | UserCreateRequest, getUserName() |
| 分层清晰 | Controller 不能注入 Repository | 必须通过 Service 层 |
| 异常处理 | 全局异常处理,业务异常定义标准码 | throw new BusinessException(400, "xxx") |
| 参数校验 | 使用 @Valid + @NotBlank 等 |
写在 Request 类上 |
| 无用依赖 | 禁止在 Controller 中引入 Entity | 用 DTO 替代 |
| 日志规范 | 使用 SLF4J 接口,打印关键入参和异常 | log.info("创建用户:{}", request) |
| 单元测试 | 核心 Service 方法应有测试 | JUnit + Mockito |
规整后的优点
- 可读性强:打开
modules/user目录,就能看清该模块的完整骨架。 - 易于测试:Service 层的接口和实现分离,便于使用 Mock 进行单元测试。
- 易于协作:多人开发时,每人负责一个
modules/xxx模块,减少代码冲突。 - 易于重构:要修改用户查询逻辑,只需修改
UserServiceImpl和UserRepository,不影响其他模块。
通过这种规整方式,Java 功能结构案例会变得逻辑清晰、代码整洁,非常适合用于团队协作或教学演示。