spring-boot-development

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Spring Boot Development Skill

Spring Boot开发技能

This skill provides comprehensive guidance for building modern Spring Boot applications using auto-configuration, dependency injection, REST APIs, Spring Data, Spring Security, and enterprise Java patterns based on official Spring Boot documentation.
本技能基于官方Spring Boot文档,提供了使用自动配置、依赖注入、REST API、Spring Data、Spring Security及企业级Java模式构建现代Spring Boot应用的全面指导。

When to Use This Skill

适用场景

Use this skill when:
  • Building enterprise REST APIs and microservices
  • Creating web applications with Spring MVC
  • Developing data-driven applications with JPA and databases
  • Implementing authentication and authorization with Spring Security
  • Building production-ready applications with actuator and monitoring
  • Creating scalable backend services with Spring Boot
  • Migrating from traditional Spring to Spring Boot
  • Developing cloud-native applications
  • Building event-driven systems with messaging
  • Creating batch processing applications
在以下场景中使用本技能:
  • 构建企业级REST API和微服务
  • 使用Spring MVC创建Web应用
  • 基于JPA和数据库开发数据驱动型应用
  • 利用Spring Security实现认证与授权
  • 构建带有Actuator监控的生产就绪型应用
  • 开发可扩展的Spring Boot后端服务
  • 从传统Spring框架迁移到Spring Boot
  • 开发云原生应用
  • 构建基于消息的事件驱动系统
  • 创建批处理应用

Core Concepts

核心概念

Auto-Configuration

自动配置

Spring Boot automatically configures your application based on the dependencies you have added to the project. This reduces boilerplate configuration significantly.
How Auto-Configuration Works:
java
@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}
The
@SpringBootApplication
annotation is a combination of:
  • @Configuration
    : Tags the class as a source of bean definitions
  • @EnableAutoConfiguration
    : Enables Spring Boot's auto-configuration mechanism
  • @ComponentScan
    : Enables component scanning in the current package and sub-packages
Conditional Auto-Configuration:
java
@Configuration
@ConditionalOnClass(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.url")
public class DataSourceAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }
}
Customizing Auto-Configuration:
java
// Exclude specific auto-configurations
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class MyApplication {
    // ...
}

// Or in application.properties
// spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
Spring Boot会根据项目中添加的依赖自动配置应用,大幅减少样板配置。
自动配置的工作原理:
java
@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}
@SpringBootApplication
注解是以下三个注解的组合:
  • @Configuration
    : 将类标记为Bean定义的来源
  • @EnableAutoConfiguration
    : 启用Spring Boot的自动配置机制
  • @ComponentScan
    : 启用当前包及子包的组件扫描
条件化自动配置:
java
@Configuration
@ConditionalOnClass(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.url")
public class DataSourceAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }
}
自定义自动配置:
java
// 排除特定自动配置类
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class MyApplication {
    // ...
}

// 或在application.properties中配置
// spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

Dependency Injection

依赖注入

Spring's IoC (Inversion of Control) container manages object creation and dependency injection.
Constructor Injection (Recommended):
java
@Service
public class UserService {

    private final UserRepository userRepository;
    private final EmailService emailService;

    // Constructor injection - recommended approach
    public UserService(UserRepository userRepository, EmailService emailService) {
        this.userRepository = userRepository;
        this.emailService = emailService;
    }

    public User createUser(User user) {
        User saved = userRepository.save(user);
        emailService.sendWelcomeEmail(saved);
        return saved;
    }
}
Field Injection (Not Recommended):
java
@Service
public class UserService {

    @Autowired  // Avoid field injection
    private UserRepository userRepository;

    // Difficult to test and creates tight coupling
}
Setter Injection (Optional Dependencies):
java
@Service
public class UserService {

    private UserRepository userRepository;
    private EmailService emailService;

    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Autowired(required = false)
    public void setEmailService(EmailService emailService) {
        this.emailService = emailService;
    }
}
Component Stereotypes:
java
@Component  // Generic component
public class MyComponent { }

@Service    // Business logic layer
public class MyService { }

@Repository // Data access layer
public class MyRepository { }

@Controller // Presentation layer (web)
public class MyController { }

@RestController // REST API controller
public class MyRestController { }
Spring的IoC(控制反转)容器负责对象创建和依赖注入。
构造函数注入(推荐):
java
@Service
public class UserService {

    private final UserRepository userRepository;
    private final EmailService emailService;

    // 构造函数注入 - 推荐方式
    public UserService(UserRepository userRepository, EmailService emailService) {
        this.userRepository = userRepository;
        this.emailService = emailService;
    }

    public User createUser(User user) {
        User saved = userRepository.save(user);
        emailService.sendWelcomeEmail(saved);
        return saved;
    }
}
字段注入(不推荐):
java
@Service
public class UserService {

    @Autowired  // 避免使用字段注入
    private UserRepository userRepository;

    // 难以测试且会产生紧耦合
}
Setter注入(可选依赖):
java
@Service
public class UserService {

    private UserRepository userRepository;
    private EmailService emailService;

    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Autowired(required = false)
    public void setEmailService(EmailService emailService) {
        this.emailService = emailService;
    }
}
组件 stereotype 注解:
java
@Component  // 通用组件
public class MyComponent { }

@Service    // 业务逻辑层组件
public class MyService { }

@Repository // 数据访问层组件
public class MyRepository { }

@Controller // 表示层(Web)组件
public class MyController { }

@RestController // REST API控制器
public class MyRestController { }

Spring Web (REST APIs)

Spring Web(REST API)

Build RESTful web services with Spring MVC annotations.
Basic REST Controller:
java
@RestController
@RequestMapping("/api/users")
public class UserController {

    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping
    public List<User> getAllUsers() {
        return userService.findAll();
    }

    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        return userService.findById(id)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }

    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody @Valid User user) {
        User created = userService.save(user);
        URI location = ServletUriComponentsBuilder
            .fromCurrentRequest()
            .path("/{id}")
            .buildAndExpand(created.getId())
            .toUri();
        return ResponseEntity.created(location).body(created);
    }

    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id,
                                          @RequestBody @Valid User user) {
        return userService.update(id, user)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        if (userService.delete(id)) {
            return ResponseEntity.noContent().build();
        }
        return ResponseEntity.notFound().build();
    }
}
Request Mapping Variations:
java
@RestController
@RequestMapping("/api/products")
public class ProductController {

    // Query parameters
    @GetMapping("/search")
    public List<Product> search(@RequestParam String name,
                               @RequestParam(required = false) String category) {
        return productService.search(name, category);
    }

    // Multiple path variables
    @GetMapping("/categories/{categoryId}/products/{productId}")
    public Product getProductInCategory(@PathVariable Long categoryId,
                                       @PathVariable Long productId) {
        return productService.findInCategory(categoryId, productId);
    }

    // Request headers
    @GetMapping("/{id}")
    public Product getProduct(@PathVariable Long id,
                             @RequestHeader("Accept-Language") String language) {
        return productService.find(id, language);
    }

    // Matrix variables
    @GetMapping("/{id}")
    public Product getProductWithMatrix(@PathVariable Long id,
                                       @MatrixVariable Map<String, String> filters) {
        return productService.findWithFilters(id, filters);
    }
}
Response Handling:
java
@RestController
@RequestMapping("/api/orders")
public class OrderController {

    // Return different status codes
    @PostMapping
    public ResponseEntity<Order> createOrder(@RequestBody Order order) {
        Order created = orderService.create(order);
        return ResponseEntity.status(HttpStatus.CREATED).body(created);
    }

    // Custom headers
    @GetMapping("/{id}")
    public ResponseEntity<Order> getOrder(@PathVariable Long id) {
        Order order = orderService.findById(id);
        return ResponseEntity.ok()
            .header("X-Order-Version", order.getVersion().toString())
            .body(order);
    }

