Spring Boot

技术栈
后端框架
javaspring微服务后端框架企业级

概览

Spring Boot

Spring Boot 是 Pivotal 团队基于 Spring Framework 推出的开源 Java 后端框架,旨在简化 Spring 应用的初始搭建与开发过程。

是什么

Spring Boot 通过「约定优于配置」的理念,提供了自动配置、起步依赖、Actuator 监控等特性,让开发者能快速创建独立运行的、生产级别的 Spring 应用。内嵌 Tomcat/Jetty/Undertow 容器,无需部署 WAR 包。

解决什么问题

  • 简化配置:告别繁琐的 XML 配置,自动配置大多数场景
  • 快速启动:起步依赖(starter)一键引入整套技术栈
  • 生产就绪:内置健康检查、指标监控、外部化配置
  • 微服务友好:与 Spring Cloud 无缝集成,快速构建分布式系统

关键特性

  • 自动配置:根据类路径依赖自动配置 Spring 应用
  • 起步依赖:spring-boot-starter-* 系列简化 Maven/Gradle 配置
  • 内嵌容器:Tomcat/Jetty/Undertow 开箱即用
  • Actuator:生产级监控端点
  • 外部化配置:application.yml/properties 多环境配置
  • Spring Boot CLI:命令行快速原型开发

安装

Spring Boot 安装指南

1. 环境准备

操作系统

  • Windows 10+ / macOS 11+ / Linux (Ubuntu 20.04+)
  • 推荐 64 位系统

JDK 版本要求

Spring Boot 版本 JDK 要求
Spring Boot 3.x JDK 17+
Spring Boot 2.7.x JDK 8 ~ JDK 17
Spring Boot 2.6.x 及更早 JDK 8 ~ JDK 11

构建工具

  • Maven 3.6.3+(推荐 3.8+)
  • Gradle 7.x+(Spring Boot 3.x 需 7.5+)

IDE(可选)

  • IntelliJ IDEA (Ultimate / Community)
  • Eclipse IDE (with Spring Tools 4)
  • VS Code (with Spring Boot Extension Pack)

2. 安装步骤

方式一:使用 Spring Initializr(推荐)

# 通过 Web 界面创建项目
# 访问 https://start.spring.io

# 或使用 curl 命令创建
curl https://start.spring.io/starter.zip \
  -d dependencies=web,data-jpa,h2 \
  -d javaVersion=17 \
  -d bootVersion=3.2.0 \
  -d groupId=com.example \
  -d artifactId=demo \
  -o demo.zip

unzip demo.zip -d demo
cd demo

方式二:Maven 手动引入

<!-- pom.xml -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.0</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

方式三:Gradle

// build.gradle
plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.0'
    id 'io.spring.dependency-management' version '1.1.4'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
}

安装 Spring Boot CLI(可选)

# macOS (Homebrew)
brew tap spring-io/tap
brew install spring-boot

# 手动安装
wget https://repo.spring.io/release/org/springframework/boot/spring-boot-cli/3.2.0/spring-boot-cli-3.2.0-bin.zip
unzip spring-boot-cli-3.2.0-bin.zip
export PATH=$PATH:$(pwd)/spring-3.2.0/bin

3. 常见安装问题

Q: 下载依赖很慢?

# Maven 镜像配置 (~/.m2/settings.xml)
<;mirror>
    <;id>aliyun</id>
    <;mirrorOf>central</mirrorOf>
    <;url>https://maven.aliyun.com/repository/central</url>
<;/mirror>

# Gradle 镜像 (build.gradle)
repositories {
    maven { url 'https://maven.aliyun.com/repository/central' }
    mavenCentral()
}

Q: JDK 版本不匹配?

确保 JAVA_HOME 指向正确的 JDK 版本,并在 pom.xml 中指定 <java.version>17</java.version>

Q: 端口被占用?

默认 8080 端口被占用时,在 application.properties 中设置:

server.port=8081

Q: Lombok 注解不生效?

IntelliJ IDEA 需安装 Lombok 插件并在 Settings → Build → Compiler → Annotation Processors 中启用注解处理。

示例

Spring Boot Hello World REST API

目标

创建一个最简单的 Spring Boot REST API,返回 "Hello, World!" JSON 响应。

完整代码

1. 主应用类 DemoApplication.java

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

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

2. REST 控制器 HelloController.java

package com.example.demo.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello() {
        return "Hello, World!";
    }

    @GetMapping("/hello/json")
    public Greeting greeting(@RequestParam(defaultValue = "World") String name) {
        return new Greeting("Hello, " + name + "!");
    }
}

class Greeting {
    private String message;

    public Greeting(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}

3. 配置文件 application.properties

server.port=8080
spring.application.name=demo

运行步骤

# Maven
./mvnw spring-boot:run

# Gradle
./gradlew bootRun

# 或打包运行
./mvnw clean package -DskipTests
java -jar target/demo-0.0.1-SNAPSHOT.jar

测试

# 测试纯文本
curl http://localhost:8080/hello
# 输出: Hello, World!

# 测试 JSON
curl http://localhost:8080/hello/json?name=SpringBoot
# 输出: {"message":"Hello, SpringBoot!"}

预期输出

启动日志关键行:

Started DemoApplication in 1.234 seconds (process running for 1.5)

访问接口返回 200 OK,响应体为 Hello, World!

教程

Spring Boot 入门到进阶教程

第一章:Spring Boot 核心概念

1.1 自动配置原理

Spring Boot 的自动配置通过 @SpringBootApplication 注解触发,该注解包含三个关键注解:

