现代化 java 分层开发实施策略与最佳实践指南

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
可观测监控 Prometheus 版,每月50GB免费额度
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
简介: 现代化Java分层开发采用清晰的多层架构,包括Controller、Service、Repository和DTO等核心层次。文章详细介绍了标准Maven/Gradle项目结构,各层职责与实现规范:实体层使用JPA注解,DTO层隔离数据传输,Repository继承JpaRepository,Service层处理业务逻辑,Controller层处理HTTP请求。推荐使用Spring Boot、Lombok、MapStruct等技术栈,并强调了单元测试和集成测试的重要性。这种分层设计提高了代码的可维护性、可测试

现代化 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());
    }
}

十二、总结与最佳实践

  1. 使用现代化工具链

    • 利用Lombok减少样板代码
    • 使用MapStruct自动生成对象映射
    • 借助Spring Validation简化参数校验
  2. 遵循分层职责

    • Controller层:处理HTTP请求、参数校验、返回适当的HTTP状态码
    • Service层:执行业务逻辑、事务管理、权限校验
    • Repository层:与数据库交互
    • 各层之间通过明确的接口通信
  3. 安全与性能考虑

    • 永远不要直接暴露PO到外部
    • 敏感数据(如密码)应始终加密存储
    • 使用DTO控制数据传输量,避免过度获取数据
  4. 自动化测试

    • 编写单元测试验证各层功能
    • 进行集成测试确保层间协作正常
    • 使用测试切片(Test Slices)提高测试效率
  5. 持续改进

    • 定期进行代码审查,确保对象使用规范
    • 根据项目需求调整分层策略
    • 关注行业最新实践和技术发展

通过采用这些现代化技术和最佳实践,你可以构建出更加健壮、高效、易维护的Java企业级应用。希望这篇文章对你理解和应用Java分层开发中的各种对象概念有所帮助!



代码获取方式
https://pan.quark.cn/s/14fcf913bae6


关注我获取更多内容

相关文章
|
16天前
|
安全 Java API
Java 抽象类与接口在 Java17 + 开发中的现代应用实践解析
《Java抽象类与接口核心技术解析》 摘要:本文全面剖析Java抽象类与接口的核心概念与技术差异。抽象类通过模板设计实现代码复用,支持具体方法与状态管理;接口则定义行为规范,实现多态支持。文章详细对比了两者在实例化、方法实现、继承机制等方面的区别,并提供了模板方法模式(抽象类)和策略模式(接口)的典型应用示例。特别指出Java8+新特性为接口带来的灵活性提升,包括默认方法和静态方法。最后给出最佳实践建议:优先使用接口定义行为规范,通过抽象类实现代码复用,合理组合两者构建灵活架构。
32 2
|
18天前
|
Java
银行转账p图软件,对公转账截图生成器,java版开发银行模拟器【仅供学习参考】
这是一套简单的银行账户管理系统代码,包含`BankAccount`和`BankSystem`两个核心类。`BankAccount`负责单个账户的管理
|
18天前
|
Java API 微服务
Java 21 与 Spring Boot 3.2 微服务开发从入门到精通实操指南
《Java 21与Spring Boot 3.2微服务开发实践》摘要: 本文基于Java 21和Spring Boot 3.2最新特性,通过完整代码示例展示了微服务开发全流程。主要内容包括:1) 使用Spring Initializr初始化项目,集成Web、JPA、H2等组件;2) 配置虚拟线程支持高并发;3) 采用记录类优化DTO设计;4) 实现JPA Repository与Stream API数据访问;5) 服务层整合虚拟线程异步处理和结构化并发;6) 构建RESTful API并使用Springdoc生成文档。文中特别演示了虚拟线程配置(@Async)和StructuredTaskSco
69 0
|
2月前
|
算法 Java 调度
Java多线程基础
本文主要讲解多线程相关知识,分为两部分。第一部分涵盖多线程概念(并发与并行、进程与线程)、Java程序运行原理(JVM启动多线程特性)、实现多线程的两种方式(继承Thread类与实现Runnable接口)及其区别。第二部分涉及线程同步(同步锁的应用场景与代码示例)及线程间通信(wait()与notify()方法的使用)。通过多个Demo代码实例,深入浅出地解析多线程的核心知识点,帮助读者掌握其实现与应用技巧。
|
5月前
|
存储 监控 Java
【Java并发】【线程池】带你从0-1入门线程池
欢迎来到我的技术博客!我是一名热爱编程的开发者,梦想是编写高端CRUD应用。2025年我正在沉淀中,博客更新速度加快,期待与你一起成长。 线程池是一种复用线程资源的机制,通过预先创建一定数量的线程并管理其生命周期,避免频繁创建/销毁线程带来的性能开销。它解决了线程创建成本高、资源耗尽风险、响应速度慢和任务执行缺乏管理等问题。
294 60
【Java并发】【线程池】带你从0-1入门线程池
|
3月前
|
Java 中间件 调度
【源码】【Java并发】从InheritableThreadLocal和TTL源码的角度来看父子线程传递
本文涉及InheritableThreadLocal和TTL,从源码的角度,分别分析它们是怎么实现父子线程传递的。建议先了解ThreadLocal。
128 4
【源码】【Java并发】从InheritableThreadLocal和TTL源码的角度来看父子线程传递
|
2月前
|
Java
java 多线程异常处理
本文介绍了Java中ThreadGroup的异常处理机制,重点讲解UncaughtExceptionHandler的使用。通过示例代码展示了当线程的run()方法抛出未捕获异常时,JVM如何依次查找并调用线程的异常处理器、线程组的uncaughtException方法或默认异常处理器。文章还提供了具体代码和输出结果,帮助理解不同处理器的优先级与执行逻辑。
|
2月前
|
机器学习/深度学习 消息中间件 存储
【高薪程序员必看】万字长文拆解Java并发编程!(9-2):并发工具-线程池
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发编程中的强力并发工具-线程池,废话不多说让我们直接开始。
89 0
|
4月前
|
存储 网络协议 安全
Java网络编程,多线程,IO流综合小项目一一ChatBoxes
**项目介绍**:本项目实现了一个基于TCP协议的C/S架构控制台聊天室,支持局域网内多客户端同时聊天。用户需注册并登录,用户名唯一,密码格式为字母开头加纯数字。登录后可实时聊天,服务端负责验证用户信息并转发消息。 **项目亮点**: - **C/S架构**:客户端与服务端通过TCP连接通信。 - **多线程**:采用多线程处理多个客户端的并发请求,确保实时交互。 - **IO流**:使用BufferedReader和BufferedWriter进行数据传输,确保高效稳定的通信。 - **线程安全**:通过同步代码块和锁机制保证共享数据的安全性。
162 23