    // No content response
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteOrder(@PathVariable Long id) {
        orderService.delete(id);
        return ResponseEntity.noContent().build();
    }
}
使用Spring MVC注解构建RESTful Web服务。
基础REST控制器:
java
@RestController
@RequestMapping("/api/users")
public class UserController {

    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping
    public List<User> getAllUsers() {
        return userService.findAll();
    }

    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        return userService.findById(id)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }

    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody @Valid User user) {
        User created = userService.save(user);
        URI location = ServletUriComponentsBuilder
            .fromCurrentRequest()
            .path("/{id}")
            .buildAndExpand(created.getId())
            .toUri();
        return ResponseEntity.created(location).body(created);
    }

    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id,
                                          @RequestBody @Valid User user) {
        return userService.update(id, user)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        if (userService.delete(id)) {
            return ResponseEntity.noContent().build();
        }
        return ResponseEntity.notFound().build();
    }
}
请求映射变体:
java
@RestController
@RequestMapping("/api/products")
public class ProductController {

    // 查询参数
    @GetMapping("/search")
    public List<Product> search(@RequestParam String name,
                               @RequestParam(required = false) String category) {
        return productService.search(name, category);
    }

    // 多个路径变量
    @GetMapping("/categories/{categoryId}/products/{productId}")
    public Product getProductInCategory(@PathVariable Long categoryId,
                                       @PathVariable Long productId) {
        return productService.findInCategory(categoryId, productId);
    }

    // 请求头
    @GetMapping("/{id}")
    public Product getProduct(@PathVariable Long id,
                             @RequestHeader("Accept-Language") String language) {
        return productService.find(id, language);
    }

    // 矩阵变量
    @GetMapping("/{id}")
    public Product getProductWithMatrix(@PathVariable Long id,
                                       @MatrixVariable Map<String, String> filters) {
        return productService.findWithFilters(id, filters);
    }
}
响应处理:
java
@RestController
@RequestMapping("/api/orders")
public class OrderController {

    // 返回不同状态码
    @PostMapping
    public ResponseEntity<Order> createOrder(@RequestBody Order order) {
        Order created = orderService.create(order);
        return ResponseEntity.status(HttpStatus.CREATED).body(created);
    }

    // 自定义响应头
    @GetMapping("/{id}")
    public ResponseEntity<Order> getOrder(@PathVariable Long id) {
        Order order = orderService.findById(id);
        return ResponseEntity.ok()
            .header("X-Order-Version", order.getVersion().toString())
            .body(order);
    }

    // 无内容响应
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteOrder(@PathVariable Long id) {
        orderService.delete(id);
        return ResponseEntity.noContent().build();
    }
}

Spring Data JPA

Spring Data JPA

Spring Data JPA provides repository abstractions for database access.
Entity Definition:
java
@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, unique = true)
    private String email;

    @Column(nullable = false)
    private String name;

    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;

    @Column(name = "updated_at")
    private LocalDateTime updatedAt;

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Order> orders = new ArrayList<>();

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "department_id")
    private Department department;

    @PrePersist
    protected void onCreate() {
        createdAt = LocalDateTime.now();
        updatedAt = LocalDateTime.now();
    }

    @PreUpdate
    protected void onUpdate() {
        updatedAt = LocalDateTime.now();
    }

    // Getters and setters
}
Repository Interface:
java
@Repository
public interface UserRepository extends JpaRepository<User, Long> {

    // Query method - Spring Data generates implementation
    Optional<User> findByEmail(String email);

    List<User> findByNameContaining(String name);

    List<User> findByDepartmentId(Long departmentId);

    // Custom JPQL query
    @Query("SELECT u FROM User u WHERE u.email = ?1")
    Optional<User> findByEmailQuery(String email);

    // Named parameters
    @Query("SELECT u FROM User u WHERE u.name LIKE %:name% AND u.department.id = :deptId")
    List<User> searchByNameAndDepartment(@Param("name") String name,
                                        @Param("deptId") Long deptId);

    // Native SQL query
    @Query(value = "SELECT * FROM users WHERE email = ?1", nativeQuery = true)
    Optional<User> findByEmailNative(String email);

    // Modifying query
    @Modifying
    @Query("UPDATE User u SET u.name = :name WHERE u.id = :id")
    int updateUserName(@Param("id") Long id, @Param("name") String name);

    // Pagination and sorting
    Page<User> findByDepartmentId(Long departmentId, Pageable pageable);

    List<User> findByNameContaining(String name, Sort sort);
}
Repository Usage:
java
@Service
public class UserService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public Optional<User> findById(Long id) {
        return userRepository.findById(id);
    }

    public User save(User user) {
        return userRepository.save(user);
    }

    public List<User> findAll() {
        return userRepository.findAll();
    }

    public Page<User> findAll(int page, int size) {
        Pageable pageable = PageRequest.of(page, size, Sort.by("name"));
        return userRepository.findAll(pageable);
    }

    public boolean delete(Long id) {
        if (userRepository.existsById(id)) {
            userRepository.deleteById(id);
            return true;
        }
        return false;
    }
}
Relationships:
java
// One-to-Many
@Entity
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;

    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<OrderItem> items = new ArrayList<>();
}

// Many-to-Many
@Entity
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToMany
    @JoinTable(
        name = "student_course",
        joinColumns = @JoinColumn(name = "student_id"),
        inverseJoinColumns = @JoinColumn(name = "course_id")
    )
    private Set<Course> courses = new HashSet<>();
}
Spring Data JPA为数据库访问提供了仓库抽象。
实体定义:
java
@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, unique = true)
    private String email;

    @Column(nullable = false)
    private String name;

    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;

    @Column(name = "updated_at")
    private LocalDateTime updatedAt;

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Order> orders = new ArrayList<>();

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "department_id")
    private Department department;

    @PrePersist
    protected void onCreate() {
        createdAt = LocalDateTime.now();
        updatedAt = LocalDateTime.now();
    }

    @PreUpdate
    protected void onUpdate() {
        updatedAt = LocalDateTime.now();
    }

    // Getter和Setter方法
}
仓库接口:
java
@Repository
public interface UserRepository extends JpaRepository<User, Long> {

    // 查询方法 - Spring Data自动生成实现
    Optional<User> findByEmail(String email);

    List<User> findByNameContaining(String name);

    List<User> findByDepartmentId(Long departmentId);

    // 自定义JPQL查询
    @Query("SELECT u FROM User u WHERE u.email = ?1")
    Optional<User> findByEmailQuery(String email);

    // 命名参数
    @Query("SELECT u FROM User u WHERE u.name LIKE %:name% AND u.department.id = :deptId")
    List<User> searchByNameAndDepartment(@Param("name") String name,
                                        @Param("deptId") Long deptId);

    // 原生SQL查询
    @Query(value = "SELECT * FROM users WHERE email = ?1", nativeQuery = true)
    Optional<User> findByEmailNative(String email);

    // 修改型查询
    @Modifying
    @Query("UPDATE User u SET u.name = :name WHERE u.id = :id")
    int updateUserName(@Param("id") Long id, @Param("name") String name);

    // 分页和排序
    Page<User> findByDepartmentId(Long departmentId, Pageable pageable);

    List<User> findByNameContaining(String name, Sort sort);
}
仓库使用:
java
@Service
public class UserService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public Optional<User> findById(Long id) {
        return userRepository.findById(id);
    }

    public User save(User user) {
        return userRepository.save(user);
    }

    public List<User> findAll() {
        return userRepository.findAll();
    }

    public Page<User> findAll(int page, int size) {
        Pageable pageable = PageRequest.of(page, size, Sort.by("name"));
        return userRepository.findAll(pageable);
    }

    public boolean delete(Long id) {
        if (userRepository.existsById(id)) {
            userRepository.deleteById(id);
            return true;
        }
        return false;
    }
}
关联关系:
java
// 一对多
@Entity
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;

    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<OrderItem> items = new ArrayList<>();
}

