本文目录导读:

针对 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 功能结构案例会变得逻辑清晰、代码整洁,非常适合用于团队协作或教学演示。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播