Spring Boot 入门与项目结构(基础篇)——难道启动就那么难吗?

举报
喵手 发表于 2026/01/15 16:58:07 2026/01/15
【摘要】 开篇语哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,...

开篇语

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

1. 简介:Spring Boot 的定位与优点

  • 定位:Spring Boot 是 Spring 的“开箱即用”解决方案,目标是让你用最少的配置快速启动 Spring 应用。

  • 优点

    • 约定优于配置(Opinionated Defaults):有一套合理的默认值,减少配置量。
    • 自动配置(Auto-Configuration):根据 classpath、bean、配置自动装配组件。
    • 内嵌容器(Embedded servlet container):打包成可执行 jar,内含 Tomcat/Jetty/Undertow。
    • Starter 依赖管理:提供一套“按需”组合依赖(spring-boot-starter-web 等)。
    • 生产级特性:Actuator、metrics、外部化配置、profiles 等。

是不是感觉像把传统 Spring 的“繁琐起步”给一脚踢走了?😉

2. 关键概念 / 注解(核心三件套)

@SpringBootApplication

这是最常见的注解,通常放在主类上:

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

它相当于三合一:

@SpringBootConfiguration  (通常是 @Configuration 的一个特化)
@EnableAutoConfiguration  (启用自动配置)
@ComponentScan             (默认扫描包及子包)

所以把它放在根包(root package)上,能让 @Component@Controller@Service 等被自动扫描到。

SpringApplication

SpringApplication.run(...) 是启动入口。它将:

  1. 创建 ApplicationContext(通常是 AnnotationConfigApplicationContextSpringApplication 依据 web 环境选择 AnnotationConfigServletWebServerApplicationContext
  2. 执行 SpringApplicationRunListeners(例如 ApplicationStarted、EnvironmentPrepared 等事件)
  3. 加载并应用自动配置(AutoConfiguration)
  4. 刷新上下文并初始化所有单例 bean
  5. 如果是 web 应用,启动内嵌容器并映射 DispatcherServlet

你可以通过 SpringApplication 的 API 做一些自定义启动行为(比如关闭 banner,开启/关闭热重载等)。

application.properties / application.yml

  • 作用:外部化配置(配置优先级:application.properties/yml < 环境变量 < 命令行参数 等)。
  • 常见配置示例application.properties):
server.port=8080
spring.application.name=demo-app
logging.level.org.springframework=INFO
  • YAML 示例application.yml)更适合结构化配置:
server:
  port: 8080

spring:
  application:
    name: demo-app

logging:
  level:
    org.springframework: INFO

application-{profile}.yml 可以配合 --spring.profiles.active=dev 使用,实现多环境配置。

3. Spring Boot 启动流程(从 main 到应用就绪)

大体流程(简化版):

  1. main() 方法 执行:通常是 SpringApplication.run(App.class, args)
  2. 构造 SpringApplication:解析参数、设置 banner、listeners 等。
  3. 准备 Environment:解析 application.properties/yml、加载命令行参数、环境变量。
  4. 创建 ApplicationContext:根据是否是 Web 应用选择不同的 ApplicationContext 实现。
  5. 执行自动配置(Auto-Configuration):加载 META-INF/spring.factoriesspring-autoconfigure-metadata 中的配置,按条件注入 Bean。
  6. 注册并实例化 Bean(包括用户定义的和自动配置的)
  7. 刷新上下文:触发 ContextRefreshedEvent 等事件。
  8. 启动内嵌容器(若为 web):嵌入 Tomcat/Jetty/Undertow 并开始监听端口。
  9. 应用就绪:触发 ApplicationReadyEvent

小技巧:你可以监听 ApplicationReadyEvent 来做启动后的初始化(例如缓存预热、注册 etcd/zookeeper 服务等)。

4. 自动配置原则(@EnableAutoConfiguration 与条件注解)

自动配置是 Spring Boot 的灵魂:把常见场景的配置封装成“自动装配”的模块。

实现机制简述

  • Spring Boot 在 spring-boot-autoconfigure 模块中通过 @Configuration 类实现自动配置,这些类会被 spring.factoriesspring-autoconfigure-metadata 注册。

  • 每个自动配置类通常带有条件注解,例如:

    • @ConditionalOnClass:当类路径存在指定类时才生效(例如 DataSource 类存在 → 加载数据库相关配置)。
    • @ConditionalOnMissingBean:只有在容器内不存在指定 bean 时才自动配置(保证用户自定义优先)。
    • @ConditionalOnProperty:基于配置项判断是否启用。
    • 还有 @ConditionalOnBean@ConditionalOnExpression 等。

