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

发布于:2025-06-15 ⋅ 阅读:(15) ⋅ 点赞:(0)

目录

环境搭建与项目创建

核心注解详解

依赖管理深入理解

自动配置原理详解

Web 开发详解

数据访问层详解

配置系统深入

AOP 面向切面编程

事务管理

数据校验

异常处理机制

日志系统

缓存机制

定时任务

事件机制

国际化支持

文件上传下载

Spring Security 安全


环境搭建与项目创建

系统要求

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

开发环境检查

# 检查 Java 版本
java -version
javac -version

# 检查 Maven 版本
mvn -version

# 检查环境变量
echo $JAVA_HOME
echo $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 CLI
spring init --dependencies=web,jpa,mysql my-project

# 使用 Maven archetype
mvn 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 配置:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!-- Spring Boot 父 POM -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.12</version>
        <relativePath/>
    </parent>

    <!-- 项目信息 -->
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <name>demo</name>
    <description>Spring Boot Demo Project</description>
    <packaging>jar</packaging>

    <!-- 属性配置 -->
    <properties>
        <java.version>8</java.version>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <!-- 依赖管理 -->
    <dependencies>
        <!-- Spring Boot Web Starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Spring Boot Data JPA Starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <!-- MySQL 驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!-- Spring Boot Validation -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

        <!-- Spring Boot Test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- 开发工具 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!-- 配置处理器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <!-- 构建配置 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.springframework.boot</groupId>
                            <artifactId>spring-boot-configuration-processor</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

核心注解详解

@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
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

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

Spring 核心注解详解

1. 依赖注入注解

@Autowired 详解:

@Service
public 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:

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

@Component 家族:

// 通用组件
@Component
public class CommonUtil {
    public String generateId() {
        return UUID.randomUUID().toString();
    }
}

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

// 持久层
@Repository
public class UserRepository {
    // 数据访问逻辑
}

// 控制层
@Controller
public class UserController {
    // 请求处理逻辑
}

// REST控制层
@RestController  // = @Controller + @ResponseBody
public class UserRestController {
    // REST API逻辑
}
3. 配置注解

@Configuration 详解:

@Configuration
public 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 家族:

@Configuration
public 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 Configure
org.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
<!-- 包含的主要依赖 -->
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
    </dependency>
</dependencies>
2. spring-boot-starter-data-jpa
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
    </dependency>
</dependencies>

版本管理最佳实践

1. 使用 Spring Boot BOM:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.7.12</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

2. 版本覆盖:

<properties>
    <!-- 覆盖 Spring Boot 管理的版本 -->
    <mysql.version>8.0.33</mysql.version>
    <jackson.version>2.15.2</jackson.version>
</properties>

自定义 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:

<dependency>
    <groupId>com.example</groupId>
    <artifactId>my-service-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>
# application.yml
myservice:
  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.properties
debug=true

2. 通过代码获取:

@RestController
public class AutoConfigReportController {
    
    @Autowired
    private ConditionEvaluationReport conditionEvaluationReport;
    
    @GetMapping("/autoconfig")
    public Map<String, Object> getAutoConfigReport() {
        Map<String, Object> report = new HashMap<>();
        
        // 匹配的配置
        Map<String, ConditionEvaluationReport.ConditionAndOutcomes> 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")
@Data
public 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<User> getUsers(@RequestParam(defaultValue = "0") int page,
                              @RequestParam(defaultValue = "10") int size) {
        return userService.findAll(page, size);
    }
    
    @GetMapping("/{id}")          // 获取单个用户
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        User user = userService.findById(id);
        return ResponseEntity.ok(user);
    }
    
    // POST - 创建资源
    @PostMapping
    public ResponseEntity<User> 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<User> 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<User> patchUser(@PathVariable Long id,
                                         @RequestBody Map<String, Object> updates) {
        User updatedUser = userService.partialUpdate(id, updates);
        return ResponseEntity.ok(updatedUser);
    }
    
    // DELETE - 删除资源
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> 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<User> searchUsers(
        @RequestParam String keyword,                    // 必需参数
        @RequestParam(defaultValue = "name") String sortBy,  // 默认值
        @RequestParam(required = false) String category,     // 可选参数
        @RequestParam List<String> 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<String> handleComplex(@Valid @RequestBody ComplexRequest request,
                                               BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResponseEntity.badRequest().body("参数错误");
        }
        return ResponseEntity.ok("处理成功");
    }
}

// 复杂请求对象
@Data
@Valid
public 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<ContactInfo> contacts;
    
    @Valid
    private Address address;
}
3. 响应处理详解
@RestController
public 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<User> 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<ApiResponse> 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<Resource> 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<StreamingResponseBody> 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
@AllArgsConstructor
public class ApiResponse<T> {
    private String status;
    private String message;
    private T data;
}

