当前位置: 首页 > news >正文

SpringBoot3.x入门到精通系列:1.4 项目结构与核心注解

SpringBoot 3.x 项目结构与核心注解

🏗️ 标准项目结构

SpringBoot遵循"约定优于配置"的原则,推荐使用标准的项目结构:

src/
├── main/
│   ├── java/                          # Java源代码
│   │   └── com/example/demo/
│   │       ├── DemoApplication.java   # 主启动类
│   │       ├── controller/            # 控制器层
│   │       ├── service/               # 业务逻辑层
│   │       ├── repository/            # 数据访问层
│   │       ├── model/                 # 数据模型
│   │       ├── dto/                   # 数据传输对象
│   │       ├── config/                # 配置类
│   │       └── util/                  # 工具类
│   └── resources/                     # 资源文件
│       ├── static/                    # 静态资源
│       ├── templates/                 # 模板文件
│       ├── application.properties     # 配置文件
│       └── application-{profile}.properties
└── test/                              # 测试代码└── java/└── com/example/demo/└── DemoApplicationTests.java

📦 分层架构详解

1. Controller层 (控制器层)

负责处理HTTP请求,调用Service层处理业务逻辑。

package com.example.demo.controller;import com.example.demo.dto.UserDTO;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;import java.util.List;@RestController
@RequestMapping("/api/users")
@CrossOrigin(origins = "*")  // 跨域配置
public class UserController {@Autowiredprivate UserService userService;@GetMappingpublic ResponseEntity<List<UserDTO>> getAllUsers() {List<UserDTO> users = userService.getAllUsers();return ResponseEntity.ok(users);}@GetMapping("/{id}")public ResponseEntity<UserDTO> getUserById(@PathVariable Long id) {UserDTO user = userService.getUserById(id);return ResponseEntity.ok(user);}@PostMappingpublic ResponseEntity<UserDTO> createUser(@RequestBody @Valid UserDTO userDTO) {UserDTO createdUser = userService.createUser(userDTO);return ResponseEntity.status(201).body(createdUser);}@PutMapping("/{id}")public ResponseEntity<UserDTO> updateUser(@PathVariable Long id, @RequestBody @Valid UserDTO userDTO) {UserDTO updatedUser = userService.updateUser(id, userDTO);return ResponseEntity.ok(updatedUser);}@DeleteMapping("/{id}")public ResponseEntity<Void> deleteUser(@PathVariable Long id) {userService.deleteUser(id);return ResponseEntity.noContent().build();}
}

2. Service层 (业务逻辑层)

处理业务逻辑,调用Repository层进行数据操作。

package com.example.demo.service;import com.example.demo.dto.UserDTO;
import com.example.demo.model.User;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.List;
import java.util.stream.Collectors;@Service
@Transactional
public class UserService {@Autowiredprivate UserRepository userRepository;public List<UserDTO> getAllUsers() {return userRepository.findAll().stream().map(this::convertToDTO).collect(Collectors.toList());}public UserDTO getUserById(Long id) {User user = userRepository.findById(id).orElseThrow(() -> new RuntimeException("用户不存在: " + id));return convertToDTO(user);}public UserDTO createUser(UserDTO userDTO) {User user = convertToEntity(userDTO);User savedUser = userRepository.save(user);return convertToDTO(savedUser);}public UserDTO updateUser(Long id, UserDTO userDTO) {User existingUser = userRepository.findById(id).orElseThrow(() -> new RuntimeException("用户不存在: " + id));existingUser.setName(userDTO.getName());existingUser.setEmail(userDTO.getEmail());existingUser.setAge(userDTO.getAge());User updatedUser = userRepository.save(existingUser);return convertToDTO(updatedUser);}public void deleteUser(Long id) {if (!userRepository.existsById(id)) {throw new RuntimeException("用户不存在: " + id);}userRepository.deleteById(id);}// DTO与Entity转换方法private UserDTO convertToDTO(User user) {return new UserDTO(user.getId(), user.getName(), user.getEmail(), user.getAge());}private User convertToEntity(UserDTO userDTO) {User user = new User();user.setName(userDTO.getName());user.setEmail(userDTO.getEmail());user.setAge(userDTO.getAge());return user;}
}