原则

  • 约定优于配置:默认开启合理功能,用户可以覆盖配置或自定义 Bean 来替换默认行为。
  • 不入侵:自动配置通常在条件不满足时不装配,避免破坏用户显式配置。
  • 显式优先:用户自己声明的 Bean 会覆盖自动配置(@ConditionalOnMissingBean)。

5. 常见目录结构与约定

Spring Boot 项目通常遵循 Maven/Gradle 的标准布局,且以包扫描为核心:

project-root
├── pom.xml / build.gradle
└── src
    ├── main
    │   ├── java
    │   │   └── com.example.demo
    │   │       ├── DemoApplication.java    <-- 主类(@SpringBootApplication)
    │   │       ├── controller
    │   │       │   └── HelloController.java
    │   │       ├── service
    │   │       └── repository
    │   └── resources
    │       ├── application.yml             <-- 配置
    │       ├── static                      <-- 静态资源(前端)
    │       └── templates                   <-- Thymeleaf / Freemarker 等
    └── test
        └── java

约定与建议

  • 把主类放在最顶层包(例如 com.example.demo),使 @ComponentScan 能扫描到所有子包。
  • application.properties/application.yml 放在 src/main/resources
  • 静态资源放 resources/static,模板放 resources/templates
  • 使用 src/test/java 写单元与集成测试(Spring Boot Test)。

6. Starter 的概念与使用

Starter = 预先打包好的依赖集合。例如,spring-boot-starter-web 帮你带上:

  • spring-webspring-webmvc
  • 嵌入式 Tomcat(默认)
  • Jackson(用于 JSON 序列化/反序列化)

使用方式(Maven)

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

常见 starter 列表(挑几个常用):

  • spring-boot-starter-web:构建 REST/Servlet 应用
  • spring-boot-starter-webflux:响应式 Web(Reactor)
  • spring-boot-starter-data-jpa:Spring Data JPA(Hibernate)
  • spring-boot-starter-security:Spring Security
  • spring-boot-starter-test:测试相关(JUnit、MockMvc 等)
  • spring-boot-starter-actuator:暴露应用运行时信息与自定义监控端点

注意:不要随意把多个不同的 web 容器 starter(比如 tomcat 与 undertow)都加上,会造成冲突或不必要的依赖。

7. 实战练习:创建一个简单 REST 应用并打成可执行 jar

下面给一个完整最小 demo(Maven)。目标:创建一个简单的 REST API /api/hello 返回 {"message":"Hello, Spring Boot!"},并打包成可执行 jar。

1) 新建 Maven 项目(pom.xml)

<!-- pom.xml -->
<project xmlns="http://maven.apache.org/POM/4.0.0" ...>
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example</groupId>
  <artifactId>springboot-demo</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.1.0</version> <!-- 根据你的需要选择版本 -->
    <relativePath/> <!-- lookup parent from repository -->
  </parent>

  <dependencies>
    <!-- Web starter 包括 Spring MVC + Jackson + 嵌入式 Tomcat -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- 测试 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>

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

注:spring-boot-starter-parent 帮你管理依赖版本(BOM),推荐使用它或 spring-boot-dependencies BOM。

2) 主类与 Controller

// src/main/java/com/example/springbootdemo/DemoApplication.java
package com.example.springbootdemo;

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);
  }
}
// src/main/java/com/example/springbootdemo/controller/HelloController.java
package com.example.springbootdemo.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@RestController
public class HelloController {

  @GetMapping("/api/hello")
  public ResponseEntity<Map<String, String>> hello() {
    return ResponseEntity.ok(Map.of("message", "Hello, Spring Boot!"));
  }
}

3) 配置(可选)

src/main/resources/application.properties

server.port=8080
spring.application.name=springboot-demo
logging.level.org.springframework=INFO

4) 打包并运行

在项目根目录运行:

# 打包
mvn clean package

# 运行可执行 jar(target/springboot-demo-0.0.1-SNAPSHOT.jar)
java -jar target/springboot-demo-0.0.1-SNAPSHOT.jar

访问 http://localhost:8080/api/hello,应该能看到:

{"message":"Hello, Spring Boot!"}

恭喜你 —— 你已经创建并运行起了一个 Spring Boot 应用 🎉

8. 常见陷阱与解决方案

1) 重复依赖或容器冲突

  • 症状:启动时报 ClassNotFoundExceptionNoSuchMethodError,或内嵌容器启动失败(端口绑定错误除外)。
  • 原因:手动引入不同版本的库或错误地同时引入多个容器(Tomcat + Undertow),或直接引入 servlet-api(会与内嵌容器冲突)。
  • 解决:使用 spring-boot-starter-parentspring-boot-dependencies 管理版本;检查 mvn dependency:tree;将 servlet-api 设置为 provided(如果必须引入)。

