Spring Boot 入门与项目结构(基础篇)——难道启动就那么难吗?
开篇语
哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区: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(...) 是启动入口。它将:
- 创建
ApplicationContext(通常是AnnotationConfigApplicationContext或SpringApplication依据 web 环境选择AnnotationConfigServletWebServerApplicationContext) - 执行
SpringApplicationRunListeners(例如 ApplicationStarted、EnvironmentPrepared 等事件) - 加载并应用自动配置(AutoConfiguration)
- 刷新上下文并初始化所有单例 bean
- 如果是 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 到应用就绪)
大体流程(简化版):
main()方法 执行:通常是SpringApplication.run(App.class, args)。- 构造 SpringApplication:解析参数、设置 banner、listeners 等。
- 准备 Environment:解析
application.properties/yml、加载命令行参数、环境变量。 - 创建 ApplicationContext:根据是否是 Web 应用选择不同的 ApplicationContext 实现。
- 执行自动配置(Auto-Configuration):加载
META-INF/spring.factories或spring-autoconfigure-metadata中的配置,按条件注入 Bean。 - 注册并实例化 Bean(包括用户定义的和自动配置的)
- 刷新上下文:触发
ContextRefreshedEvent等事件。 - 启动内嵌容器(若为 web):嵌入 Tomcat/Jetty/Undertow 并开始监听端口。
- 应用就绪:触发
ApplicationReadyEvent。
小技巧:你可以监听
ApplicationReadyEvent来做启动后的初始化(例如缓存预热、注册 etcd/zookeeper 服务等)。
4. 自动配置原则(@EnableAutoConfiguration 与条件注解)
自动配置是 Spring Boot 的灵魂:把常见场景的配置封装成“自动装配”的模块。
实现机制简述:
-
Spring Boot 在
spring-boot-autoconfigure模块中通过@Configuration类实现自动配置,这些类会被spring.factories或spring-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-web、spring-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 Securityspring-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-dependenciesBOM。
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) 重复依赖或容器冲突
- 症状:启动时报
ClassNotFoundException、NoSuchMethodError,或内嵌容器启动失败(端口绑定错误除外)。 - 原因:手动引入不同版本的库或错误地同时引入多个容器(Tomcat + Undertow),或直接引入 servlet-api(会与内嵌容器冲突)。
- 解决:使用
spring-boot-starter-parent或spring-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?如果没有,可能需要禁用该自动配置或调整配置项。
- 自定义 bean 是否在 Spring 容器内(被扫描或在
-
解决:可使用
@EnableAutoConfiguration(exclude = {SomeAutoConfiguration.class})或spring.autoconfigure.exclude来排除特定自动配置。
5) 打包后静态资源路径问题
- 注意:静态资源应放在
src/main/resources/static或public,模板放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-parent或spring-boot-dependencies管理依赖版本。 - [ ] 使用 starter(
spring-boot-starter-web、spring-boot-starter-data-jpa等)而非手动拉一堆依赖。 - [ ] 把配置写在
application.yml或application.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 !!!
⭐️若喜欢我,就请关注我叭。
⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。
版权声明:本文由作者原创,转载请注明出处,谢谢支持!
- 点赞
- 收藏
- 关注作者
评论(0)