3. Repository层 (数据访问层)

负责数据持久化操作。

package com.example.demo.repository;import com.example.demo.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;import java.util.List;
import java.util.Optional;@Repository
public interface UserRepository extends JpaRepository<User, Long> {// 根据邮箱查找用户Optional<User> findByEmail(String email);// 根据姓名查找用户(忽略大小写)List<User> findByNameIgnoreCase(String name);// 根据年龄范围查找用户List<User> findByAgeBetween(Integer minAge, Integer maxAge);// 自定义查询@Query("SELECT u FROM User u WHERE u.age > :age")List<User> findUsersOlderThan(@Param("age") Integer age);// 原生SQL查询@Query(value = "SELECT * FROM users WHERE email LIKE %:domain%", nativeQuery = true)List<User> findUsersByEmailDomain(@Param("domain") String domain);
}

4. Model层 (数据模型)

定义数据实体。

package com.example.demo.model;import jakarta.persistence.*;
import jakarta.validation.constraints.*;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;import java.time.LocalDateTime;@Entity
@Table(name = "users")
public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(nullable = false, length = 100)@NotBlank(message = "姓名不能为空")@Size(min = 2, max = 100, message = "姓名长度必须在2-100个字符之间")private String name;@Column(nullable = false, unique = true, length = 255)@NotBlank(message = "邮箱不能为空")@Email(message = "邮箱格式不正确")private String email;@Column@Min(value = 0, message = "年龄不能小于0")@Max(value = 150, message = "年龄不能大于150")private Integer age;@CreationTimestamp@Column(name = "created_at", updatable = false)private LocalDateTime createdAt;@UpdateTimestamp@Column(name = "updated_at")private LocalDateTime updatedAt;// 构造函数public User() {}public User(String name, String email, Integer age) {this.name = name;this.email = email;this.age = age;}// Getter和Setter方法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 String getEmail() { return email; }public void setEmail(String email) { this.email = email; }public Integer getAge() { return age; }public void setAge(Integer age) { this.age = age; }public LocalDateTime getCreatedAt() { return createdAt; }public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }public LocalDateTime getUpdatedAt() { return updatedAt; }public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; }@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", email='" + email + '\'' +", age=" + age +", createdAt=" + createdAt +", updatedAt=" + updatedAt +'}';}
}

5. DTO层 (数据传输对象)

用于前后端数据传输。

package com.example.demo.dto;import jakarta.validation.constraints.*;/*** 用户数据传输对象* 使用Java 17的Record特性*/
public record UserDTO(Long id,@NotBlank(message = "姓名不能为空")@Size(min = 2, max = 100, message = "姓名长度必须在2-100个字符之间")String name,@NotBlank(message = "邮箱不能为空")@Email(message = "邮箱格式不正确")String email,@Min(value = 0, message = "年龄不能小于0")@Max(value = 150, message = "年龄不能大于150")Integer age
) {// Record自动生成构造函数、getter、equals、hashCode、toString方法/*** 创建用户DTO的静态工厂方法*/public static UserDTO of(String name, String email, Integer age) {return new UserDTO(null, name, email, age);}/*** 检查是否为成年人*/public boolean isAdult() {return age != null && age >= 18;}
}

🏷️ 核心注解详解

1. 启动类注解

@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}

@SpringBootApplication 是一个组合注解,等价于:

@SpringBootConfiguration  // 标识配置类
@EnableAutoConfiguration  // 启用自动配置
@ComponentScan           // 启用组件扫描

2. Web层注解

注解作用示例
@RestControllerREST控制器@RestController
@ControllerMVC控制器@Controller
@RequestMapping请求映射@RequestMapping("/api")
@GetMappingGET请求@GetMapping("/users")
@PostMappingPOST请求@PostMapping("/users")
@PutMappingPUT请求@PutMapping("/users/{id}")
@DeleteMappingDELETE请求@DeleteMapping("/users/{id}")
@PathVariable路径变量@PathVariable Long id
@RequestParam请求参数@RequestParam String name
@RequestBody请求体@RequestBody UserDTO user
@ResponseBody响应体@ResponseBody