// 多对多
@Entity
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToMany
    @JoinTable(
        name = "student_course",
        joinColumns = @JoinColumn(name = "student_id"),
        inverseJoinColumns = @JoinColumn(name = "course_id")
    )
    private Set<Course> courses = new HashSet<>();
}

Configuration

配置

Spring Boot uses
application.properties
or
application.yml
for configuration.
Application Properties:
properties
undefined
Spring Boot使用
application.properties
application.yml
进行配置。
Application Properties配置:
properties
undefined

Server configuration

服务器配置

server.port=8080 server.servlet.context-path=/api
server.port=8080 server.servlet.context-path=/api

Database configuration

数据库配置

spring.datasource.url=jdbc:postgresql://localhost:5432/mydb spring.datasource.username=user spring.datasource.password=password spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb spring.datasource.username=user spring.datasource.password=password spring.datasource.driver-class-name=org.postgresql.Driver

JPA configuration

JPA配置

spring.jpa.hibernate.ddl-auto=validate spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=validate spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect

Logging

日志配置

logging.level.root=INFO logging.level.com.example=DEBUG logging.level.org.springframework.web=DEBUG logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} - %msg%n
logging.level.root=INFO logging.level.com.example=DEBUG logging.level.org.springframework.web=DEBUG logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} - %msg%n

Custom properties

自定义属性

app.name=My Application app.version=1.0.0

**Application YAML:**
```yaml
server:
  port: 8080
  servlet:
    context-path: /api

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/mydb
    username: user
    password: password
    driver-class-name: org.postgresql.Driver

  jpa:
    hibernate:
      ddl-auto: validate
    show-sql: true
    properties:
      hibernate:
        format_sql: true
        dialect: org.hibernate.dialect.PostgreSQLDialect

logging:
  level:
    root: INFO
    com.example: DEBUG
    org.springframework.web: DEBUG

app:
  name: My Application
  version: 1.0.0
Configuration Properties Class:
java
@Configuration
@ConfigurationProperties(prefix = "app")
public class AppConfig {

    private String name;
    private String version;
    private Security security = new Security();

    public static class Security {
        private int tokenExpiration = 3600;
        private String secretKey;

        // Getters and setters
    }

    // Getters and setters
}

// Usage
@Service
public class MyService {

    private final AppConfig appConfig;

    public MyService(AppConfig appConfig) {
        this.appConfig = appConfig;
    }

    public void printConfig() {
        System.out.println("App: " + appConfig.getName());
        System.out.println("Version: " + appConfig.getVersion());
    }
}
Environment-Specific Configuration:
properties
undefined
app.name=My Application app.version=1.0.0

**Application YAML配置:**
```yaml
server:
  port: 8080
  servlet:
    context-path: /api

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/mydb
    username: user
    password: password
    driver-class-name: org.postgresql.Driver

  jpa:
    hibernate:
      ddl-auto: validate
    show-sql: true
    properties:
      hibernate:
        format_sql: true
        dialect: org.hibernate.dialect.PostgreSQLDialect

logging:
  level:
    root: INFO
    com.example: DEBUG
    org.springframework.web: DEBUG

app:
  name: My Application
  version: 1.0.0
配置属性类:
java
@Configuration
@ConfigurationProperties(prefix = "app")
public class AppConfig {

    private String name;
    private String version;
    private Security security = new Security();

    public static class Security {
        private int tokenExpiration = 3600;
        private String secretKey;

        // Getter和Setter方法
    }

    // Getter和Setter方法
}

// 使用示例
@Service
public class MyService {

    private final AppConfig appConfig;

    public MyService(AppConfig appConfig) {
        this.appConfig = appConfig;
    }

    public void printConfig() {
        System.out.println("应用名称: " + appConfig.getName());
        System.out.println("版本号: " + appConfig.getVersion());
    }
}
环境特定配置:
properties
undefined

application.properties (default)

application.properties(默认配置)

spring.profiles.active=dev
spring.profiles.active=dev

application-dev.properties

application-dev.properties(开发环境)

spring.datasource.url=jdbc:postgresql://localhost:5432/mydb_dev logging.level.root=DEBUG
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb_dev logging.level.root=DEBUG

application-prod.properties

application-prod.properties(生产环境)

spring.datasource.url=jdbc:postgresql://prod-server:5432/mydb_prod logging.level.root=WARN

**Profile-Specific Beans:**
```java
@Configuration
public class DatabaseConfig {

    @Bean
    @Profile("dev")
    public DataSource devDataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .build();
    }

    @Bean
    @Profile("prod")
    public DataSource prodDataSource() {
        return DataSourceBuilder.create().build();
    }
}
spring.datasource.url=jdbc:postgresql://prod-server:5432/mydb_prod logging.level.root=WARN

**环境特定Bean:**
```java
@Configuration
public class DatabaseConfig {

    @Bean
    @Profile("dev")
    public DataSource devDataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .build();
    }

    @Bean
    @Profile("prod")
    public DataSource prodDataSource() {
        return DataSourceBuilder.create().build();
    }
}

Spring Security

Spring Security

