Spring Boot 框架入门

先看框架承担哪部分职责

Spring Boot 入门:容器创建并连接对象,Controller 把 HTTP 转成方法调用,自动配置根据依赖和配置提供默认组件。业务函数仍应能脱离 HTTP 测试。

最小练习与预期结果:用构造器注入一个服务,先直接单测它,再请求 Controller;分别验证业务行为与 HTTP 映射。

具体 API 与安装版本以模块基线和本篇官方来源为准。先完成这条数据路径,再展开后面的高级配置;框架名称变化后,输入边界、状态归属和失败处理仍是需要理解的机制。

一、创建项目

到 Spring Initializr 选择 Java 21(或 25 LTS)+ Spring Boot 4.1 生成 Maven 项目,勾选 web、actuator 起步。关键依赖(pom.xml 片段;Boot 4 起 Web MVC 的 starter 由 spring-boot-starter-web 更名为 spring-boot-starter-webmvc):

<properties>
    <java.version>21</java.version>
</properties>
<dependencies>
    <!-- Spring MVC + 内嵌 Tomcat(Boot 4 起:starter-web 更名为 starter-webmvc) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webmvc</artifactId>
    </dependency>
</dependencies>

Spring Boot 4.x 基于 Spring Framework 7.x(Jakarta EE 11 基线,Servlet 6.1),命名空间沿用 Boot 3 起的 jakarta.*(如 jakarta.validation.constraints.NotNull);Boot 3→4 的 starter 改名与属性迁移见 Boot 3→4 迁移速查 与 Spring Boot 核心速查。

二、依赖注入(DI)

核心:IoC 容器管理 Bean

你不再 new 对象,而是声明”我需要什么”,容器负责装配。

// @Service:业务层 Bean 的标准标记
@Service
public class GreetingService {

    public String greet(String name) {
        return "Hello, %s!".formatted(name); // Java 15+ formatted
    }
}

// 构造器注入:推荐做法(单一构造器可省略 @Autowired)
@RestController
public class GreetingController {

    private final GreetingService greetingService; // final 保证不可变

    // Spring 4.3+ 单构造器自动注入,无需注解
    public GreetingController(GreetingService greetingService) {
        this.greetingService = greetingService;
    }

    @GetMapping("/greet/{name}")
    public String greet(@PathVariable String name) {
        return greetingService.greet(name);
    }
}

Bean 角色注解对照

注解语义层典型用途
@Component通用组件工具类、转换器
@Service业务逻辑领域服务
@Repository数据访问附加异常转换
@Controller / @RestControllerWeb 层处理 HTTP 请求
@Configuration配置类声明 @Bean 方法

第三方类怎么注入?

无法给第三方类加 @Component,用 @Configuration + @Bean:

@Configuration
public class AppConfig {

    @Bean // 方法返回值注册为单例 Bean
    public Clock clock() {
        return Clock.systemDefaultZone(); // 便于测试时注入固定时钟
    }
}

避免字段注入

// 反例:字段注入隐藏依赖、无法用 final、难以脱离容器单测
@Autowired
private GreetingService service; // 不要这样写

三、自动配置

Spring Boot 按”classpath 里有什么”自动装配合理默认值:

  1. 启动类 @SpringBootApplication = @AutoConfigurationPackage + @EnableAutoConfiguration + @ComponentScan
  2. 自动配置类从 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 加载(Boot 2 的 spring.factories 已废弃)
  3. 每个自动配置带条件注解,条件不满足就不生效:
@AutoConfiguration
@ConditionalOnClass(DataSource.class)      // classpath 有数据源驱动才装配
@ConditionalOnMissingBean(DataSource.class) // 用户自己定义了就让位
public class DataSourceAutoConfiguration { /* ... */ }

排查:启动加 --debug 打印条件评估报告(Positive/Negative matches),或查 Actuator 的 /actuator/conditions 端点。

常用配置覆盖(application.yml):

spring:
  application:
    name: demo
server:
  port: 8080
logging:
  level:
    com.devquest: DEBUG

四、REST Controller 实战

完整 CRUD 片段

// 用 Record 做 DTO:不可变、自动生成访问器与 equals/hashCode
public record TaskDto(Long id, String title, boolean done) {}

@RestController
@RequestMapping("/api/tasks")
public class TaskController {

    private final Map<Long, TaskDto> store = new ConcurrentHashMap<>();
    private final AtomicLong seq = new AtomicLong();

    @GetMapping
    public List<TaskDto> list() {
        return List.copyOf(store.values()); // 返回不可变副本
    }

    @GetMapping("/{id}")
    public ResponseEntity<TaskDto> get(@PathVariable Long id) {
        // ResponseEntity 显式控制状态码与响应体
        return ResponseEntity.of(Optional.ofNullable(store.get(id)));
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED) // 201
    public TaskDto create(@RequestBody @Valid CreateTaskRequest req) {
        long id = seq.incrementAndGet();
        TaskDto task = new TaskDto(id, req.title(), false);
        store.put(id, task);
        return task;
    }

    public record CreateTaskRequest(
            @NotBlank(message = "标题不能为空") String title) {}
}

统一异常处理

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Map<String, String> onValidation(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new LinkedHashMap<>();
        ex.getBindingResult().getFieldErrors()
          .forEach(e -> errors.put(e.getField(), e.getDefaultMessage()));
        return errors;
    }
}

最佳实践

构造器参数使依赖显式,测试可以传入替代实现。final 字段限制重新赋值,不会让依赖对象自动不可变;record 同样只提供浅层不可变的数据载体,成员若是可变集合仍需考虑防御性复制。

Web DTO 与持久化实体分开可避免意外暴露字段和懒加载。循环依赖优先检查职责是否混在一起,Lazy 只能在有明确生命周期理由时使用。把重工作移到 PostConstruct 仍会影响启动,初始化应定义超时、失败和就绪语义。

相关文档

本模块

  • 📖 Spring Boot 核心速查 — 自动配置与注解的完整字典条目
  • 📖 Record / Sealed / 模式匹配速查 — DTO 用到的 Record 语义
  • 📄 现代 Java 特性 — 本文代码大量使用的 Lambda/Stream
  • 📄 第一个项目 — 无框架的纯 Java 版本项目,可对照体会框架带来的差异
  • 📄 Spring Boot 进阶 — 下一篇:JPA、事务与 AOP
暂无评论

发送评论 编辑评论

|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