3. 业务层注解

@Service
@Transactional
public class UserService {// 业务逻辑
}

4. 数据层注解

@Repository
public interface UserRepository extends JpaRepository<User, Long> {// 数据访问方法
}

5. 配置类注解

@Configuration
@EnableJpaRepositories
@EntityScan
public class DatabaseConfig {@Bean@Primarypublic DataSource dataSource() {// 数据源配置}
}

6. 依赖注入注解

@Component
public class UserService {@Autowiredprivate UserRepository userRepository;// 或使用构造函数注入(推荐)public UserService(UserRepository userRepository) {this.userRepository = userRepository;}
}

📋 最佳实践

1. 包命名规范

com.company.project.module.layer
例如:com.example.demo.user.controller

2. 类命名规范

  • Controller: UserController
  • Service: UserService
  • Repository: UserRepository
  • Model: User
  • DTO: UserDTO
  • Config: DatabaseConfig

3. 依赖注入推荐方式

// 推荐:构造函数注入
@Service
public class UserService {private final UserRepository userRepository;public UserService(UserRepository userRepository) {this.userRepository = userRepository;}
}// 不推荐:字段注入
@Service
public class UserService {@Autowiredprivate UserRepository userRepository;
}

🔗 下一篇

在下一篇文章中,我们将详细介绍SpringBoot的配置文件使用方法和最佳实践。


本文关键词: 项目结构, 分层架构, 核心注解, 最佳实践, MVC模式

http://www.dtcms.com/a/309699.html

相关文章:

  • 三十九、【扩展工具篇】Allpairspy 组合用例生成器:智能设计高效测试集
  • spring中自带的执行定时任务的注解是什么?
  • 铁皮矫平机是什么?
  • 掌握长尾关键词提升SEO
  • 4-verilog简单状态机
  • 使用mybatis生成器生成实体类mapper和查询参数文件,简单spring mvc 项目。使用log4j输出日志到控制台和文件中。使用配置文件注册Bean
  • 【U8+】删除部门的时候提示已经在总账(辅助总账)中使用,不可删除。
  • 从0到1学PHP(十三):PHP 安全编程:构建稳固的应用防线
  • (一)LoRA微调BERT:为何在单分类任务中表现优异,而在多分类任务中效果不佳?
  • 自动化测试准备工作:概念篇
  • Java HTTPS 请求失败排查与证书导入全过程
  • 从豆瓣小组到深度洞察:一个基于Python的舆情分析爬虫实践
  • 【05】VM二次开发——模块参数配置--带渲染/不带渲染(WinForm界面调用 模块参数配置)
  • JVM指针压缩的那些事
  • JVM学习日记(十三)Day13
  • C#线程同步(二)锁
  • 【工具变量大全】上市公司实证研究常用控制变量数据集(2001-2024年)
  • sqli-labs通关笔记-第26a关GET字符注入(多重关键字过滤绕过 手注法)
  • qt贝塞尔曲线演示工具
  • Product Hunt 每日热榜 | 2025-08-01
  • 5-EP4CE10F17C8-引脚配置
  • Fiddler中文版使用指南 提升开发流程的一站式抓包与调试体验
  • 大模型幻觉的本质:深度=逻辑层次,宽度=组合限制,深度为n的神经网络最多只能处理n层逻辑推理,宽度为w的网络无法区分超过w+1个复杂对象的组合
  • 搭建体育直播系统所需的核心数据接入
  • 深度解析:Nginx的卓越性能
  • C# 中生成随机数的常用方法
  • 消息顺序、消息重复问题
  • 在VScode里运行并调试C++程序
  • SpringMVC的拦截器
  • Mermaid流程图可视化系统:基于Spring Boot与Node.js的三层架构实现