内容协商

@RestController
public 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<User> 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: 全局配置
@Configuration
public 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
@Configuration
public 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
@AllArgsConstructor
public 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<Order> orders = new ArrayList<>();
    
    // 多对多关系 - 用户的角色
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(
        name = "user_roles",
        joinColumns = @JoinColumn(name = "user_id"),
        inverseJoinColumns = @JoinColumn(name = "role_id")
    )
    private Set<Role> roles = new HashSet<>();
    
    // 一对一关系 - 用户档案
    @OneToOne(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private UserProfile profile;
    
    @Version
    private Long version; // 乐观锁
}

// 订单实体
@Entity
@Table(name = "orders")
@Data
@NoArgsConstructor
public 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<OrderItem> orderItems = new ArrayList<>();
}

// 订单项实体
@Entity
@Table(name = "order_items")
@Data
@NoArgsConstructor
public 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 详解
// 基础 Repository
public interface UserRepository extends JpaRepository<User, Long> {
    
    // 查询方法命名规则
    Optional<User> findByUsername(String username);
    Optional<User> findByEmail(String email);
    List<User> findByStatus(UserStatus status);
    List<User> findByCreatedAtBetween(LocalDateTime start, LocalDateTime end);
    List<User> findByUsernameContainingIgnoreCase(String username);
    List<User> findByRolesName(String roleName);
    
    // 排序和分页
    List<User> findByStatusOrderByCreatedAtDesc(UserStatus status);
    Page<User> findByStatus(UserStatus status, Pageable pageable);
    
    // @Query 注解 - JPQL
    @Query("SELECT u FROM User u WHERE u.email = ?1")
    Optional<User> findByEmailJPQL(String email);
    
    @Query("SELECT u FROM User u WHERE u.username LIKE %:username% AND u.status = :status")
    List<User> findByUsernameContainingAndStatus(@Param("username") String username, 
                                                 @Param("status") UserStatus status);
    
    // 原生SQL查询
    @Query(value = "SELECT * FROM users WHERE email = ?1", nativeQuery = true)
    Optional<User> 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<Object[]> 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<UserProjection> 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<User> 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
@AllArgsConstructor
public class UserSummary {
    private Long id;
    private String username;
    private String email;
    private Long orderCount;
}
3. 自定义Repository实现
// 自定义Repository接口
public interface UserRepositoryCustom {
    List<User> findUsersByCriteria(UserSearchCriteria criteria);
    Page<User> findUsersWithDynamicQuery(UserSearchCriteria criteria, Pageable pageable);
}

// 自定义Repository实现
@Repository
public class UserRepositoryCustomImpl implements UserRepositoryCustom {
    
    @PersistenceContext
    private EntityManager entityManager;
    
    @Override
    public List<User> findUsersByCriteria(UserSearchCriteria criteria) {
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        CriteriaQuery<User> query = cb.createQuery(User.class);
        Root<User> root = query.from(User.class);
        
        List<Predicate> 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<User> findUsersWithDynamicQuery(UserSearchCriteria criteria, Pageable pageable) {
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        
        // 查询数据
        CriteriaQuery<User> query = cb.createQuery(User.class);
        Root<User> root = query.from(User.class);
        
        List<Predicate> predicates = buildPredicates(cb, root, criteria);
        query.where(cb.and(predicates.toArray(new Predicate[0])));
        
        // 添加排序
        if (pageable.getSort().isSorted()) {
            List<javax.persistence.criteria.Order> 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<User> typedQuery = entityManager.createQuery(query);
        typedQuery.setFirstResult((int) pageable.getOffset());
        typedQuery.setMaxResults(pageable.getPageSize());
        
        List<User> users = typedQuery.getResultList();
        
        // 查询总数
        CriteriaQuery<Long> countQuery = cb.createQuery(Long.class);
        Root<User> 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<Predicate> buildPredicates(CriteriaBuilder cb, Root<User> root, UserSearchCriteria criteria) {
        List<Predicate> 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;
    }
}

// 搜索条件类
@Data
public class UserSearchCriteria {
    private String username;
    private String email;
    private UserStatus status;
    private LocalDateTime createdAfter;
    private LocalDateTime createdBefore;
}

// 完整的Repository接口
public interface UserRepository extends JpaRepository<User, Long>, UserRepositoryCustom {
    // JPA方法查询...
}

数据库连接配置

1. 多数据源配置
@Configuration
public 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
@EnableCaching
public class RedisConfig {
    
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        LettuceConnectionFactory factory = new LettuceConnectionFactory();
        factory.setHostName("localhost");
        factory.setPort(6379);
        factory.setDatabase(0);
        return factory;
    }
    
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        
        // 设置序列化器
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = 
            new Jackson2JsonRedisSerializer<>(Object.class);