> 技术文档 > Spring Boot 完整教程 - 从入门到精通(全面版)_springboot教程

Spring Boot 完整教程 - 从入门到精通(全面版)_springboot教程

目录

环境搭建与项目创建

核心注解详解

依赖管理深入理解

自动配置原理详解

Web 开发详解

数据访问层详解

配置系统深入

AOP 面向切面编程

事务管理

数据校验

异常处理机制

日志系统

缓存机制

定时任务

事件机制

国际化支持

文件上传下载

Spring Security 安全


环境搭建与项目创建

系统要求

组件 版本要求 Java JDK 8+ Spring Boot 2.7.x / 3.x Maven 3.6.3+ Gradle 6.8+

开发环境检查

# 检查 Java 版本java -versionjavac -version# 检查 Maven 版本mvn -version# 检查环境变量echo $JAVA_HOMEecho $MAVEN_HOME

创建项目的四种方式

方式一:Spring Initializr 网站
  1. 访问 https://start.spring.io/
  2. 选择项目配置
  3. 下载项目压缩包
方式二:IDE 集成

IntelliJ IDEA:

File -> New -> Project -> Spring Initializr

Eclipse (STS):

File -> New -> Other -> Spring Boot -> Spring Starter Project
方式三:命令行工具
# 使用 Spring Boot CLIspring init --dependencies=web,jpa,mysql my-project# 使用 Maven archetypemvn archetype:generate -DgroupId=com.example \\ -DartifactId=demo \\ -DarchetypeArtifactId=maven-archetype-quickstart \\ -DinteractiveMode=false
方式四:手动创建

完整的项目结构:

demo/├── src/│ ├── main/│ │ ├── java/│ │ │ └── com/│ │ │ └── example/│ │ │  └── demo/│ │ │  ├── DemoApplication.java│ │ │  ├── controller/│ │ │  ├── service/│ │ │  ├── repository/│ │ │  ├── entity/│ │ │  ├── dto/│ │ │  ├── config/│ │ │  └── util/│ │ └── resources/│ │ ├── static/│ │ ├── templates/│ │ ├── application.yml│ │ └── application-dev.yml│ └── test/│ └── java/│  └── com/│  └── example/│  └── demo/├── target/├── pom.xml└── README.md

详细的 pom.xml 配置:

 4.0.0   org.springframework.boot spring-boot-starter-parent 2.7.12    com.example demo 1.0.0-SNAPSHOT demo Spring Boot Demo Project jar   8 8 8 UTF-8      org.springframework.boot spring-boot-starter-web    org.springframework.boot spring-boot-starter-data-jpa    mysql mysql-connector-java runtime    org.springframework.boot spring-boot-starter-validation    org.springframework.boot spring-boot-starter-test test    org.springframework.boot spring-boot-devtools runtime true    org.springframework.boot spring-boot-configuration-processor true       org.springframework.boot spring-boot-maven-plugin     org.springframework.boot spring-boot-configuration-processor       

核心注解详解

@SpringBootApplication 深入理解

@SpringBootApplication 源码分析:

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@SpringBootConfiguration // 标识为配置类@EnableAutoConfiguration // 启用自动配置@ComponentScan // 组件扫描public @interface SpringBootApplication { // 排除特定的自动配置类 Class[] exclude() default {}; // 排除特定的自动配置类名 String[] excludeName() default {}; // 指定扫描的包 String[] scanBasePackages() default {}; // 指定扫描的类 Class[] scanBasePackageClasses() default {};}

等价写法:

// 使用 @SpringBootApplication@SpringBootApplicationpublic class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); }}// 等价于以下写法@SpringBootConfiguration@EnableAutoConfiguration@ComponentScanpublic class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); }}

Spring 核心注解详解

1. 依赖注入注解

@Autowired 详解:

@Servicepublic class UserService { // 1. 字段注入(不推荐) @Autowired private UserRepository userRepository; // 2. 构造器注入(推荐) private final UserRepository userRepository; @Autowired public UserService(UserRepository userRepository) { this.userRepository = userRepository; } // 3. Setter注入 private UserRepository userRepository; @Autowired public void setUserRepository(UserRepository userRepository) { this.userRepository = userRepository; } // 4. 方法参数注入 @Autowired public void init(UserRepository userRepository) { this.userRepository = userRepository; }}

@Resource vs @Autowired:

@Servicepublic class OrderService { // @Autowired 按类型注入,如果有多个同类型Bean,再按名称 @Autowired @Qualifier(\"orderRepositoryImpl\") // 指定具体实现 private OrderRepository orderRepository; // @Resource 按名称注入,JSR-250标准 @Resource(name = \"orderRepositoryImpl\") private OrderRepository orderRepository2;}
2. 组件注解

@Component 家族:

// 通用组件@Componentpublic class CommonUtil { public String generateId() { return UUID.randomUUID().toString(); }}// 服务层@Servicepublic class UserService { // 业务逻辑}// 持久层@Repositorypublic class UserRepository { // 数据访问逻辑}// 控制层@Controllerpublic class UserController { // 请求处理逻辑}// REST控制层@RestController // = @Controller + @ResponseBodypublic class UserRestController { // REST API逻辑}
3. 配置注解

@Configuration 详解:

@Configurationpublic class DatabaseConfig { @Bean @Primary // 主要的Bean,当有多个同类型Bean时优先选择 public DataSource primaryDataSource() { return DataSourceBuilder.create() .url(\"jdbc:mysql://localhost:3306/primary\") .username(\"root\") .password(\"123456\") .build(); } @Bean(\"secondaryDataSource\") public DataSource secondaryDataSource() { return DataSourceBuilder.create() .url(\"jdbc:mysql://localhost:3306/secondary\") .username(\"root\") .password(\"123456\") .build(); } @Bean @ConditionalOnProperty(name = \"app.cache.enabled\", havingValue = \"true\") public CacheManager cacheManager() { return new SimpleCacheManager(); }}
4. 条件注解

@Conditional 家族:

@Configurationpublic class ConditionalConfig { // 当类存在时 @Bean @ConditionalOnClass(RedisTemplate.class) public RedisService redisService() { return new RedisService(); } // 当Bean不存在时 @Bean @ConditionalOnMissingBean(DataSource.class) public DataSource defaultDataSource() { return new EmbeddedDatabaseBuilder().build(); } // 当属性匹配时 @Bean @ConditionalOnProperty( prefix = \"app.email\", name = \"enabled\", havingValue = \"true\", matchIfMissing = false ) public EmailService emailService() { return new EmailService(); } // 自定义条件 @Bean @ConditionalOnLinux public LinuxService linuxService() { return new LinuxService(); }}// 自定义条件注解@Target({ElementType.TYPE, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Conditional(LinuxCondition.class)public @interface ConditionalOnLinux {}public class LinuxCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { return System.getProperty(\"os.name\").toLowerCase().contains(\"linux\"); }}

依赖管理深入理解

Spring Boot Starter 原理

Starter 的结构:

spring-boot-starter-web/├── META-INF/│ └── spring.factories└── pom.xml (依赖声明)

spring.factories 文件:

# Auto Configureorg.springframework.boot.autoconfigure.EnableAutoConfiguration=\\org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\\org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\\org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration

常用 Starter 详解

1. spring-boot-starter-web
  org.springframework.boot spring-boot-starter   org.springframework.boot spring-boot-starter-tomcat   org.springframework spring-web   org.springframework spring-webmvc 
2. spring-boot-starter-data-jpa
  org.springframework.boot spring-boot-starter-aop   org.springframework.boot spring-boot-starter-jdbc   org.springframework.data spring-data-jpa   org.hibernate hibernate-core 

版本管理最佳实践

1. 使用 Spring Boot BOM:

   org.springframework.boot spring-boot-dependencies 2.7.12 pom import  

2. 版本覆盖:

  8.0.33 2.15.2

自定义 Starter

1. 创建 autoconfigure 模块:

// 自动配置类@Configuration@ConditionalOnClass(MyService.class)@ConditionalOnProperty(prefix = \"myservice\", name = \"enabled\", havingValue = \"true\")@EnableConfigurationProperties(MyServiceProperties.class)public class MyServiceAutoConfiguration { @Bean @ConditionalOnMissingBean public MyService myService(MyServiceProperties properties) { return new MyService(properties); }}// 配置属性类@ConfigurationProperties(prefix = \"myservice\")public class MyServiceProperties { private boolean enabled = true; private String prefix = \"默认前缀\"; private int timeout = 30; // getter/setter...}// 服务类public class MyService { private final MyServiceProperties properties; public MyService(MyServiceProperties properties) { this.properties = properties; } public String processMessage(String message) { return properties.getPrefix() + \": \" + message; }}

2. spring.factories 配置:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\\com.example.myservice.autoconfigure.MyServiceAutoConfiguration

3. 使用自定义 Starter:

 com.example my-service-spring-boot-starter 1.0.0
# application.ymlmyservice: enabled: true prefix: \"自定义前缀\" timeout: 60

自动配置原理详解

自动配置的工作流程

1. 启动时的处理流程:

@SpringBootApplication ↓@EnableAutoConfiguration ↓AutoConfigurationImportSelector ↓读取 META-INF/spring.factories ↓加载所有 AutoConfiguration 类 ↓根据 @Conditional 注解过滤 ↓创建符合条件的 Bean

深入理解 @EnableAutoConfiguration

@EnableAutoConfiguration 源码:

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@AutoConfigurationPackage@Import(AutoConfigurationImportSelector.class)public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = \"spring.boot.enableautoconfiguration\"; Class[] exclude() default {}; String[] excludeName() default {};}

条件注解深入分析

所有条件注解及其作用:

public class ConditionalExamples { // 当指定的类在classpath中存在时 @ConditionalOnClass(RedisTemplate.class) public RedisConfig redisConfig() { return new RedisConfig(); } // 当指定的类在classpath中不存在时 @ConditionalOnMissingClass(\"com.example.SomeClass\") public DefaultConfig defaultConfig() { return new DefaultConfig(); } // 当指定的Bean存在时 @ConditionalOnBean(DataSource.class) public JdbcTemplate jdbcTemplate(DataSource dataSource) { return new JdbcTemplate(dataSource); } // 当指定的Bean不存在时 @ConditionalOnMissingBean(DataSource.class) public DataSource defaultDataSource() { return new EmbeddedDatabaseBuilder().build(); } // 当指定的属性存在且匹配时 @ConditionalOnProperty( prefix = \"spring.datasource\", name = \"url\", matchIfMissing = false ) public DataSource configuredDataSource() { return null; } // 当运行在Web环境中 @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) public WebConfig webConfig() { return new WebConfig(); } // 当不是Web环境时 @ConditionalOnNotWebApplication public ConsoleConfig consoleConfig() { return new ConsoleConfig(); } // 当指定的资源存在时 @ConditionalOnResource(resources = \"classpath:config/app.properties\") public ExternalConfig externalConfig() { return new ExternalConfig(); } // 当表达式为true时 @ConditionalOnExpression(\"${app.feature.enabled:false}\") public FeatureConfig featureConfig() { return new FeatureConfig(); } // 当Java版本匹配时 @ConditionalOnJava(JavaVersion.EIGHT) public Java8Config java8Config() { return new Java8Config(); } // 当指定的JNDI存在时 @ConditionalOnJndi(\"java:comp/env/jdbc/MyDataSource\") public JndiConfig jndiConfig() { return new JndiConfig(); }}

查看自动配置报告

1. 启用调试模式:

# application.propertiesdebug=true

2. 通过代码获取:

@RestControllerpublic class AutoConfigReportController { @Autowired private ConditionEvaluationReport conditionEvaluationReport; @GetMapping(\"/autoconfig\") public Map getAutoConfigReport() { Map report = new HashMap(); // 匹配的配置 Map conditions = conditionEvaluationReport.getConditionAndOutcomesBySource();  report.put(\"matched\", conditions.entrySet().stream() .filter(entry -> entry.getValue().isFullMatch()) .collect(Collectors.toMap( Map.Entry::getKey, entry -> entry.getValue().getOutcomes() )));  // 未匹配的配置 report.put(\"unmatched\", conditions.entrySet().stream() .filter(entry -> !entry.getValue().isFullMatch()) .collect(Collectors.toMap( Map.Entry::getKey, entry -> entry.getValue().getOutcomes() )));  return report; }}

自定义自动配置

完整的自动配置示例:

// 1. 配置属性类@ConfigurationProperties(prefix = \"app.email\")@Datapublic class EmailProperties { private boolean enabled = false; private String host = \"localhost\"; private int port = 25; private String username; private String password; private boolean auth = false; private boolean starttls = false;}// 2. 服务类public class EmailService { private final EmailProperties properties; public EmailService(EmailProperties properties) { this.properties = properties; } public void sendEmail(String to, String subject, String content) { // 发送邮件的逻辑 System.out.println(\"发送邮件到: \" + to); System.out.println(\"主题: \" + subject); System.out.println(\"内容: \" + content); }}// 3. 自动配置类@Configuration@ConditionalOnClass(EmailService.class)@ConditionalOnProperty(prefix = \"app.email\", name = \"enabled\", havingValue = \"true\")@EnableConfigurationProperties(EmailProperties.class)public class EmailAutoConfiguration { @Bean @ConditionalOnMissingBean public EmailService emailService(EmailProperties properties) { return new EmailService(properties); } @Bean @ConditionalOnBean(EmailService.class) public EmailController emailController(EmailService emailService) { return new EmailController(emailService); }}// 4. 控制器@RestController@RequestMapping(\"/api/email\")public class EmailController { private final EmailService emailService; public EmailController(EmailService emailService) { this.emailService = emailService; } @PostMapping(\"/send\") public String sendEmail(@RequestParam String to, @RequestParam String subject, @RequestParam String content) { emailService.sendEmail(to, subject, content); return \"邮件发送成功\"; }}

Web 开发详解

Spring MVC 架构深入

Spring MVC 执行流程:

请求 → DispatcherServlet → HandlerMapping → Handler → HandlerAdapter → Controller → ModelAndView → ViewResolver → View → 响应

RESTful API 设计详解

1. HTTP 方法语义
@RestController@RequestMapping(\"/api/users\")public class UserController { // GET - 获取资源 @GetMapping  // 获取所有用户 public List getUsers(@RequestParam(defaultValue = \"0\") int page, @RequestParam(defaultValue = \"10\") int size) { return userService.findAll(page, size); } @GetMapping(\"/{id}\") // 获取单个用户 public ResponseEntity getUser(@PathVariable Long id) { User user = userService.findById(id); return ResponseEntity.ok(user); } // POST - 创建资源 @PostMapping public ResponseEntity createUser(@Valid @RequestBody User user) { User savedUser = userService.save(user); URI location = URI.create(\"/api/users/\" + savedUser.getId()); return ResponseEntity.created(location).body(savedUser); } // PUT - 更新整个资源 @PutMapping(\"/{id}\") public ResponseEntity updateUser(@PathVariable Long id,  @Valid @RequestBody User user) { user.setId(id); User updatedUser = userService.save(user); return ResponseEntity.ok(updatedUser); } // PATCH - 部分更新资源 @PatchMapping(\"/{id}\") public ResponseEntity patchUser(@PathVariable Long id,  @RequestBody Map updates) { User updatedUser = userService.partialUpdate(id, updates); return ResponseEntity.ok(updatedUser); } // DELETE - 删除资源 @DeleteMapping(\"/{id}\") public ResponseEntity deleteUser(@PathVariable Long id) { userService.deleteById(id); return ResponseEntity.noContent().build(); }}
2. 请求参数处理详解
@RestController@RequestMapping(\"/api/advanced\")public class AdvancedController { // 路径变量 @GetMapping(\"/users/{id}/orders/{orderId}\") public Order getOrder(@PathVariable(\"id\") Long userId, @PathVariable(\"orderId\") Long orderId) { return orderService.findByUserAndId(userId, orderId); } // 请求参数 @GetMapping(\"/search\") public List searchUsers( @RequestParam String keyword,  // 必需参数 @RequestParam(defaultValue = \"name\") String sortBy, // 默认值 @RequestParam(required = false) String category, // 可选参数 @RequestParam List tags) {  // 列表参数 return userService.search(keyword, sortBy, category, tags); } // 请求头 @GetMapping(\"/profile\") public User getProfile(@RequestHeader(\"Authorization\") String token, @RequestHeader(value = \"Accept-Language\", defaultValue = \"zh-CN\") String lang) { return userService.findByToken(token); } // Cookie @GetMapping(\"/preferences\") public UserPreferences getPreferences(@CookieValue(\"sessionId\") String sessionId) { return userService.findPreferences(sessionId); } // 矩阵变量 @GetMapping(\"/matrix/{id}\") public String matrixVar(@PathVariable String id, @MatrixVariable String name, @MatrixVariable int age) { return \"ID: \" + id + \", Name: \" + name + \", Age: \" + age; } // 访问: /matrix/123;name=john;age=25 // 请求体绑定 @PostMapping(\"/complex\") public ResponseEntity handleComplex(@Valid @RequestBody ComplexRequest request, BindingResult bindingResult) { if (bindingResult.hasErrors()) { return ResponseEntity.badRequest().body(\"参数错误\"); } return ResponseEntity.ok(\"处理成功\"); }}// 复杂请求对象@Data@Validpublic class ComplexRequest { @NotBlank(message = \"名称不能为空\") private String name; @NotNull(message = \"年龄不能为空\") @Min(value = 0, message = \"年龄不能小于0\") @Max(value = 150, message = \"年龄不能大于150\") private Integer age; @Email(message = \"邮箱格式不正确\") private String email; @Valid private List contacts; @Valid private Address address;}
3. 响应处理详解
@RestControllerpublic class ResponseController { // 基本响应 @GetMapping(\"/basic\") public String basicResponse() { return \"Hello World\"; } // JSON响应 @GetMapping(\"/json\") public User jsonResponse() { return new User(1L, \"张三\", \"zhang@example.com\"); } // 响应实体 - 完全控制HTTP响应 @GetMapping(\"/entity\") public ResponseEntity entityResponse() { User user = userService.findById(1L); return ResponseEntity.ok() .header(\"Custom-Header\", \"custom-value\") .lastModified(Instant.now()) .eTag(\"\\\"user-1\\\"\") .body(user); } // 不同状态码响应 @PostMapping(\"/status\") public ResponseEntity statusResponse(@RequestBody User user) { try { User savedUser = userService.save(user); ApiResponse response = new ApiResponse(\"success\", \"用户创建成功\", savedUser); return ResponseEntity.status(HttpStatus.CREATED).body(response); } catch (Exception e) { ApiResponse response = new ApiResponse(\"error\", e.getMessage(), null); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response); } } // 文件下载响应 @GetMapping(\"/download/{filename}\") public ResponseEntity downloadFile(@PathVariable String filename) { Resource resource = fileService.loadFileAsResource(filename); return ResponseEntity.ok() .contentType(MediaType.APPLICATION_OCTET_STREAM) .header(HttpHeaders.CONTENT_DISPOSITION, \"attachment; filename=\\\"\" + resource.getFilename() + \"\\\"\") .body(resource); } // 流式响应 @GetMapping(value = \"/stream\", produces = MediaType.TEXT_PLAIN_VALUE) public ResponseEntity streamResponse() { StreamingResponseBody stream = outputStream -> { for (int i = 0; i < 1000; i++) { outputStream.write((\"数据行 \" + i + \"\\n\").getBytes()); outputStream.flush(); Thread.sleep(10); // 模拟延迟 } }; return ResponseEntity.ok() .contentType(MediaType.TEXT_PLAIN) .body(stream); }}// 统一API响应格式@Data@AllArgsConstructorpublic class ApiResponse { private String status; private String message; private T data;}

内容协商

@RestControllerpublic class ContentNegotiationController { // 根据Accept头返回不同格式 @GetMapping(value = \"/data\", produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE }) public User getData() { return new User(1L, \"张三\", \"zhang@example.com\"); } // 根据请求参数返回不同格式 @GetMapping(\"/data\") public ResponseEntity getDataWithParam(@RequestParam(defaultValue = \"json\") String format) { User user = new User(1L, \"张三\", \"zhang@example.com\"); if (\"xml\".equals(format)) { return ResponseEntity.ok()  .contentType(MediaType.APPLICATION_XML)  .body(user); } else { return ResponseEntity.ok()  .contentType(MediaType.APPLICATION_JSON)  .body(user); } }}

跨域处理(CORS)

// 方式1: 注解方式@RestController@CrossOrigin(origins = \"http://localhost:3000\") // 允许特定源public class CorsController { @CrossOrigin(origins = \"*\", maxAge = 3600) // 方法级别配置 @GetMapping(\"/api/data\") public String getData() { return \"跨域数据\"; }}// 方式2: 全局配置@Configurationpublic class CorsConfig { @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); // 允许的源 configuration.setAllowedOriginPatterns(Arrays.asList(\"*\")); // 允许的HTTP方法 configuration.setAllowedMethods(Arrays.asList(\"GET\", \"POST\", \"PUT\", \"DELETE\", \"OPTIONS\")); // 允许的头部 configuration.setAllowedHeaders(Arrays.asList(\"*\")); // 允许携带凭证 configuration.setAllowCredentials(true); // 预检请求缓存时间 configuration.setMaxAge(3600L); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration(\"/**\", configuration); return source; }}// 方式3: WebMvcConfigurer@Configurationpublic class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(\"/api/**\") .allowedOrigins(\"http://localhost:3000\", \"https://example.com\") .allowedMethods(\"GET\", \"POST\", \"PUT\", \"DELETE\") .allowedHeaders(\"*\") .allowCredentials(true) .maxAge(3600); }}

数据访问层详解

JPA 深入理解

1. 实体关系映射
// 用户实体@Entity@Table(name = \"users\", indexes = { @Index(name = \"idx_email\", columnList = \"email\"), @Index(name = \"idx_username\", columnList = \"username\")})@Data@NoArgsConstructor@AllArgsConstructorpublic class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false, unique = true, length = 50) private String username; @Column(nullable = false, unique = true, length = 100) private String email; @Column(nullable = false) private String password; @Enumerated(EnumType.STRING) @Column(nullable = false) private UserStatus status = UserStatus.ACTIVE; @CreationTimestamp @Column(name = \"created_at\", nullable = false, updatable = false) private LocalDateTime createdAt; @UpdateTimestamp @Column(name = \"updated_at\", nullable = false) private LocalDateTime updatedAt; // 一对多关系 - 用户的订单 @OneToMany(mappedBy = \"user\", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private List orders = new ArrayList(); // 多对多关系 - 用户的角色 @ManyToMany(fetch = FetchType.LAZY) @JoinTable( name = \"user_roles\", joinColumns = @JoinColumn(name = \"user_id\"), inverseJoinColumns = @JoinColumn(name = \"role_id\") ) private Set roles = new HashSet(); // 一对一关系 - 用户档案 @OneToOne(mappedBy = \"user\", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private UserProfile profile; @Version private Long version; // 乐观锁}// 订单实体@Entity@Table(name = \"orders\")@Data@NoArgsConstructorpublic class Order { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false, unique = true) private String orderNumber; @Column(nullable = false, precision = 10, scale = 2) private BigDecimal totalAmount; @Enumerated(EnumType.STRING) private OrderStatus status = OrderStatus.PENDING; @CreationTimestamp private LocalDateTime createdAt; // 多对一关系 - 订单属于用户 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = \"user_id\", nullable = false) private User user; // 一对多关系 - 订单项 @OneToMany(mappedBy = \"order\", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private List orderItems = new ArrayList();}// 订单项实体@Entity@Table(name = \"order_items\")@Data@NoArgsConstructorpublic class OrderItem { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false) private String productName; @Column(nullable = false) private Integer quantity; @Column(nullable = false, precision = 10, scale = 2) private BigDecimal price; // 多对一关系 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = \"order_id\", nullable = false) private Order order;}// 枚举类型public enum UserStatus { ACTIVE, INACTIVE, SUSPENDED}public enum OrderStatus { PENDING, PAID, SHIPPED, DELIVERED, CANCELLED}
2. Repository 详解
// 基础 Repositorypublic interface UserRepository extends JpaRepository { // 查询方法命名规则 Optional findByUsername(String username); Optional findByEmail(String email); List findByStatus(UserStatus status); List findByCreatedAtBetween(LocalDateTime start, LocalDateTime end); List findByUsernameContainingIgnoreCase(String username); List findByRolesName(String roleName); // 排序和分页 List findByStatusOrderByCreatedAtDesc(UserStatus status); Page findByStatus(UserStatus status, Pageable pageable); // @Query 注解 - JPQL @Query(\"SELECT u FROM User u WHERE u.email = ?1\") Optional findByEmailJPQL(String email); @Query(\"SELECT u FROM User u WHERE u.username LIKE %:username% AND u.status = :status\") List findByUsernameContainingAndStatus(@Param(\"username\") String username, @Param(\"status\") UserStatus status); // 原生SQL查询 @Query(value = \"SELECT * FROM users WHERE email = ?1\", nativeQuery = true) Optional findByEmailNative(String email); @Query(value = \"SELECT u.*, COUNT(o.id) as order_count \" +  \"FROM users u LEFT JOIN orders o ON u.id = o.user_id \" +  \"GROUP BY u.id ORDER BY order_count DESC\",  nativeQuery = true) List findUsersWithOrderCount(); // 更新查询 @Modifying @Query(\"UPDATE User u SET u.status = :status WHERE u.id = :id\") int updateUserStatus(@Param(\"id\") Long id, @Param(\"status\") UserStatus status); @Modifying @Query(\"DELETE FROM User u WHERE u.status = :status AND u.createdAt < :date\") int deleteInactiveUsers(@Param(\"status\") UserStatus status, @Param(\"date\") LocalDateTime date); // 投影查询 @Query(\"SELECT u.id as id, u.username as username, u.email as email FROM User u\") List findAllProjected(); // 动态查询支持 @Query(\"SELECT u FROM User u WHERE \" +  \"(:username IS NULL OR u.username LIKE %:username%) AND \" +  \"(:email IS NULL OR u.email = :email) AND \" +  \"(:status IS NULL OR u.status = :status)\") Page findUsersDynamic(@Param(\"username\") String username, @Param(\"email\") String email, @Param(\"status\") UserStatus status, Pageable pageable);}// 投影接口public interface UserProjection { Long getId(); String getUsername(); String getEmail();}// DTO投影类@Data@AllArgsConstructorpublic class UserSummary { private Long id; private String username; private String email; private Long orderCount;}
3. 自定义Repository实现
// 自定义Repository接口public interface UserRepositoryCustom { List findUsersByCriteria(UserSearchCriteria criteria); Page findUsersWithDynamicQuery(UserSearchCriteria criteria, Pageable pageable);}// 自定义Repository实现@Repositorypublic class UserRepositoryCustomImpl implements UserRepositoryCustom { @PersistenceContext private EntityManager entityManager; @Override public List findUsersByCriteria(UserSearchCriteria criteria) { CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery query = cb.createQuery(User.class); Root root = query.from(User.class); List predicates = new ArrayList(); // 动态添加查询条件 if (criteria.getUsername() != null) { predicates.add(cb.like(cb.lower(root.get(\"username\")), \"%\" + criteria.getUsername().toLowerCase() + \"%\")); } if (criteria.getEmail() != null) { predicates.add(cb.equal(root.get(\"email\"), criteria.getEmail())); } if (criteria.getStatus() != null) { predicates.add(cb.equal(root.get(\"status\"), criteria.getStatus())); } if (criteria.getCreatedAfter() != null) { predicates.add(cb.greaterThanOrEqualTo(root.get(\"createdAt\"), criteria.getCreatedAfter())); } if (criteria.getCreatedBefore() != null) { predicates.add(cb.lessThanOrEqualTo(root.get(\"createdAt\"), criteria.getCreatedBefore())); } query.where(cb.and(predicates.toArray(new Predicate[0]))); query.orderBy(cb.desc(root.get(\"createdAt\"))); return entityManager.createQuery(query).getResultList(); } @Override public Page findUsersWithDynamicQuery(UserSearchCriteria criteria, Pageable pageable) { CriteriaBuilder cb = entityManager.getCriteriaBuilder(); // 查询数据 CriteriaQuery query = cb.createQuery(User.class); Root root = query.from(User.class); List predicates = buildPredicates(cb, root, criteria); query.where(cb.and(predicates.toArray(new Predicate[0]))); // 添加排序 if (pageable.getSort().isSorted()) { List orders = new ArrayList(); pageable.getSort().forEach(order -> { if (order.isAscending()) {  orders.add(cb.asc(root.get(order.getProperty()))); } else {  orders.add(cb.desc(root.get(order.getProperty()))); } }); query.orderBy(orders); } TypedQuery typedQuery = entityManager.createQuery(query); typedQuery.setFirstResult((int) pageable.getOffset()); typedQuery.setMaxResults(pageable.getPageSize()); List users = typedQuery.getResultList(); // 查询总数 CriteriaQuery countQuery = cb.createQuery(Long.class); Root countRoot = countQuery.from(User.class); countQuery.select(cb.count(countRoot)); countQuery.where(cb.and(buildPredicates(cb, countRoot, criteria).toArray(new Predicate[0]))); Long total = entityManager.createQuery(countQuery).getSingleResult(); return new PageImpl(users, pageable, total); } private List buildPredicates(CriteriaBuilder cb, Root root, UserSearchCriteria criteria) { List predicates = new ArrayList(); if (criteria.getUsername() != null) { predicates.add(cb.like(cb.lower(root.get(\"username\")), \"%\" + criteria.getUsername().toLowerCase() + \"%\")); } if (criteria.getEmail() != null) { predicates.add(cb.equal(root.get(\"email\"), criteria.getEmail())); } if (criteria.getStatus() != null) { predicates.add(cb.equal(root.get(\"status\"), criteria.getStatus())); } return predicates; }}// 搜索条件类@Datapublic class UserSearchCriteria { private String username; private String email; private UserStatus status; private LocalDateTime createdAfter; private LocalDateTime createdBefore;}// 完整的Repository接口public interface UserRepository extends JpaRepository, UserRepositoryCustom { // JPA方法查询...}

数据库连接配置

1. 多数据源配置
@Configurationpublic class DataSourceConfig { // 主数据源 @Primary @Bean @ConfigurationProperties(\"spring.datasource.primary\") public DataSourceProperties primaryDataSourceProperties() { return new DataSourceProperties(); } @Primary @Bean public DataSource primaryDataSource() { return primaryDataSourceProperties() .initializeDataSourceBuilder() .type(HikariDataSource.class) .build(); } // 从数据源 @Bean @ConfigurationProperties(\"spring.datasource.secondary\") public DataSourceProperties secondaryDataSourceProperties() { return new DataSourceProperties(); } @Bean public DataSource secondaryDataSource() { return secondaryDataSourceProperties() .initializeDataSourceBuilder() .type(HikariDataSource.class) .build(); } // 主数据源的JPA配置 @Primary @Bean public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory( @Qualifier(\"primaryDataSource\") DataSource dataSource) { LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setDataSource(dataSource); factory.setPackagesToScan(\"com.example.demo.entity.primary\"); factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); Properties jpaProperties = new Properties(); jpaProperties.setProperty(\"hibernate.dialect\", \"org.hibernate.dialect.MySQL8Dialect\"); jpaProperties.setProperty(\"hibernate.hbm2ddl.auto\", \"update\"); jpaProperties.setProperty(\"hibernate.show_sql\", \"true\"); factory.setJpaProperties(jpaProperties); return factory; } // 从数据源的JPA配置 @Bean public LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactory( @Qualifier(\"secondaryDataSource\") DataSource dataSource) { LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setDataSource(dataSource); factory.setPackagesToScan(\"com.example.demo.entity.secondary\"); factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); Properties jpaProperties = new Properties(); jpaProperties.setProperty(\"hibernate.dialect\", \"org.hibernate.dialect.MySQL8Dialect\"); jpaProperties.setProperty(\"hibernate.hbm2ddl.auto\", \"update\"); jpaProperties.setProperty(\"hibernate.show_sql\", \"false\"); factory.setJpaProperties(jpaProperties); return factory; } // 主数据源事务管理器 @Primary @Bean public PlatformTransactionManager primaryTransactionManager( @Qualifier(\"primaryEntityManagerFactory\") EntityManagerFactory factory) { return new JpaTransactionManager(factory); } // 从数据源事务管理器 @Bean public PlatformTransactionManager secondaryTransactionManager( @Qualifier(\"secondaryEntityManagerFactory\") EntityManagerFactory factory) { return new JpaTransactionManager(factory); }}// 配置文件spring: datasource: primary: url: jdbc:mysql://localhost:3306/primary_db username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver secondary: url: jdbc:mysql://localhost:3306/secondary_db username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver
2. Redis 集成详解
// Redis配置@Configuration@EnableCachingpublic class RedisConfig { @Bean public RedisConnectionFactory redisConnectionFactory() { LettuceConnectionFactory factory = new LettuceConnectionFactory(); factory.setHostName(\"localhost\"); factory.setPort(6379); factory.setDatabase(0); return factory; } @Bean public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate template = new RedisTemplate(); template.setConnectionFactory(connectionFactory); // 设置序列化器 Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); objectMapper.enableDefaultTyping(ObjectMapper.De