  • @SpringBootConfiguration:标记为配置类
  • @EnableAutoConfiguration:启用自动配置机制
  • @ComponentScan:扫描组件
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
// 组合注解的本质
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { ... })
public @interface SpringBootApplication { }

启动时,Spring Boot 通过 spring.factories 文件加载所有 AutoConfiguration 类,根据条件注解(@ConditionalOnClass@ConditionalOnMissingBean 等)决定哪些自动配置生效。

1.2 起步依赖(Starter)

Starter 是一组依赖的集合描述符,通过 Maven 的传递依赖机制,一次性引入某个功能所需的所有 JAR。

常用 Starter:

Starter 用途
spring-boot-starter-web Web 开发(含 Tomcat + Spring MVC)
spring-boot-starter-data-jpa JPA + Hibernate 数据库操作
spring-boot-starter-security 安全认证与授权
spring-boot-starter-test 测试框架集成
spring-boot-starter-actuator 生产监控
spring-boot-starter-validation Bean Validation

1.3 外部化配置

Spring Boot 配置加载优先级(从高到低):

  1. 命令行参数
  2. 操作系统环境变量
  3. application-{profile}.properties(外部)
  4. application.properties(外部)
  5. application-{profile}.properties(classpath)
  6. application.properties(classpath)

第二章:REST API 开发实战

2.1 构建 CRUD 接口

@RestController
@RequestMapping("/api/users")
public class UserController {

    @Autowired
    private UserService userService;

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

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

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public User create(@Valid @RequestBody User user) {
        return userService.save(user);
    }

    @PutMapping("/{id}")
    public User update(@PathVariable Long id, @Valid @RequestBody User user) {
        user.setId(id);
        return userService.update(user);
    }

    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void delete(@PathVariable Long id) {
        userService.deleteById(id);
    }
}

2.2 统一异常处理

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ErrorResponse handleNotFound(ResourceNotFoundException ex) {
        return new ErrorResponse(404, ex.getMessage());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ErrorResponse handleValidation(MethodArgumentNotValidException ex) {
        String message = ex.getBindingResult().getFieldErrors().stream()
            .map(e -> e.getField() + ": " + e.getDefaultMessage())
            .collect(Collectors.joining(", "));
        return new ErrorResponse(400, message);
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ErrorResponse handleGeneral(Exception ex) {
        return new ErrorResponse(500, "服务器内部错误");
    }
}

第三章:数据访问与 JPA

3.1 配置数据源

# application.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC
    username: root
    password: ${DB_PASSWORD}
    driver-class-name: com.mysql.cj.jdbc.Driver
    hikari:
      maximum-pool-size: 10
      minimum-idle: 5

  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    properties:
      hibernate:
        format_sql: true

3.2 实体与 Repository

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

    @Column(nullable = false, length = 50)
    private String name;

    @Column(unique = true)
    private String email;

    @CreatedDate
    private LocalDateTime createdAt;

    @LastModifiedDate
    private LocalDateTime updatedAt;
}

public interface UserRepository extends JpaRepository<User, Long> {

    Optional<User> findByEmail(String email);

    @Query("SELECT u FROM User u WHERE u.name LIKE %:keyword%")
    List<User> searchByName(@Param("keyword") String keyword);

    @Modifying
    @Query("UPDATE User u SET u.email = :email WHERE u.id = :id")
    int updateEmail(@Param("id") Long id, @Param("email") String email);
}

第四章:Actuator 监控

4.1 启用端点

management.endpoints.web.exposure.include=health,info,metrics,prometheus
management.endpoint.health.show-details=always
management.metrics.export.prometheus.enabled=true

4.2 自定义健康检查

@Component
public class DatabaseHealthIndicator implements HealthIndicator {
    @Autowired
    private DataSource dataSource;

    @Override
    public Health health() {
        try (Connection conn = dataSource.getConnection()) {
            if (conn.isValid(1000)) {
                return Health.up()
                    .withDetail("database", "MySQL")
                    .withDetail("status", "connected")
                    .build();
            }
        } catch (Exception e) {
            return Health.down()
                .withDetail("error", e.getMessage())
                .build();
        }
        return Health.down().build();
    }
}

第五章:打包与部署

5.1 Fat JAR 打包

./mvnw clean package -DskipTests
java -jar target/demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod

5.2 Docker 部署

FROM openjdk:17-slim
COPY target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app.jar"]
docker build -t myapp:latest .
docker run -d -p 8080:8080 -e SPRING_PROFILES_ACTIVE=prod myapp:latest

思考题

  1. @SpringBootApplication 的三个组成注解各自的具体作用是什么?
  2. Spring Boot 如何处理循环依赖问题?
  3. 如何自定义一个 Starter 模块?
  4. Actuator 的 /health 端点在生产环境中如何安全暴露?