Implement authentication and authorization in your application.
Basic Security Configuration:
java
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/public/**").permitAll()
                .requestMatchers("/api/admin/**").hasRole("ADMIN")
                .requestMatchers("/api/users/**").hasAnyRole("USER", "ADMIN")
                .anyRequest().authenticated()
            )
            .httpBasic();

        return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
In-Memory Authentication:
java
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {
        UserDetails user = User.builder()
            .username("user")
            .password(passwordEncoder.encode("password"))
            .roles("USER")
            .build();

        UserDetails admin = User.builder()
            .username("admin")
            .password(passwordEncoder.encode("admin"))
            .roles("ADMIN", "USER")
            .build();

        return new InMemoryUserDetailsManager(user, admin);
    }
}
Database Authentication:
java
@Service
public class CustomUserDetailsService implements UserDetailsService {

    private final UserRepository userRepository;

    public CustomUserDetailsService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByEmail(username)
            .orElseThrow(() -> new UsernameNotFoundException("User not found: " + username));

        return org.springframework.security.core.userdetails.User.builder()
            .username(user.getEmail())
            .password(user.getPassword())
            .roles(user.getRoles().toArray(new String[0]))
            .build();
    }
}

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    private final CustomUserDetailsService userDetailsService;

    public SecurityConfig(CustomUserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Bean
    public DaoAuthenticationProvider authenticationProvider(PasswordEncoder passwordEncoder) {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setUserDetailsService(userDetailsService);
        provider.setPasswordEncoder(passwordEncoder);
        return provider;
    }
}
JWT Authentication:
java
@Component
public class JwtTokenProvider {

    @Value("${app.security.jwt.secret}")
    private String jwtSecret;

    @Value("${app.security.jwt.expiration}")
    private int jwtExpiration;

    public String generateToken(Authentication authentication) {
        UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal();

        Date now = new Date();
        Date expiryDate = new Date(now.getTime() + jwtExpiration);

        return Jwts.builder()
            .setSubject(Long.toString(userPrincipal.getId()))
            .setIssuedAt(now)
            .setExpiration(expiryDate)
            .signWith(SignatureAlgorithm.HS512, jwtSecret)
            .compact();
    }

    public Long getUserIdFromJWT(String token) {
        Claims claims = Jwts.parser()
            .setSigningKey(jwtSecret)
            .parseClaimsJws(token)
            .getBody();

        return Long.parseLong(claims.getSubject());
    }

    public boolean validateToken(String authToken) {
        try {
            Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken);
            return true;
        } catch (SignatureException | MalformedJwtException | ExpiredJwtException |
                 UnsupportedJwtException | IllegalArgumentException ex) {
            return false;
        }
    }
}

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JwtTokenProvider tokenProvider;
    private final CustomUserDetailsService customUserDetailsService;

    public JwtAuthenticationFilter(JwtTokenProvider tokenProvider,
                                  CustomUserDetailsService customUserDetailsService) {
        this.tokenProvider = tokenProvider;
        this.customUserDetailsService = customUserDetailsService;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                   HttpServletResponse response,
                                   FilterChain filterChain) throws ServletException, IOException {
        try {
            String jwt = getJwtFromRequest(request);

            if (jwt != null && tokenProvider.validateToken(jwt)) {
                Long userId = tokenProvider.getUserIdFromJWT(jwt);

                UserDetails userDetails = customUserDetailsService.loadUserById(userId);
                UsernamePasswordAuthenticationToken authentication =
                    new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities()
                    );

                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        } catch (Exception ex) {
            logger.error("Could not set user authentication", ex);
        }

        filterChain.doFilter(request, response);
    }

    private String getJwtFromRequest(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }
}
在应用中实现认证与授权机制。
基础安全配置:
java
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/public/**").permitAll()
                .requestMatchers("/api/admin/**").hasRole("ADMIN")
                .requestMatchers("/api/users/**").hasAnyRole("USER", "ADMIN")
                .anyRequest().authenticated()
            )
            .httpBasic();

        return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
内存中的认证:
java
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {
        UserDetails user = User.builder()
            .username("user")
            .password(passwordEncoder.encode("password"))
            .roles("USER")
            .build();

        UserDetails admin = User.builder()
            .username("admin")
            .password(passwordEncoder.encode("admin"))
            .roles("ADMIN", "USER")
            .build();

        return new InMemoryUserDetailsManager(user, admin);
    }
}
基于数据库的认证:
java
@Service
public class CustomUserDetailsService implements UserDetailsService {

    private final UserRepository userRepository;

    public CustomUserDetailsService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByEmail(username)
            .orElseThrow(() -> new UsernameNotFoundException("未找到用户: " + username));

        return org.springframework.security.core.userdetails.User.builder()
            .username(user.getEmail())
            .password(user.getPassword())
            .roles(user.getRoles().toArray(new String[0]))
            .build();
    }
}

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    private final CustomUserDetailsService userDetailsService;

    public SecurityConfig(CustomUserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Bean
    public DaoAuthenticationProvider authenticationProvider(PasswordEncoder passwordEncoder) {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setUserDetailsService(userDetailsService);
        provider.setPasswordEncoder(passwordEncoder);
        return provider;
    }
}
JWT认证:
java
@Component
public class JwtTokenProvider {

    @Value("${app.security.jwt.secret}")
    private String jwtSecret;

    @Value("${app.security.jwt.expiration}")
    private int jwtExpiration;

    public String generateToken(Authentication authentication) {
        UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal();

        Date now = new Date();
        Date expiryDate = new Date(now.getTime() + jwtExpiration);

        return Jwts.builder()
            .setSubject(Long.toString(userPrincipal.getId()))
            .setIssuedAt(now)
            .setExpiration(expiryDate)
            .signWith(SignatureAlgorithm.HS512, jwtSecret)
            .compact();
    }

    public Long getUserIdFromJWT(String token) {
        Claims claims = Jwts.parser()
            .setSigningKey(jwtSecret)
            .parseClaimsJws(token)
            .getBody();

        return Long.parseLong(claims.getSubject());
    }

    public boolean validateToken(String authToken) {
        try {
            Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken);
            return true;
        } catch (SignatureException | MalformedJwtException | ExpiredJwtException |
                 UnsupportedJwtException | IllegalArgumentException ex) {
            return false;
        }
    }
}

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JwtTokenProvider tokenProvider;
    private final CustomUserDetailsService customUserDetailsService;

    public JwtAuthenticationFilter(JwtTokenProvider tokenProvider,
                                  CustomUserDetailsService customUserDetailsService) {
        this.tokenProvider = tokenProvider;
        this.customUserDetailsService = customUserDetailsService;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                   HttpServletResponse response,
                                   FilterChain filterChain) throws ServletException, IOException {
        try {
            String jwt = getJwtFromRequest(request);

            if (jwt != null && tokenProvider.validateToken(jwt)) {
                Long userId = tokenProvider.getUserIdFromJWT(jwt);

                UserDetails userDetails = customUserDetailsService.loadUserById(userId);
                UsernamePasswordAuthenticationToken authentication =
                    new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities()
                    );

                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        } catch (Exception ex) {
            logger.error("无法设置用户认证信息", ex);
        }

        filterChain.doFilter(request, response);
    }

    private String getJwtFromRequest(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }
}

API Reference

API参考

Common Annotations

常用注解

Core Spring Annotations:
  • @SpringBootApplication
    : Main application class
  • @Component
    : Generic component
  • @Service
    : Service layer component
  • @Repository
    : Data access layer component
  • @Configuration
    : Configuration class
  • @Bean
    : Bean definition method
  • @Autowired
    : Dependency injection
  • @Value
    : Inject property values
  • @Profile
    : Conditional beans based on profiles
Web Annotations:
  • @RestController
    : REST API controller
  • @Controller
    : MVC controller
  • @RequestMapping
    : Map HTTP requests
  • @GetMapping
    : Map GET requests
  • @PostMapping
    : Map POST requests
  • @PutMapping
    : Map PUT requests
  • @DeleteMapping
    : Map DELETE requests
  • @PatchMapping
    : Map PATCH requests
  • @PathVariable
    : Extract path variables
  • @RequestParam
    : Extract query parameters
  • @RequestBody
    : Extract request body
  • @RequestHeader
    : Extract request headers
  • @ResponseStatus
    : Set response status
Data Annotations:
  • @Entity
    : JPA entity
  • @Table
    : Table mapping
  • @Id
    : Primary key
  • @GeneratedValue
    : Auto-generated values
  • @Column
    : Column mapping
  • @OneToOne
    : One-to-one relationship
  • @OneToMany
    : One-to-many relationship
  • @ManyToOne
    : Many-to-one relationship
  • @ManyToMany
    : Many-to-many relationship
  • @JoinColumn
    : Join column
  • @JoinTable
    : Join table
Validation Annotations:
  • @Valid
    : Enable validation
  • @NotNull
    : Field cannot be null
  • @NotEmpty
    : Field cannot be empty
  • @NotBlank
    : Field cannot be blank
  • @Size
    : String or collection size
  • @Min
    : Minimum value
  • @Max
    : Maximum value
  • @Email
    : Email format
  • @Pattern
    : Regex pattern
Transaction Annotations:
  • @Transactional
    : Enable transaction management
  • @Transactional(readOnly = true)
    : Read-only transaction
Security Annotations:
  • @EnableWebSecurity
    : Enable security
  • @PreAuthorize
    : Method-level authorization
  • @PostAuthorize
    : Post-method authorization
  • @Secured
    : Role-based access
Async and Scheduling:
  • @EnableAsync
    : Enable async processing
  • @Async
    : Async method
  • @EnableScheduling
    : Enable scheduling
  • @Scheduled
    : Scheduled method
核心Spring注解:
  • @SpringBootApplication
    : 主应用类注解
  • @Component
    : 通用组件注解
  • @Service
    : 服务层组件注解
  • @Repository
    : 数据访问层组件注解
  • @Configuration
    : 配置类注解
  • @Bean
    : Bean定义方法注解
  • @Autowired
    : 依赖注入注解
  • @Value
    : 属性值注入注解
  • @Profile
    : 基于环境的条件化Bean注解
Web相关注解:
  • @RestController
    : REST API控制器注解
  • @Controller
    : MVC控制器注解
  • @RequestMapping
    : HTTP请求映射注解
  • @GetMapping
    : GET请求映射注解
  • @PostMapping
    : POST请求映射注解
  • @PutMapping
    : PUT请求映射注解
  • @DeleteMapping
    : DELETE请求映射注解
  • @PatchMapping
    : PATCH请求映射注解
  • @PathVariable
    : 路径变量提取注解
  • @RequestParam
    : 查询参数提取注解
  • @RequestBody
    : 请求体提取注解
  • @RequestHeader
    : 请求头提取注解
  • @ResponseStatus
    : 响应状态设置注解
数据相关注解:
  • @Entity
    : JPA实体注解
  • @Table
    : 表映射注解
  • @Id
    : 主键注解
  • @GeneratedValue
    : 自动生成值注解
  • @Column
    : 列映射注解
  • @OneToOne
    : 一对一关联注解
  • @OneToMany
    : 一对多关联注解
  • @ManyToOne
    : 多对一关联注解
  • @ManyToMany
    : 多对多关联注解
  • @JoinColumn
    : 关联列注解
  • @JoinTable
    : 关联表注解
验证相关注解:
  • @Valid
    : 启用验证注解
  • @NotNull
    : 字段不能为空注解
  • @NotEmpty
    : 字段不能为空注解
  • @NotBlank
    : 字段不能为空白注解
  • @Size
    : 字符串或集合大小限制注解
  • @Min
    : 最小值限制注解
  • @Max
    : 最大值限制注解
  • @Email
    : 邮箱格式验证注解
  • @Pattern
    : 正则表达式验证注解
事务相关注解:
  • @Transactional
    : 启用事务管理注解
  • @Transactional(readOnly = true)
    : 只读事务注解
安全相关注解:
  • @EnableWebSecurity
    : 启用安全配置注解
  • @PreAuthorize
    : 方法级前置授权注解
  • @PostAuthorize
    : 方法级后置授权注解
  • @Secured
    : 基于角色的访问控制注解
异步与调度注解:
  • @EnableAsync
    : 启用异步处理注解
  • @Async
    : 异步方法注解
  • @EnableScheduling
    : 启用任务调度注解
  • @Scheduled
    : 调度任务注解

Workflow Patterns

工作流模式

REST API Design Pattern

REST API设计模式

Complete CRUD REST API:
java
// Entity
@Entity
@Table(name = "products")
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank(message = "Name is required")
    private String name;

    @NotBlank(message = "Description is required")
    private String description;

    @NotNull(message = "Price is required")
    @Min(value = 0, message = "Price must be positive")
    private BigDecimal price;

    @NotNull(message = "Stock is required")
    @Min(value = 0, message = "Stock must be positive")
    private Integer stock;

    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;

    @PrePersist
    protected void onCreate() {
        createdAt = LocalDateTime.now();
        updatedAt = LocalDateTime.now();
    }

    @PreUpdate
    protected void onUpdate() {
        updatedAt = LocalDateTime.now();
    }

    // Getters and setters
}

// Repository
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
    List<Product> findByNameContaining(String name);
    List<Product> findByPriceBetween(BigDecimal minPrice, BigDecimal maxPrice);
}

// Service
@Service
@Transactional
public class ProductService {

    private final ProductRepository productRepository;

    public ProductService(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }

    @Transactional(readOnly = true)
    public Page<Product> findAll(Pageable pageable) {
        return productRepository.findAll(pageable);
    }

    @Transactional(readOnly = true)
    public Optional<Product> findById(Long id) {
        return productRepository.findById(id);
    }

    public Product create(Product product) {
        return productRepository.save(product);
    }

    public Optional<Product> update(Long id, Product productDetails) {
        return productRepository.findById(id)
            .map(product -> {
                product.setName(productDetails.getName());
                product.setDescription(productDetails.getDescription());
                product.setPrice(productDetails.getPrice());
                product.setStock(productDetails.getStock());
                return productRepository.save(product);
            });
    }

    public boolean delete(Long id) {
        return productRepository.findById(id)
            .map(product -> {
                productRepository.delete(product);
                return true;
            })
            .orElse(false);
    }
}

// Controller
@RestController
@RequestMapping("/api/products")
public class ProductController {

    private final ProductService productService;

    public ProductController(ProductService productService) {
        this.productService = productService;
    }

    @GetMapping
    public Page<Product> getAllProducts(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(defaultValue = "id") String sortBy) {
        Pageable pageable = PageRequest.of(page, size, Sort.by(sortBy));
        return productService.findAll(pageable);
    }

    @GetMapping("/{id}")
    public ResponseEntity<Product> getProductById(@PathVariable Long id) {
        return productService.findById(id)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }

    @PostMapping
    public ResponseEntity<Product> createProduct(@Valid @RequestBody Product product) {
        Product created = productService.create(product);
        URI location = ServletUriComponentsBuilder
            .fromCurrentRequest()
            .path("/{id}")
            .buildAndExpand(created.getId())
            .toUri();
        return ResponseEntity.created(location).body(created);
    }

    @PutMapping("/{id}")
    public ResponseEntity<Product> updateProduct(
            @PathVariable Long id,
            @Valid @RequestBody Product product) {
        return productService.update(id, product)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteProduct(@PathVariable Long id) {
        if (productService.delete(id)) {
            return ResponseEntity.noContent().build();
        }
        return ResponseEntity.notFound().build();
    }
}
完整的CRUD REST API示例:
java
// 实体类
@Entity
@Table(name = "products")
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank(message = "产品名称为必填项")
    private String name;

    @NotBlank(message = "产品描述为必填项")
    private String description;

    @NotNull(message = "产品价格为必填项")
    @Min(value = 0, message = "产品价格必须为正数")
    private BigDecimal price;

    @NotNull(message = "库存数量为必填项")
    @Min(value = 0, message = "库存数量必须为正数")
    private Integer stock;

    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;

    @PrePersist
    protected void onCreate() {
        createdAt = LocalDateTime.now();
        updatedAt = LocalDateTime.now();
    }

    @PreUpdate
    protected void onUpdate() {
        updatedAt = LocalDateTime.now();
    }

    // Getter和Setter方法
}

// 仓库接口
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
    List<Product> findByNameContaining(String name);
    List<Product> findByPriceBetween(BigDecimal minPrice, BigDecimal maxPrice);
}

// 服务类
@Service
@Transactional
public class ProductService {

    private final ProductRepository productRepository;

    public ProductService(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }

    @Transactional(readOnly = true)
    public Page<Product> findAll(Pageable pageable) {
        return productRepository.findAll(pageable);
    }

    @Transactional(readOnly = true)
    public Optional<Product> findById(Long id) {
        return productRepository.findById(id);
    }

    public Product create(Product product) {
        return productRepository.save(product);
    }

    public Optional<Product> update(Long id, Product productDetails) {
        return productRepository.findById(id)
            .map(product -> {
                product.setName(productDetails.getName());
                product.setDescription(productDetails.getDescription());
                product.setPrice(productDetails.getPrice());
                product.setStock(productDetails.getStock());
                return productRepository.save(product);
            });
    }

    public boolean delete(Long id) {
        return productRepository.findById(id)
            .map(product -> {
                productRepository.delete(product);
                return true;
            })
            .orElse(false);
    }
}

// 控制器类
@RestController
@RequestMapping("/api/products")
public class ProductController {

    private final ProductService productService;

    public ProductController(ProductService productService) {
        this.productService = productService;
    }

    @GetMapping
    public Page<Product> getAllProducts(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(defaultValue = "id") String sortBy) {
        Pageable pageable = PageRequest.of(page, size, Sort.by(sortBy));
        return productService.findAll(pageable);
    }

    @GetMapping("/{id}")
    public ResponseEntity<Product> getProductById(@PathVariable Long id) {
        return productService.findById(id)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }

    @PostMapping
    public ResponseEntity<Product> createProduct(@Valid @RequestBody Product product) {
        Product created = productService.create(product);
        URI location = ServletUriComponentsBuilder
            .fromCurrentRequest()
            .path("/{id}")
            .buildAndExpand(created.getId())
            .toUri();
        return ResponseEntity.created(location).body(created);
    }

    @PutMapping("/{id}")
    public ResponseEntity<Product> updateProduct(
            @PathVariable Long id,
            @Valid @RequestBody Product product) {
        return productService.update(id, product)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteProduct(@PathVariable Long id) {
        if (productService.delete(id)) {
            return ResponseEntity.noContent().build();
        }
        return ResponseEntity.notFound().build();
    }
}

Exception Handling Pattern

异常处理模式

Global Exception Handler:
java
// Custom exceptions
public class ResourceNotFoundException extends RuntimeException {
    public ResourceNotFoundException(String message) {
        super(message);
    }
}

public class BadRequestException extends RuntimeException {
    public BadRequestException(String message) {
        super(message);
    }
}

// Error response
public class ErrorResponse {
    private LocalDateTime timestamp;
    private int status;
    private String error;
    private String message;
    private String path;

    // Constructors, getters, setters
}

// Global exception handler
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleResourceNotFound(
            ResourceNotFoundException ex,
            WebRequest request) {
        ErrorResponse error = new ErrorResponse(
            LocalDateTime.now(),
            HttpStatus.NOT_FOUND.value(),
            "Not Found",
            ex.getMessage(),
            request.getDescription(false).replace("uri=", "")
        );
        return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(BadRequestException.class)
    public ResponseEntity<ErrorResponse> handleBadRequest(
            BadRequestException ex,
            WebRequest request) {
        ErrorResponse error = new ErrorResponse(
            LocalDateTime.now(),
            HttpStatus.BAD_REQUEST.value(),
            "Bad Request",
            ex.getMessage(),
            request.getDescription(false).replace("uri=", "")
        );
        return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, Object>> handleValidationErrors(
            MethodArgumentNotValidException ex) {
        Map<String, Object> errors = new HashMap<>();
        errors.put("timestamp", LocalDateTime.now());
        errors.put("status", HttpStatus.BAD_REQUEST.value());

        Map<String, String> fieldErrors = new HashMap<>();
        ex.getBindingResult().getFieldErrors().forEach(error ->
            fieldErrors.put(error.getField(), error.getDefaultMessage())
        );
        errors.put("errors", fieldErrors);

        return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleGlobalException(
            Exception ex,
            WebRequest request) {
        ErrorResponse error = new ErrorResponse(
            LocalDateTime.now(),
            HttpStatus.INTERNAL_SERVER_ERROR.value(),
            "Internal Server Error",
            ex.getMessage(),
            request.getDescription(false).replace("uri=", "")
        );
        return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}
全局异常处理器:
java
// 自定义异常类
public class ResourceNotFoundException extends RuntimeException {
    public ResourceNotFoundException(String message) {
        super(message);
    }
}

public class BadRequestException extends RuntimeException {
    public BadRequestException(String message) {
        super(message);
    }
}

// 错误响应类
public class ErrorResponse {
    private LocalDateTime timestamp;
    private int status;
    private String error;
    private String message;
    private String path;

    // 构造函数、Getter和Setter方法
}

// 全局异常处理器
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleResourceNotFound(
            ResourceNotFoundException ex,
            WebRequest request) {
        ErrorResponse error = new ErrorResponse(
            LocalDateTime.now(),
            HttpStatus.NOT_FOUND.value(),
            "资源未找到",
            ex.getMessage(),
            request.getDescription(false).replace("uri=", "")
        );
        return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(BadRequestException.class)
    public ResponseEntity<ErrorResponse> handleBadRequest(
            BadRequestException ex,
            WebRequest request) {
        ErrorResponse error = new ErrorResponse(
            LocalDateTime.now(),
            HttpStatus.BAD_REQUEST.value(),
            "请求参数错误",
            ex.getMessage(),
            request.getDescription(false).replace("uri=", "")
        );
        return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, Object>> handleValidationErrors(
            MethodArgumentNotValidException ex) {
        Map<String, Object> errors = new HashMap<>();
        errors.put("timestamp", LocalDateTime.now());
        errors.put("status", HttpStatus.BAD_REQUEST.value());

        Map<String, String> fieldErrors = new HashMap<>();
        ex.getBindingResult().getFieldErrors().forEach(error ->
            fieldErrors.put(error.getField(), error.getDefaultMessage())
        );
        errors.put("errors", fieldErrors);

        return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleGlobalException(
            Exception ex,
            WebRequest request) {
        ErrorResponse error = new ErrorResponse(
            LocalDateTime.now(),
            HttpStatus.INTERNAL_SERVER_ERROR.value(),
            "内部服务器错误",
            ex.getMessage(),
            request.getDescription(false).replace("uri=", "")
        );
        return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

Database Integration Pattern

数据库集成模式

Complete Database Setup:
java
// application.yml
/*
spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/mydb
    username: user
    password: password
  jpa:
    hibernate:
      ddl-auto: validate
    show-sql: true
    properties:
      hibernate:
        dialect: org.hibernate.dialect.PostgreSQLDialect
*/

