现代化 Java 分层开发采用清晰的层次结构和设计模式,有助于提高代码的可维护性、可测试性和可扩展性。以下是一套被广泛认可的最佳实践:
一. 项目结构分层
采用标准的 Maven/Gradle 项目结构,按职责划分模块:
src/main/java/ ├── com.example.app/ │ ├── config/ # 配置类(如Spring配置) │ ├── controller/ # Web控制器层 │ ├── service/ # 业务逻辑层 │ ├── repository/ # 数据访问层 │ ├── model/ # 数据模型 │ │ ├── dto/ # 数据传输对象 │ │ ├── entity/ # 持久化实体 │ │ └── mapper/ # 对象映射器 │ ├── exception/ # 自定义异常 │ └── util/ # 工具类 └── resources/ ├── application.yml # 配置文件 └── db/ # 数据库脚本 二. 各层职责与实现
(1) 实体层(Entity)
职责:映射数据库表结构,使用 JPA 注解。
最佳实践:
仅包含数据字段和基本 getter/setter。
使用@Entity、@Table等 JPA 注解。
避免业务逻辑,保持 POJO 纯净。2. 各层职责与实现
// UserEntity.java @Entity @Table(name = "users") public class UserEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; private String email; // getters/setters } (2) 数据传输对象(DTO)
职责:封装跨层传输的数据,避免直接暴露实体。
最佳实践:
使用 Lombok 减少样板代码。
通过映射器(Mapper)与 Entity 转换。
// UserDTO.java @Data @NoArgsConstructor @AllArgsConstructor public class UserDTO { private Long id; private String username; private String email; } (3) 数据访问层(Repository)
职责:与数据库交互,使用 Spring Data JPA。
最佳实践:
继承JpaRepository或CrudRepository。
使用自定义查询方法(如findByEmail)。
避免复杂查询,必要时使用@Query注解。
// UserRepository.java public interface UserRepository extends JpaRepository<UserEntity, Long> { Optional<UserEntity> findByEmail(String email); } (4) 服务层(Service)
职责:实现核心业务逻辑,事务管理。
最佳实践:
使用@Service注解声明服务。
通过@Transactional管理事务。
依赖注入 Repository。
处理业务异常(如serNotFoundException)。
// UserService.java @Service @Transactional public class UserService { private final UserRepository userRepository; private final UserMapper userMapper; public UserService(UserRepository userRepository, UserMapper userMapper) { this.userRepository = userRepository; this.userMapper = userMapper; } public UserDTO createUser(UserDTO userDTO) { UserEntity entity = userMapper.toEntity(userDTO); UserEntity savedEntity = userRepository.save(entity); return userMapper.toDTO(savedEntity); } public UserDTO getUserById(Long id) { return userRepository.findById(id) .map(userMapper::toDTO) .orElseThrow(() -> new UserNotFoundException("User not found with id: " + id)); } } (5) 控制器层(Controller)
职责:处理 HTTP 请求,返回 JSON 响应。
最佳实践:
使用@RestController和请求映射注解(如@GetMapping)。
参数校验(如@Valid)。
异常处理(如@ExceptionHandler)。
返回ResponseEntity或自定义响应格式。
// UserController.java @RestController @RequestMapping("/api/users") public class UserController { private final UserService userService; public UserController(UserService userService) { this.userService = userService; } @PostMapping public ResponseEntity<UserDTO> createUser(@Valid @RequestBody UserDTO userDTO) { UserDTO createdUser = userService.createUser(userDTO); return ResponseEntity.status(HttpStatus.CREATED).body(createdUser); } @GetMapping("/{id}") public ResponseEntity<UserDTO> getUser(@PathVariable Long id) { UserDTO userDTO = userService.getUserById(id); return ResponseEntity.ok(userDTO); } } (6) 映射器(Mapper)
职责:实现 Entity 与 DTO 的相互转换。
最佳实践:
使用 MapStruct 或 ModelMapper 自动生成映射代码。
避免手动编写转换逻辑。
// UserMapper.java @Mapper(componentModel = "spring") public interface UserMapper { UserDTO toDTO(UserEntity entity); UserEntity toEntity(UserDTO dto); } 三. 关键技术与工具
Spring Boot:快速搭建项目,自动配置依赖。
Spring Data JPA:简化数据库访问。
Lombok:减少样板代码(如@Data、@Builder)。
MapStruct:实体映射工具。
Validation API:参数校验(如@NotNull、@Size)。
Spring Security:身份验证与授权。
Docker:容器化部署。
JUnit 5 + Mockito:单元测试。
四. 测试策略
单元测试:测试 Service 层逻辑,使用 Mockito 模拟依赖。
集成测试:测试 Controller 层,使用@WebMvcTest或@SpringBootTest。
数据库测试:使用 H2 内存数据库或 Testcontainers。
// UserServiceTest.java @ExtendWith(MockitoExtension.class) class UserServiceTest { @Mock private UserRepository userRepository; @Mock private UserMapper userMapper; private UserService userService; @BeforeEach void setUp() { userService = new UserService(userRepository, userMapper); } @Test void shouldCreateUser() { // 测试逻辑... } } 五. 技术栈升级
- Spring Boot 3.0+:简化项目搭建和配置
- Spring Data JPA:提供更高级的ORM功能
- MapStruct:自动生成对象映射代码
- Lombok:减少样板代码
- Spring Validation:统一参数校验
- Record类(Java 14+):简化不可变数据类
OpenAPI/Springdoc:自动生成API文档
现代化代码实现:下面是一个使用上述技术的现代化实现示例:
(1). 使用Lombok和JPA注解的PO
@Entity @Table(name = "users") @Data // Lombok注解自动生成getter/setter等 @NoArgsConstructor @AllArgsConstructor public class UserPO { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false, unique = true) private String username; @Column(nullable = false) private String encryptedPassword; private LocalDateTime createdAt; } (2). 使用Record类的DTO
public record UserDTO(Long id, String username, LocalDateTime createdAt) { } (3). 使用Record类的VO
public record UserVO(String username, String formattedCreatedAt) { } (4). MapStruct映射器
@Mapper(componentModel = "spring", uses = DateFormatMapper.class) public interface UserMapper { UserMapper INSTANCE = Mappers.getMapper(UserMapper.class); UserDTO poToDto(UserPO po); @Mapping(target = "formattedCreatedAt", source = "createdAt") UserVO dtoToVo(UserDTO dto); } (5). 日期格式化工具
public class DateFormatMapper { public String formatDate(LocalDateTime dateTime) { return dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); } } (6). Service层实现
@Service @Transactional public class UserServiceImpl implements UserService { @Autowired private UserRepository userRepository; @Autowired private UserMapper userMapper; @Override public UserDTO createUser(CreateUserRequest request) { // 验证请求 validateRequest(request); // 创建PO UserPO userPO = new UserPO(); userPO.setUsername(request.username()); userPO.setEncryptedPassword(passwordEncoder.encode(request.password())); userPO.setCreatedAt(LocalDateTime.now()); // 持久化 UserPO savedPO = userRepository.save(userPO); // 转换为DTO return userMapper.poToDto(savedPO); } @Override public UserVO getUserById(Long id) { UserPO userPO = userRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException("User not found")); UserDTO userDTO = userMapper.poToDto(userPO); return userMapper.dtoToVo(userDTO); } private void validateRequest(CreateUserRequest request) { // 使用Spring Validation进行参数校验 // 示例代码省略 } } (7). Controller层实现
@RestController @RequestMapping("/api/users") @Validated public class UserController { @Autowired private UserService userService; @PostMapping @ResponseStatus(HttpStatus.CREATED) @Operation(summary = "创建用户") public UserDTO createUser(@RequestBody @Valid CreateUserRequest request) { return userService.createUser(request); } @GetMapping("/{id}") @Operation(summary = "根据ID获取用户") public UserVO getUser(@PathVariable Long id) { return userService.getUserById(id); } } (8). 自动生成的API文档示例
// http://localhost:8080/swagger-ui.html 六. 客户端请求
```http POST /api/users HTTP/1.1 Content-Type: application/json { "username": "john.doe", "password": "SecurePass123" } 七. 响应客户端:
HTTP/1.1 201 Created Content-Type: application/json { "username": "john.doe", "formattedCreatedAt": "2023-10-15T14:30:00" } 八.高级特性与最佳实践
(1). 全局异常处理
@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(EntityNotFoundException.class) @ResponseStatus(HttpStatus.NOT_FOUND) public ErrorResponse handleEntityNotFound(EntityNotFoundException ex) { return new ErrorResponse(HttpStatus.NOT_FOUND.value(), ex.getMessage()); } @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public ErrorResponse handleValidationExceptions(MethodArgumentNotValidException ex) { // 构建详细的验证错误信息 // 示例代码省略 } } 九 .分页与排序
(1) Controller层
@GetMapping public Page<UserVO> getUsers( @PageableDefault(size = 10, sort = "createdAt", direction = Sort.Direction.DESC) Pageable pageable) { Page<UserDTO> userDTOPage = userService.getUsers(pageable); return userDTOPage.map(userMapper::dtoToVo); } (2) Service层
@Override public Page<UserDTO> getUsers(Pageable pageable) { Page<UserPO> userPOPage = userRepository.findAll(pageable); return userPOPage.map(userMapper::poToDto); } 十.事务管理
@Service @Transactional public class OrderServiceImpl implements OrderService { @Autowired private OrderRepository orderRepository; @Autowired private InventoryService inventoryService; @Override public OrderDTO createOrder(CreateOrderRequest request) { // 检查库存 inventoryService.debitStock(request.getProductId(), request.getQuantity()); // 创建订单 OrderPO orderPO = new OrderPO(); // 设置订单属性 // ... OrderPO savedOrder = orderRepository.save(orderPO); return orderMapper.poToDto(savedOrder); } } 十一.集成测试示例
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) class UserControllerIntegrationTest { @Autowired private TestRestTemplate restTemplate; @Test void shouldCreateUserSuccessfully() { CreateUserRequest request = new CreateUserRequest("test.user", "Password123"); ResponseEntity<UserDTO> response = restTemplate.postForEntity( "/api/users", request, UserDTO.class); assertEquals(HttpStatus.CREATED, response.getStatusCode()); assertNotNull(response.getBody().id()); assertEquals("test.user", response.getBody().username()); } } 十二、总结与最佳实践
使用现代化工具链:
- 利用Lombok减少样板代码
- 使用MapStruct自动生成对象映射
- 借助Spring Validation简化参数校验
遵循分层职责:
- Controller层:处理HTTP请求、参数校验、返回适当的HTTP状态码
- Service层:执行业务逻辑、事务管理、权限校验
- Repository层:与数据库交互
- 各层之间通过明确的接口通信
安全与性能考虑:
- 永远不要直接暴露PO到外部
- 敏感数据(如密码)应始终加密存储
- 使用DTO控制数据传输量,避免过度获取数据
自动化测试:
- 编写单元测试验证各层功能
- 进行集成测试确保层间协作正常
- 使用测试切片(Test Slices)提高测试效率
持续改进:
- 定期进行代码审查,确保对象使用规范
- 根据项目需求调整分层策略
- 关注行业最新实践和技术发展
通过采用这些现代化技术和最佳实践,你可以构建出更加健壮、高效、易维护的Java企业级应用。希望这篇文章对你理解和应用Java分层开发中的各种对象概念有所帮助!
代码获取方式
https://pan.quark.cn/s/14fcf913bae6
关注我获取更多内容