以下是对 Spring Boot 项目目录结构及分层(包含 DAO 和 DTO)的简洁总结,重新整理后更清晰明了:
1. 典型 Spring Boot 项目目录结构
my-spring-boot-project/
├── src/
│ ├── main/
│ │ ├── java/com/example/myapp/
│ │ │ ├── Application.java # 主入口类
│ │ │ ├── controller/ # 控制器层(处理请求)
│ │ │ │ └── MyController.java
│ │ │ ├── service/ # 服务层(业务逻辑)
│ │ │ │ ├── MyService.java # 接口
│ │ │ │ └── impl/MyServiceImpl.java
│ │ │ ├── dao/ # 数据访问层(DAO)
│ │ │ │ └── MyDao.java
│ │ │ ├── entity/ # 实体类(数据库映射)
│ │ │ │ └── MyEntity.java
│ │ │ ├── dto/ # 数据传输对象
│ │ │ │ ├── MyRequestDto.java # 请求 DTO
│ │ │ │ └── MyResponseDto.java # 响应 DTO
│ │ │ ├── config/ # 配置类
│ │ │ └── util/ # 工具类
│ │ └── resources/
│ │ ├── application.properties # 配置文件
│ │ ├── static/ # 静态资源
│ │ └── templates/ # 模板文件
│ └── test/ # 测试代码和资源
├── pom.xml # Maven 构建文件
└── README.md # 项目说明
2. 各层作用及 DTO 的意义
-
controller/- 控制器层- 处理 HTTP 请求,返回响应。
- 使用
DTO(如MyRequestDto和MyResponseDto)接收和返回数据。
-
service/- 服务层- 处理业务逻辑,调用
DAO,负责DTO和Entity的转换。 - 通常包含接口和实现类。
- 处理业务逻辑,调用
-
dao/- 数据访问层- 与数据库交互,执行 CRUD 操作。
- 在 Spring Data JPA 中常用
repository/替代,但功能一致。
-
entity/- 实体层- 数据库表的映射类(如
@Entity),用于持久化。
- 数据库表的映射类(如
-
dto/- 数据传输对象- 用于层间数据传递,隔离
Entity,定制字段。 - 示例:
MyRequestDto(请求数据)、MyResponseDto(响应数据)。
- 用于层间数据传递,隔离
3. 数据流转
- 请求: 用户 →
Controller(接收MyRequestDto)→Service(转为MyEntity)→DAO(保存到数据库)。 - 响应:
DAO(返回MyEntity)→Service(转为MyResponseDto)→Controller(返回给用户)。
4. 关键点
DAOvsRepository:DAO是传统术语,Repository是 Spring Data 的抽象,作用相同。- 为什么用 DTO: 保护
Entity,灵活定制数据,避免直接暴露数据库结构。 - 转换:
Entity和DTO之间通常用手动映射或工具(如 MapStruct)转换。
这个结构适用于大多数 Spring Boot 项目,尤其是 REST API 类型。
curd demo
下面是一个基于上述 Spring Boot 项目结构的 CRUD(Create, Update, Read, Delete)示例,使用 Spring Data JPA 实现。我们以一个简单的“用户”(User)管理为例,展示各层的代码。
1. 项目目录结构
my-spring-boot-project/
├── src/
│ ├── main/
│ │ ├── java/com/example/myapp/
│ │ │ ├── Application.java
│ │ │ ├── controller/
│ │ │ │ └── UserController.java
│ │ │ ├── service/
│ │ │ │ ├── UserService.java
│ │ │ │ └── impl/UserServiceImpl.java
│ │ │ ├── dao/
│ │ │ │ └── UserDao.java
│ │ │ ├── entity/
│ │ │ │ └── User.java
│ │ │ ├── dto/
│ │ │ │ ├── UserRequestDto.java
│ │ │ │ └── UserResponseDto.java
│ │ └── resources/
│ │ └── application.properties
├── pom.xml
2. 代码实现
2.1 pom.xml
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-spring-boot-project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.3</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
2.2 Application.java
package com.example.myapp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
2.3 entity/User.java
package com.example.myapp.entity;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private int age;
// Constructors
public User() {}
public User(String name, int age) {
this.name = name;
this.age = age;
}
// Getters and Setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}
2.4 dto/UserRequestDto.java
package com.example.myapp.dto;
public class UserRequestDto {
private String name;
private int age;
// Getters and Setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}
2.5 dto/UserResponseDto.java
package com.example.myapp.dto;
public class UserResponseDto {
private Long id;
private String name;
private int age;
public UserResponseDto(Long id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
// Getters
public Long getId() { return id; }
public String getName() { return name; }
public int getAge() { return age; }
}
2.6 dao/UserDao.java
package com.example.myapp.dao;
import com.example.myapp.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserDao extends JpaRepository<User, Long> {
}
2.7 service/UserService.java
package com.example.myapp.service;
import com.example.myapp.dto.UserRequestDto;
import com.example.myapp.dto.UserResponseDto;
import java.util.List;
public interface UserService {
UserResponseDto createUser(UserRequestDto requestDto);
UserResponseDto getUser(Long id);
List<UserResponseDto> getAllUsers();
UserResponseDto updateUser(Long id, UserRequestDto requestDto);
void deleteUser(Long id);
}
2.8 service/impl/UserServiceImpl.java
package com.example.myapp.service.impl;
import com.example.myapp.dao.UserDao;
import com.example.myapp.dto.UserRequestDto;
import com.example.myapp.dto.UserResponseDto;
import com.example.myapp.entity.User;
import com.example.myapp.service.UserService;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class UserServiceImpl implements UserService {
private final UserDao userDao;
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
@Override
public UserResponseDto createUser(UserRequestDto requestDto) {
User user = new User(requestDto.getName(), requestDto.getAge());
user = userDao.save(user);
return new UserResponseDto(user.getId(), user.getName(), user.getAge());
}
@Override
public UserResponseDto getUser(Long id) {
User user = userDao.findById(id)
.orElseThrow(() -> new RuntimeException("User not found"));
return new UserResponseDto(user.getId(), user.getName(), user.getAge());
}
@Override
public List<UserResponseDto> getAllUsers() {
return userDao.findAll().stream()
.map(user -> new UserResponseDto(user.getId(), user.getName(), user.getAge()))
.collect(Collectors.toList());
}
@Override
public UserResponseDto updateUser(Long id, UserRequestDto requestDto) {
User user = userDao.findById(id)
.orElseThrow(() -> new RuntimeException("User not found"));
user.setName(requestDto.getName());
user.setAge(requestDto.getAge());
user = userDao.save(user);
return new UserResponseDto(user.getId(), user.getName(), user.getAge());
}
@Override
public void deleteUser(Long id) {
userDao.deleteById(id);
}
}
2.9 controller/UserController.java
package com.example.myapp.controller;
import com.example.myapp.dto.UserRequestDto;
import com.example.myapp.dto.UserResponseDto;
import com.example.myapp.service.UserService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping
public UserResponseDto createUser(@RequestBody UserRequestDto requestDto) {
return userService.createUser(requestDto);
}
@GetMapping("/{id}")
public UserResponseDto getUser(@PathVariable Long id) {
return userService.getUser(id);
}
@GetMapping
public List<UserResponseDto> getAllUsers() {
return userService.getAllUsers();
}
@PutMapping("/{id}")
public UserResponseDto updateUser(@PathVariable Long id, @RequestBody UserRequestDto requestDto) {
return userService.updateUser(id, requestDto);
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
}
}
2.10 resources/application.properties
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
server.port=8080
3. 使用说明
- 运行项目: 启动
Application.java,访问http://localhost:8080/h2-console查看 H2 数据库。 - 测试 API:
- 创建用户:
POST /api/users
请求:{"name": "Alice", "age": 25}
响应:{"id": 1, "name": "Alice", "age": 25} - 查询用户:
GET /api/users/1
响应:{"id": 1, "name": "Alice", "age": 25} - 查询所有用户:
GET /api/users
响应:[{"id": 1, "name": "Alice", "age": 25}] - 更新用户:
PUT /api/users/1
请求:{"name": "Alice Updated", "age": 26}
响应:{"id": 1, "name": "Alice Updated", "age": 26} - 删除用户:
DELETE /api/users/1
- 创建用户:
4. 总结
Entity:User表示数据库表结构。DTO:UserRequestDto和UserResponseDto用于请求和响应,避免直接暴露Entity。DAO:UserDao使用 Spring Data JPA 提供 CRUD 方法。Service:UserServiceImpl处理逻辑,转换Entity和DTO。Controller:UserController提供 REST API。
这个示例是完整的 CRUD 实现,基于 H2 内存数据库,适合学习和测试。
前端工程师、程序员

浙公网安备 33010602011771号