// Flyway migrations (db/migration/V1__Create_users_table.sql)
/*
CREATE TABLE users (
    id BIGSERIAL PRIMARY KEY,
    email VARCHAR(255) NOT NULL UNIQUE,
    name VARCHAR(255) NOT NULL,
    password VARCHAR(255) NOT NULL,
    created_at TIMESTAMP NOT NULL,
    updated_at TIMESTAMP NOT NULL
);

CREATE INDEX idx_users_email ON users(email);
*/

// Entity with auditing
@Entity
@Table(name = "users")
@EntityListeners(AuditingEntityListener.class)
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, unique = true)
    private String email;

    @Column(nullable = false)
    private String name;

    @Column(nullable = false)
    private String password;

    @CreatedDate
    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;

    @LastModifiedDate
    @Column(name = "updated_at")
    private LocalDateTime updatedAt;

    // Getters and setters
}

// Enable JPA auditing
@Configuration
@EnableJpaAuditing
public class JpaConfig {
}
完整数据库配置示例:
java
// application.yml
/*
spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/mydb
    username: user
    password: password
  jpa:
    hibernate:
      ddl-auto: validate
    show-sql: true
    properties:
      hibernate:
        dialect: org.hibernate.dialect.PostgreSQLDialect
*/

// Flyway迁移脚本(db/migration/V1__Create_users_table.sql)
/*
CREATE TABLE users (
    id BIGSERIAL PRIMARY KEY,
    email VARCHAR(255) NOT NULL UNIQUE,
    name VARCHAR(255) NOT NULL,
    password VARCHAR(255) NOT NULL,
    created_at TIMESTAMP NOT NULL,
    updated_at TIMESTAMP NOT NULL
);

CREATE INDEX idx_users_email ON users(email);
*/