2) Starter 版本冲突

  • 症状:依赖版本不一致导致运行时错误(如 Jackson 版本不匹配)。
  • 解决:使用父 POM 或 BOM;不要单独指定与 Spring Boot 不一致的依赖版本;如果确实需要覆盖,谨慎使用 <dependencyManagement>

3) profile 配置没生效

  • 常见原因:命令行未传入 --spring.profiles.active=dev,或者配置文件命名不正确(application-dev.yml)。
  • 建议:在本地使用 application-dev.yml,并通过 -Dspring.profiles.active=dev--spring.profiles.active=dev 启动。

4) 自动装配无法覆盖

  • 情况:你自定义了一个 bean,但是自动配置仍旧生效或冲突。

  • 检查点

    • 自定义 bean 是否在 Spring 容器内(被扫描或在 @Configuration 中声明)?
    • 自动配置是否使用了 @ConditionalOnMissingBean?如果没有,可能需要禁用该自动配置或调整配置项。
  • 解决:可使用 @EnableAutoConfiguration(exclude = {SomeAutoConfiguration.class})spring.autoconfigure.exclude 来排除特定自动配置。

5) 打包后静态资源路径问题

  • 注意:静态资源应放在 src/main/resources/staticpublic,模板放 templates。Jar 包结构下资源映射路径与开发环境一致,但某些资源加载策略(如 Classpath vs FileSystem)应注意。

9. 延伸:Spring Boot 与传统 Spring 的差别(说人话)

方面 传统 Spring Spring Boot
配置方式 XML 或 Java Config,很多显式配置 约定优于配置,自动配置大量场景
启动 需要部署到外部容器(如 Tomcat) 嵌入容器,可执行 jar
依赖管理 自己管理版本 提供 Parent POM / BOM 管理版本
生产特性 需自行集成 Actuator、metrics、health 等开箱支持
学习曲线 深入理解每个模块配置 快速上手,深入时仍需理解 Spring 细节

一句话:Spring Boot 把大量“起步和整合”的繁琐交给框架,但你仍然需要理解 Spring 的核心(IoC、AOP、事务、数据访问等)来做正确的设计与排错。

10. 小结与上线/开发建议(Checklist)

  • [ ] 主类放在根包,使用 @SpringBootApplication
  • [ ] 使用 spring-boot-starter-parentspring-boot-dependencies 管理依赖版本。
  • [ ] 使用 starter(spring-boot-starter-webspring-boot-starter-data-jpa 等)而非手动拉一堆依赖。
  • [ ] 把配置写在 application.ymlapplication.properties,并使用 profiles (application-dev.yml)。
  • [ ] 在开发时使用 spring-boot-devtools 来提高效率(自动重启、LiveReload)。
  • [ ] 引入 spring-boot-starter-actuator 并配置必要的 endpoint(health、info)以便健康检查与监控。
  • [ ] 用 mvn dependency:tree 或 Gradle 的依赖分析检查冲突。
  • [ ] 在 CI/CD 流程中保证 mvn -DskipTests package 可打包,通过容器化进一步标准化部署。
  • [ ] 生产环境下把日志、敏感配置等外部化(环境变量、ConfigServer、Vault 等)。

常见问答(快答)

Q:@SpringBootApplication 里能否拆分那些注解手动写?
A:可以,把它拆成 @Configuration + @EnableAutoConfiguration + @ComponentScan。不过不推荐,使用合成注解更简洁。

Q:我可以在生产环境使用 jar 还是 war 更好?
A:Spring Boot 支持两者。jar(内嵌容器)部署便利、适合现代微服务;war 适合需要部署到现有应用服务器的场景。

Q:如何查看自动配置是否生效?
A:使用 spring-boot-actuator/actuator/conditions(或早期版本的 /autoconfig)查看哪些自动配置生效、哪些未生效以及原因。

结语(认真也要可爱一下)

Spring Boot 把“很多重复劳动”自动化了,但那不意味着你可以把脑子交给框架。理解启动流程、自动配置与项目约定,能让你在遇到生产问题时少熬夜、少读别人的 PR 评论。要是你愿意,我可以接着给你写——

  • 进阶篇:Actuator、Tracing(Sleuth/OpenTelemetry)、Metrics、Micrometer、Prometheus、Grafana 的整合;
  • 数据库篇:Spring Data JPA 的调优、事务、连接池(HikariCP)、N+1 问题与解决;
  • 部署篇:Docker 化、Kubernetes 部署、配置中心与密钥管理。

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。


版权声明:本文由作者原创,转载请注明出处,谢谢支持!

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。