// 带有审计功能的实体类
@Entity
@Table(name = "users")
@EntityListeners(AuditingEntityListener.class)
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, unique = true)
    private String email;

    @Column(nullable = false)
    private String name;

    @Column(nullable = false)
    private String password;

    @CreatedDate
    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;

    @LastModifiedDate
    @Column(name = "updated_at")
    private LocalDateTime updatedAt;

    // Getter和Setter方法
}

// 启用JPA审计
@Configuration
@EnableJpaAuditing
public class JpaConfig {
}

Testing Pattern

测试模式

Unit Tests:
java
@SpringBootTest
class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @BeforeEach
    void setUp() {
        MockitoAnnotations.openMocks(this);
    }

    @Test
    void testFindById_Success() {
        User user = new User();
        user.setId(1L);
        user.setEmail("test@example.com");

        when(userRepository.findById(1L)).thenReturn(Optional.of(user));

        Optional<User> result = userService.findById(1L);

        assertTrue(result.isPresent());
        assertEquals("test@example.com", result.get().getEmail());
        verify(userRepository, times(1)).findById(1L);
    }

    @Test
    void testFindById_NotFound() {
        when(userRepository.findById(1L)).thenReturn(Optional.empty());

        Optional<User> result = userService.findById(1L);

        assertFalse(result.isPresent());
    }
}
Integration Tests:
java
@SpringBootTest
@AutoConfigureMockMvc
@Transactional
class UserControllerIntegrationTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private UserRepository userRepository;

    @Test
    void testCreateUser_Success() throws Exception {
        User user = new User();
        user.setEmail("test@example.com");
        user.setName("Test User");

        mockMvc.perform(post("/api/users")
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsString(user)))
            .andExpect(status().isCreated())
            .andExpect(jsonPath("$.email").value("test@example.com"))
            .andExpect(jsonPath("$.name").value("Test User"));
    }

    @Test
    void testGetUser_Success() throws Exception {
        User user = new User();
        user.setEmail("test@example.com");
        user.setName("Test User");
        User saved = userRepository.save(user);

        mockMvc.perform(get("/api/users/" + saved.getId()))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.id").value(saved.getId()))
            .andExpect(jsonPath("$.email").value("test@example.com"));
    }

    @Test
    void testGetUser_NotFound() throws Exception {
        mockMvc.perform(get("/api/users/999"))
            .andExpect(status().isNotFound());
    }
}
单元测试:
java
@SpringBootTest
class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @BeforeEach
    void setUp() {
        MockitoAnnotations.openMocks(this);
    }

    @Test
    void testFindById_Success() {
        User user = new User();
        user.setId(1L);
        user.setEmail("test@example.com");

        when(userRepository.findById(1L)).thenReturn(Optional.of(user));

        Optional<User> result = userService.findById(1L);

        assertTrue(result.isPresent());
        assertEquals("test@example.com", result.get().getEmail());
        verify(userRepository, times(1)).findById(1L);
    }

    @Test
    void testFindById_NotFound() {
        when(userRepository.findById(1L)).thenReturn(Optional.empty());

        Optional<User> result = userService.findById(1L);

        assertFalse(result.isPresent());
    }
}
集成测试:
java
@SpringBootTest
@AutoConfigureMockMvc
@Transactional
class UserControllerIntegrationTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private UserRepository userRepository;

    @Test
    void testCreateUser_Success() throws Exception {
        User user = new User();
        user.setEmail("test@example.com");
        user.setName("Test User");

        mockMvc.perform(post("/api/users")
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsString(user)))
            .andExpect(status().isCreated())
            .andExpect(jsonPath("$.email").value("test@example.com"))
            .andExpect(jsonPath("$.name").value("Test User"));
    }

    @Test
    void testGetUser_Success() throws Exception {
        User user = new User();
        user.setEmail("test@example.com");
        user.setName("Test User");
        User saved = userRepository.save(user);

        mockMvc.perform(get("/api/users/" + saved.getId()))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.id").value(saved.getId()))
            .andExpect(jsonPath("$.email").value("test@example.com"));
    }

    @Test
    void testGetUser_NotFound() throws Exception {
        mockMvc.perform(get("/api/users/999"))
            .andExpect(status().isNotFound());
    }
}

Best Practices

最佳实践

1. Use Constructor Injection

1. 使用构造函数注入

Constructor injection is the recommended approach for dependency injection.
java
// Good - Constructor injection
@Service
public class UserService {
    private final UserRepository userRepository;
    private final EmailService emailService;

    public UserService(UserRepository userRepository, EmailService emailService) {
        this.userRepository = userRepository;
        this.emailService = emailService;
    }
}

// Bad - Field injection
@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
}
构造函数注入是依赖注入的推荐方式。
java
// 推荐 - 构造函数注入
@Service
public class UserService {
    private final UserRepository userRepository;
    private final EmailService emailService;

    public UserService(UserRepository userRepository, EmailService emailService) {
        this.userRepository = userRepository;
        this.emailService = emailService;
    }
}

// 不推荐 - 字段注入
@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
}

2. Use DTOs for API Requests/Responses

2. 为API请求/响应使用DTO

Don't expose entities directly through REST APIs.
java
// DTO
public class UserDTO {
    private Long id;
    private String email;
    private String name;

    // No password field exposed
    // Getters and setters
}

// Mapper
@Component
public class UserMapper {
    public UserDTO toDTO(User user) {
        UserDTO dto = new UserDTO();
        dto.setId(user.getId());
        dto.setEmail(user.getEmail());
        dto.setName(user.getName());
        return dto;
    }

    public User toEntity(UserDTO dto) {
        User user = new User();
        user.setEmail(dto.getEmail());
        user.setName(dto.getName());
        return user;
    }
}

// Controller
@RestController
@RequestMapping("/api/users")
public class UserController {
    private final UserService userService;
    private final UserMapper userMapper;

    @GetMapping("/{id}")
    public ResponseEntity<UserDTO> getUser(@PathVariable Long id) {
        return userService.findById(id)
            .map(userMapper::toDTO)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }
}
不要直接通过REST API暴露实体类。
java
// DTO类
public class UserDTO {
    private Long id;
    private String email;
    private String name;

    // 不暴露密码字段
    // Getter和Setter方法
}

// 映射器类
@Component
public class UserMapper {
    public UserDTO toDTO(User user) {
        UserDTO dto = new UserDTO();
        dto.setId(user.getId());
        dto.setEmail(user.getEmail());
        dto.setName(user.getName());
        return dto;
    }

    public User toEntity(UserDTO dto) {
        User user = new User();
        user.setEmail(dto.getEmail());
        user.setName(dto.getName());
        return user;
    }
}

// 控制器类
@RestController
@RequestMapping("/api/users")
public class UserController {
    private final UserService userService;
    private final UserMapper userMapper;

    @GetMapping("/{id}")
    public ResponseEntity<UserDTO> getUser(@PathVariable Long id) {
        return userService.findById(id)
            .map(userMapper::toDTO)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }
}

3. Use Validation

3. 使用验证机制

Always validate input data.
java
// Entity with validation
@Entity
public class User {
    @NotBlank(message = "Email is required")
    @Email(message = "Email should be valid")
    private String email;

    @NotBlank(message = "Name is required")
    @Size(min = 2, max = 100, message = "Name must be between 2 and 100 characters")
    private String name;

    @NotBlank(message = "Password is required")
    @Size(min = 8, message = "Password must be at least 8 characters")
    private String password;
}

// Controller
@PostMapping
public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
    // Validation happens automatically
    return ResponseEntity.ok(userService.save(user));
}
始终验证输入数据。
java
// 带有验证注解的实体类
@Entity
public class User {
    @NotBlank(message = "邮箱为必填项")
    @Email(message = "请输入有效的邮箱地址")
    private String email;

    @NotBlank(message = "姓名为必填项")
    @Size(min = 2, max = 100, message = "姓名长度必须在2到100个字符之间")
    private String name;

    @NotBlank(message = "密码为必填项")
    @Size(min = 8, message = "密码长度至少为8个字符")
    private String password;
}

// 控制器类
@PostMapping
public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
    // 验证会自动执行
    return ResponseEntity.ok(userService.save(user));
}

4. Use Transactions Properly

4. 正确使用事务

Mark service methods with appropriate transaction settings.
java
@Service
@Transactional
public class OrderService {

    @Transactional(readOnly = true)
    public List<Order> findAll() {
        return orderRepository.findAll();
    }

    @Transactional
    public Order createOrder(Order order) {
        // Multiple database operations in one transaction
        Order saved = orderRepository.save(order);
        inventoryService.decreaseStock(order.getItems());
        emailService.sendOrderConfirmation(saved);
        return saved;
    }
}
为服务方法标记合适的事务设置。
java
@Service
@Transactional
public class OrderService {

    @Transactional(readOnly = true)
    public List<Order> findAll() {
        return orderRepository.findAll();
    }

    @Transactional
    public Order createOrder(Order order) {
        // 多个数据库操作在同一个事务中执行
        Order saved = orderRepository.save(order);
        inventoryService.decreaseStock(order.getItems());
        emailService.sendOrderConfirmation(saved);
        return saved;
    }
}

5. Use Pagination

5. 使用分页

Always paginate large datasets.
java
@GetMapping
public Page<Product> getProducts(
        @RequestParam(defaultValue = "0") int page,
        @RequestParam(defaultValue = "20") int size,
        @RequestParam(defaultValue = "id") String sortBy) {
    Pageable pageable = PageRequest.of(page, size, Sort.by(sortBy));
    return productService.findAll(pageable);
}
对大型数据集始终使用分页。
java
@GetMapping
public Page<Product> getProducts(
        @RequestParam(defaultValue = "0") int page,
        @RequestParam(defaultValue = "20") int size,
        @RequestParam(defaultValue = "id") String sortBy) {
    Pageable pageable = PageRequest.of(page, size, Sort.by(sortBy));
    return productService.findAll(pageable);
}

6. Handle Exceptions Globally

6. 全局处理异常

Use
@RestControllerAdvice
for centralized exception handling.
java
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException ex) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND)
            .body(new ErrorResponse(ex.getMessage()));
    }
}
使用
@RestControllerAdvice
实现集中式异常处理。
java
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException ex) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND)
            .body(new ErrorResponse(ex.getMessage()));
    }
}

7. Use Logging

7. 使用日志

Implement proper logging throughout your application.
java
@Service
public class UserService {
    private static final Logger logger = LoggerFactory.getLogger(UserService.class);

    public User createUser(User user) {
        logger.info("Creating user with email: {}", user.getEmail());
        try {
            User saved = userRepository.save(user);
            logger.info("User created successfully with id: {}", saved.getId());
            return saved;
        } catch (Exception e) {
            logger.error("Error creating user: {}", e.getMessage(), e);
            throw e;
        }
    }
}
在应用中实现合适的日志记录。
java
@Service
public class UserService {
    private static final Logger logger = LoggerFactory.getLogger(UserService.class);

    public User createUser(User user) {
        logger.info("正在创建邮箱为{}的用户", user.getEmail());
        try {
            User saved = userRepository.save(user);
            logger.info("用户创建成功,用户ID为{}", saved.getId());
            return saved;
        } catch (Exception e) {
            logger.error("创建用户失败:{}", e.getMessage(), e);
            throw e;
        }
    }
}

8. Secure Your Endpoints

8. 保护你的端点

Implement proper authentication and authorization.
java
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/public/**").permitAll()
                .requestMatchers("/api/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            )
            .oauth2ResourceServer().jwt();

        return http.build();
    }
}
实现合适的认证与授权机制。
java
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/public/**").permitAll()
                .requestMatchers("/api/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            )
            .oauth2ResourceServer().jwt();

        return http.build();
    }
}

9. Use Database Migrations

9. 使用数据库迁移工具

Use Flyway or Liquibase for database version control.
sql
-- V1__Create_users_table.sql
CREATE TABLE users (
    id BIGSERIAL PRIMARY KEY,
    email VARCHAR(255) NOT NULL UNIQUE,
    name VARCHAR(255) NOT NULL,
    created_at TIMESTAMP NOT NULL
);

-- V2__Add_password_column.sql
ALTER TABLE users ADD COLUMN password VARCHAR(255);
使用Flyway或Liquibase进行数据库版本控制。
sql
-- V1__Create_users_table.sql
CREATE TABLE users (
    id BIGSERIAL PRIMARY KEY,
    email VARCHAR(255) NOT NULL UNIQUE,
    name VARCHAR(255) NOT NULL,
    created_at TIMESTAMP NOT NULL
);

-- V2__Add_password_column.sql
ALTER TABLE users ADD COLUMN password VARCHAR(255);

10. Monitor Your Application

10. 监控你的应用

Use Spring Boot Actuator for monitoring.
properties
undefined
使用Spring Boot Actuator进行应用监控。
properties
undefined

application.properties

application.properties

management.endpoints.web.exposure.include=health,info,metrics management.endpoint.health.show-details=always
undefined
management.endpoints.web.exposure.include=health,info,metrics management.endpoint.health.show-details=always
undefined

Examples

示例代码

See EXAMPLES.md for detailed code examples including:
  • Basic Spring Boot Application
  • REST API with CRUD Operations
  • Database Integration with JPA
  • Custom Queries and Specifications
  • Request Validation
  • Exception Handling
  • Authentication with JWT
  • Role-Based Authorization
  • File Upload/Download
  • Caching with Redis
  • Async Processing
  • Scheduled Tasks
  • Multiple Database Configuration
  • Actuator and Monitoring
  • Docker Deployment
查看EXAMPLES.md获取详细的代码示例,包括:
  • 基础Spring Boot应用
  • 带有CRUD操作的REST API
  • 基于JPA的数据库集成
  • 自定义查询与规范
  • 请求验证
  • 异常处理
  • JWT认证
  • 基于角色的授权
  • 文件上传/下载
  • Redis缓存
  • 异步处理
  • 定时任务
  • 多数据库配置
  • Actuator与监控
  • Docker部署

Summary

总结

This Spring Boot development skill covers:
  1. Auto-Configuration: Automatic configuration based on dependencies
  2. Dependency Injection: IoC container, constructor injection, component stereotypes
  3. REST APIs: Controllers, request mapping, response handling
  4. Spring Data JPA: Entities, repositories, relationships, queries
  5. Configuration: Properties, YAML, profiles, custom properties
  6. Security: Authentication, authorization, JWT, role-based access
  7. Exception Handling: Global exception handling, custom exceptions
  8. Testing: Unit tests, integration tests, MockMvc
  9. Best Practices: DTOs, validation, transactions, pagination, logging
  10. Production Ready: Actuator, monitoring, database migrations, deployment
The patterns and examples are based on official Spring Boot documentation (Trust Score: 7.5) and represent modern enterprise Java development practices.
本Spring Boot开发技能涵盖以下内容:
  1. 自动配置:基于依赖的自动配置机制
  2. 依赖注入:IoC容器、构造函数注入、组件 stereotype
  3. REST API:控制器、请求映射、响应处理
  4. Spring Data JPA:实体、仓库、关联关系、查询
  5. 配置:Properties、YAML、环境配置、自定义属性
  6. 安全机制:认证、授权、JWT、基于角色的访问控制
  7. 异常处理:全局异常处理、自定义异常
  8. 测试:单元测试、集成测试、MockMvc
  9. 最佳实践:DTO、验证、事务、分页、日志
  10. 生产就绪:Actuator监控、数据库迁移、部署
这些模式和示例基于官方Spring Boot文档(可信度评分:7.5),代表了现代企业级Java开发的最佳实践。