Spring Boot入门指南:从零构建Java Web应用,告别配置地狱

Spring Boot入门指南:从零构建Java Web应用,告别配置地狱

1. 为什么是Spring Boot?从“配置地狱”到“约定大于配置”

如果你刚开始接触Java Web开发,或者刚从传统的SSH、SSM框架转过来,听到“Spring Boot”这个词,第一反应可能是:这又是一个新框架?我得学多久?别慌,Spring Boot并不是一个全新的技术,它更像是Spring家族的一个“革命性”的增强包。要理解它,我们得先回到“前Spring Boot时代”。

在Spring Boot出现之前,搭建一个标准的Spring MVC项目是什么体验?你需要手动管理一大堆XML配置文件,或者写一堆Java Config。光是搞明白web.xmlspring-mvc.xmlapplicationContext.xml之间的关系和配置项,就足以劝退不少新手。更别提整合MyBatis、Redis、消息队列这些组件时,每个都需要引入对应的依赖、编写配置类、处理版本兼容性问题。这个过程繁琐、重复,且极易出错,业界戏称为“配置地狱”。每个项目开始前,你都得花大量时间在搭建环境、配置依赖上,而不是专注于业务逻辑本身。

Spring Boot的出现,就是为了终结这种状态。它的核心设计哲学是“约定大于配置”。什么意思呢?就是Spring Boot团队根据大量最佳实践,预先为你设定好了一套默认的配置和项目结构。你只需要按照它的“约定”来组织代码,就能快速得到一个可运行的应用,无需(或只需极少量)手动配置。比如,它内嵌了Tomcat、Jetty或Undertow服务器,你写好的应用直接就是一个可执行的JAR包,java -jar一下就能跑起来,彻底告别了手动部署WAR包到外部容器的麻烦。它提供了“起步依赖”,将常用功能(如Web开发、数据访问、安全等)所需的一组依赖打包好,你引入一个spring-boot-starter-web,相关的Spring MVC、Tomcat、JSON处理库就都自动配齐了,版本还是兼容的。它还提供了强大的自动配置机制,根据你引入的依赖和类路径下的内容,自动推断并配置所需的Bean。

所以,对于新手而言,Spring Boot极大地降低了学习曲线和入门门槛。你可以更快地看到成果,建立信心,从而把精力集中在学习Spring的核心概念(如IoC、AOP)和业务开发上。本系列教程的目的,就是手把手带你绕过我当年踩过的那些坑,从零开始,构建一个真正可用的Spring Boot应用,并理解其背后的运作原理。

2. 工欲善其事:环境准备与第一个“Hello World”

在开始敲代码之前,我们需要把“战场”布置好。这里我会给出最简洁、最通用的环境配置方案,并解释每个环节的必要性。

2.1 基础环境三件套:JDK、Maven/Gradle、IDE

1. JDK (Java Development Kit)这是Java开发的基石。Spring Boot 3.x 版本要求至少JDK 17,而Spring Boot 2.x 则兼容JDK 8及以上。为了跟上技术潮流并享受新特性带来的便利(如记录类、文本块等),我强烈建议新手直接从JDK 17或最新的JDK 21 (LTS)开始。

注意:请务必区分JRE(运行环境)和JDK(开发工具包)。开发必须安装JDK。建议从Oracle官网或更开放的Adoptium(Eclipse Temurin)网站下载安装包。

安装后,在终端(Windows CMD/PowerShell, macOS/Linux Terminal)输入java -versionjavac -version验证。你应该能看到类似openjdk version "17.0.10"的输出。

2. 构建工具:Maven 或 Gradle这是项目管理的核心工具,负责依赖管理、编译、打包等。Spring Boot官方同时支持两者。对于新手,我推荐Maven,因为它的配置(pom.xml)是XML格式,结构直观,网上资料也最丰富。Gradle使用基于Groovy或Kotlin的DSL,更灵活强大,但学习曲线稍陡。

安装Maven后,同样在终端用mvn -v验证。你需要配置Maven的本地仓库路径(默认在用户目录下的.m2文件夹)和镜像源(国内推荐使用阿里云镜像以加速依赖下载)。这通常通过修改Maven安装目录下conf/settings.xml文件实现。

3. 集成开发环境 (IDE)写Java不用IDE就像打仗不带枪。两大主流选择:

  • IntelliJ IDEA (Ultimate版):业界公认的Java开发神器,对Spring Boot的支持是“开箱即用”级别的,智能提示、代码生成、图形化启动配置都极其强大。社区版(免费)对Spring Boot支持有限,开发Spring Boot建议使用Ultimate版(可申请学生许可或购买)。
  • Eclipse / Spring Tools Suite (STS):老牌IDE,STS是Eclipse针对Spring开发的定制版,完全免费且对Spring支持很好。但整体流畅度和智能感知略逊于IDEA。

本教程后续演示将基于IntelliJ IDEA Ultimate进行,因为它的高效能极大提升学习和开发体验。

2.2 使用Spring Initializr:三分钟创建项目骨架

Spring官方提供了在线工具Spring Initializr,这是创建Spring Boot项目最标准、最推荐的方式,避免了手动创建目录结构的繁琐。

  1. 访问 https://start.spring.io 。
  2. Project: 选择Maven Project(如果你选Gradle,后续命令需相应调整)。
  3. Language: 选择Java
  4. Spring Boot: 选择当前最新的稳定版(如3.2.5)。新手建议不要选快照版(SNAPSHOT)。
  5. Project Metadata:
    • Group: 通常填写公司或组织域名的反写,例如com.example
    • Artifact: 项目名称,例如demo
    • Name: 同上,可自动填充。
    • Description: 项目描述,可选。
    • Package name: 包名,通常是Group+Artifact,如com.example.demo
    • Packaging: 选择Jar(这是Spring Boot推荐的方式)。
    • Java: 选择你安装的JDK版本,如17
  6. Dependencies: 这是关键!点击“ADD DEPENDENCIES”按钮,搜索并添加:
    • Spring Web: 这是构建Web应用(包括RESTful API)的核心起步依赖。
    • Spring Boot DevTools: 强烈建议添加。它提供热重启功能,修改代码后无需手动重启应用,提升开发效率。
    • Lombok: 同样强烈建议。通过注解自动生成Getter、Setter、构造函数等样板代码,让实体类非常简洁。需要在IDE中安装Lombok插件。
  7. 点击右下角的GENERATE按钮,下载一个ZIP压缩包。

2.3 在IDEA中打开并运行项目

  1. 解压下载的ZIP包。
  2. 打开IntelliJ IDEA,选择Open,找到并选中解压后的项目文件夹(包含pom.xml的根目录)。
  3. IDEA会自动识别为Maven项目并开始下载依赖(观察底部进度条)。首次加载可能需要几分钟,取决于网络。
  4. 依赖加载完成后,展开项目结构,找到主应用类:src/main/java/com/example/demo/DemoApplication.java。这个类上有一个@SpringBootApplication注解。
  5. 直接右键点击这个类,选择Run ‘DemoApplication.main()‘
  6. 观察控制台日志。如果看到类似以下的输出,恭喜你,Spring Boot应用启动成功了!

. ____ _ __ _ _ /\ /'__ _()__ __ _ \ \ \
( ( )_
_ | '_ | '| | '/` | \ \ \
\/)| |)| | | | | || (| | ) ) ) ) ' |
| .__|| ||| |_, | / / / / =========||==============|/=//// :: Spring Boot :: (v3.2.5)

2024-XX-XXTXX:XX:XX.XXX+08:00 INFO 12345 --- [ main] com.example.demo.DemoApplication : Starting DemoApplication using Java 17.0.10 on ... 2024-XX-XXTXX:XX:XX.XXX+08:00 INFO 12345 --- [ main] com.example.demo.DemoApplication : No active profile set, falling back to 1 default profile: "default" 2024-XX-XXTXX:XX:XX.XXX+08:00 INFO 12345 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http) 2024-XX-XXTXX:XX:XX.XXX+08:00 INFO 12345 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2024-XX-XXTXX:XX:XX.XXX+08:00 INFO 12345 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.20] 2024-XX-XXTXX:XX:XX.XXX+08:00 INFO 12345 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2024-XX-XXTXX:XX:XX.XXX+08:00 INFO 12345 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1234 ms 2024-XX-XXTXX:XX:XX.XXX+08:00 INFO 12345 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '' 2024-XX-XXTXX:XX:XX.XXX+08:00 INFO 12345 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 2.345 seconds (process running for 2.567)

注意日志中的 `Tomcat started on port 8080`,说明内嵌的Tomcat服务器已经在8080端口启动了。 ### 2.4 编写第一个REST接口 现在,让我们让这个应用“说句话”。我们将创建一个简单的REST控制器。 1. 在 `src/main/java/com/example/demo` 包下,新建一个Java类,命名为 `HelloController`。 2. 输入以下代码: ```java package com.example.demo; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController // 这是一个组合注解,包含了@Controller和@ResponseBody,表明这个类是一个控制器,且其方法返回值直接写入HTTP响应体。 public class HelloController { @GetMapping("/hello") // 处理HTTP GET请求到“/hello”这个路径。 public String sayHello() { return "Hello, Spring Boot!"; } } ``` 3. 由于我们之前添加了 `Spring Boot DevTools`,IDEA通常会自动进行热重启。如果你修改了代码,可以手动保存(Ctrl+S),观察控制台,DevTools会触发应用快速重启(比冷启动快得多)。 4. 打开你的浏览器,访问 `http://localhost:8080/hello`。你应该能看到页面上显示着 `Hello, Spring Boot!`。 至此,你的第一个Spring Boot应用已经成功运行并对外提供了服务!这个过程是不是比想象中简单得多?这就是Spring Boot“开箱即用”的魅力。 ## 3. 项目结构深度解析:每个文件夹和文件的作用 当你通过Initializr创建项目后,会得到一个标准的目录结构。理解这个结构是成为合格Spring Boot开发者的第一步。我们来逐一拆解:

demo/ ├── src/ │ ├── main/ │ │ ├── java/ # 主要的Java源代码目录 │ │ │ └── com/ │ │ │ └── example/ │ │ │ └── demo/ │ │ │ ├── DemoApplication.java # Spring Boot主启动类 │ │ │ └── (其他业务包,如controller, service, repository等) │ │ └── resources/ # 资源文件目录 │ │ ├── static/ # 存放静态资源(CSS, JS, 图片等),可通过/static/xxx.css直接访问 │ │ ├── templates/ # 存放模板文件(Thymeleaf, FreeMarker等),用于服务端渲染页面 │ │ └── application.properties # 主配置文件(或使用application.yml) │ └── test/ # 测试代码目录,结构与main类似 │ └── java/ │ └── com/ │ └── example/ │ └── demo/ │ └── DemoApplicationTests.java # 自动生成的测试类 └── pom.xml # Maven项目对象模型文件,定义依赖、构建配置等

**核心文件详解:** 1. **`DemoApplication.java` (主启动类)** 这是整个应用的入口。`@SpringBootApplication` 注解是核心,它是一个组合注解,等价于: * `@SpringBootConfiguration`: 标记该类为配置类。 * `@EnableAutoConfiguration`: **开启自动配置**,这是Spring Boot魔力的源泉。 * `@ComponentScan`: 开启组件扫描,自动发现并注册当前包及其子包下的组件(如`@Controller`, `@Service`, `@Repository`)。 `main` 方法中通过 `SpringApplication.run()` 启动应用。**一个项目通常只有一个类标注 `@SpringBootApplication`**。 2. **`application.properties` / `application.yml` (配置文件)** 这是Spring Boot应用的“控制中心”。所有可调整的配置都在这里,例如: * **服务器端口**:`server.port=9090` (将端口改为9090) * **应用上下文路径**:`server.servlet.context-path=/api` (所有接口路径前会加上`/api`) * **数据库连接**:`spring.datasource.url=jdbc:mysql://localhost:3306/test` * **日志级别**:`logging.level.com.example.demo=DEBUG` `yml`格式采用缩进,层次更清晰,是更现代的选择。它们可以共存,但`properties`优先级高于`yml`。 3. **`pom.xml` (依赖与构建管理)** Maven的核心。重点关注: * `<parent>`: 继承了 `spring-boot-starter-parent`,这定义了Spring Boot项目的默认配置(如JDK版本、依赖版本、插件配置等),让你无需关心大量依赖的具体版本号,保证了兼容性。 * `<dependencies>`: 声明项目依赖。我们通过Initializr添加的 `spring-boot-starter-web` 就在这里。 * `<build>` 下的 `<plugins>`: 包含了 `spring-boot-maven-plugin`,这个插件至关重要,它负责将应用打包成**可执行的Fat JAR**(也叫Uber JAR),即把所有依赖的JAR包都打包进一个JAR文件中,这样你才能用 `java -jar app.jar` 来运行。 4. **包结构 (`com.example.demo` 下的子包)** 虽然没有强制规定,但遵循分层架构是良好实践,通常按功能模块划分: * `controller`: 存放控制器类,处理HTTP请求,是前后端的交互边界。使用 `@RestController` 或 `@Controller` 注解。 * `service`: 存放业务逻辑层接口和实现类,处理核心业务。使用 `@Service` 注解。 * `repository` / `dao`: 存放数据访问层接口,负责与数据库交互。使用 `@Repository` 注解。如果使用Spring Data JPA,接口只需继承 `JpaRepository` 即可获得基础的CRUD方法。 * `entity` / `model` / `domain`: 存放实体类(与数据库表映射的Java对象)或数据传输对象(DTO)。通常使用 `@Entity`(JPA)或 `@Table`(MyBatis)注解。 * `config`: 存放自定义的配置类,用于定义一些Spring容器管理的Bean。 * `util`: 存放工具类。 * `exception`: 存放自定义的异常类。 > 提示:这些注解(`@Controller`, `@Service`, `@Repository`, `@Component`)在Spring中统称为“原型注解”,它们的作用都是告诉Spring:“请把我这个类实例化并管理起来,成为一个Bean”。它们的区别更多是语义上的,便于代码分层和理解。`@RestController` 是 `@Controller` 的特化,专用于REST API。 ## 4. 自动配置与起步依赖:Spring Boot的魔法引擎 前面我们提到了Spring Boot的“约定大于配置”和“开箱即用”,这背后的两大核心技术支柱就是 **起步依赖 (Starters)** 和 **自动配置 (Auto-Configuration)**。理解它们,你才算真正理解了Spring Boot。 ### 4.1 起步依赖:一站式的依赖管理包 在传统的Spring项目中,如果你想开发一个Web应用,需要在`pom.xml`里手动添加:Spring MVC、Jackson(JSON处理)、Tomcat(或其他Servlet容器)等依赖,并且必须确保它们之间的版本兼容。这非常容易出错。 Spring Boot的起步依赖将一组功能相关的依赖“打包”在一起。例如,当你声明依赖 `spring-boot-starter-web` 时,你实际上引入了: * `spring-boot-starter` (核心启动器,包含自动配置、日志、YAML支持) * `spring-boot-starter-json` (Jackson,用于JSON序列化/反序列化) * `spring-boot-starter-tomcat` (内嵌Tomcat服务器) * `spring-webmvc` (Spring MVC框架) * ... 以及其他相关传递依赖。 这些依赖的版本由 `spring-boot-starter-parent` 统一管理,保证了它们能完美协同工作。你需要什么功能,就引入对应的 `spring-boot-starter-*`,无需再操心具体的依赖项和版本冲突。这极大地简化了依赖管理。 ### 4.2 自动配置:基于条件的“智能”装配 这是Spring Boot最精妙的部分。自动配置的核心是 `@EnableAutoConfiguration` 注解(已包含在 `@SpringBootApplication` 中)。它的工作原理是: 1. **扫描类路径**:Spring Boot启动时,会扫描类路径下存在的JAR包。 2. **读取 `spring.factories`**:在 `spring-boot-autoconfigure` 这个核心JAR包的 `META-INF` 目录下,有一个 `spring.factories` 文件。这个文件里定义了大量 **自动配置类** 的全限定名,例如 `org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration`。 3. **条件化加载**:这些自动配置类上通常带有 `@ConditionalOnXxx` 系列注解(条件注解)。Spring Boot会根据当前应用的环境(类路径、已存在的Bean、配置文件属性等)来判断是否应该加载这个配置类。 * `@ConditionalOnClass`:当类路径下存在某个类时才生效。例如,只有当你引入了 `spring-boot-starter-web`(包含了Tomcat相关的类),`TomcatServletWebServerFactoryAutoConfiguration` 才会生效,从而自动配置内嵌Tomcat。 * `@ConditionalOnMissingBean`:当Spring容器中不存在某个Bean时才生效。这给了开发者**覆盖默认配置**的机会。如果你想自定义某个Bean(比如定制的 `DataSource`),只需要自己定义一个并注入Spring容器,Spring Boot的默认配置就会因为此条件不满足而跳过。 * `@ConditionalOnProperty`:当配置文件中某个属性为特定值时才生效。 **一个生动的例子:** 当你引入了 `spring-boot-starter-web`,类路径下就有了Spring MVC和Tomcat的相关类。`DispatcherServletAutoConfiguration`(配置Spring MVC的核心DispatcherServlet)和 `TomcatServletWebServerFactoryAutoConfiguration`(配置内嵌Tomcat服务器)的条件得到满足,它们被自动加载。于是,一个完整的Web应用环境就自动搭建好了,包括DispatcherServlet、视图解析器、消息转换器等,并且Tomcat在8080端口启动。 **如何查看生效的自动配置?** 在启动日志中,如果你将日志级别调整为 `DEBUG`(在`application.properties`中设置 `debug=true` 或 `logging.level.root=DEBUG`),启动时会打印一份“自动配置报告”,清晰地列出哪些配置类生效了(Positive matches),哪些没有生效(Negative matches)及其原因。这是调试自动配置问题的利器。 > 实操心得:自动配置并不意味着“黑盒”。当你需要定制化行为时,第一选择是查阅官方文档,看是否有现成的配置属性(以 `spring.*` 开头)可以修改。如果配置属性无法满足,再考虑通过 `@Bean` 注解提供自己的Bean实现来覆盖默认配置。理解自动配置的条件机制,能让你在遇到问题时快速定位。 ## 5. 配置文件详解:Properties vs. YAML与多环境配置 配置文件是应用与运行环境之间的桥梁。Spring Boot支持两种格式:`.properties`(传统)和 `.yml` / `.yaml`(YAML Ain‘t Markup Language,更现代)。我们来详细对比和讲解。 ### 5.1 Properties vs. YAML 格式对比 **Properties 格式 (`application.properties`)** ```properties # 键值对形式,使用点(.)分隔层级 server.port=9090 server.servlet.context-path=/api spring.datasource.url=jdbc:mysql://localhost:3306/mydb spring.datasource.username=root spring.datasource.password=secret spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver logging.level.com.example.demo=DEBUG
  • 优点:简单直观,编辑器和IDE支持好,无需担心缩进问题。
  • 缺点:对于复杂的、有层次结构的配置(如List、Map),书写起来冗长且不直观。

YAML 格式 (application.yml)

# 使用缩进表示层级关系,冒号后需有空格 server: port: 9090 servlet: context-path: /api spring: datasource: url: jdbc:mysql://localhost:3306/mydb username: root password: secret driver-class-name: com.mysql.cj.jdbc.Driver logging: level: com.example.demo: DEBUG # YAML 可以更优雅地表示数组/列表 myapp: servers: - dev.example.com - prod.example.com users: admin: name: Admin User roles: - USER - ADMIN
  • 优点:结构清晰,易于阅读,特别适合表达复杂、有层次的数据。在Spring Cloud等微服务配置中几乎是标配。
  • 缺点:对缩进极其敏感,缩进错误会导致解析失败。需要编辑器有较好的YAML支持。

个人建议:对于新项目,尤其是可能涉及复杂配置或微服务的项目,优先使用YAML格式。它的可读性优势在项目后期维护时非常明显。IDEA对YAML的缩进提示和校验做得很好。

5.2 配置的加载顺序与优先级

Spring Boot会从多个位置加载application配置文件,并且后加载的配置会覆盖先加载的配置,优先级从低到高如下:

  1. 项目根目录下的/config子目录(最高优先级)
  2. 项目根目录
  3. Classpath下的/config
  4. Classpath根目录(最低优先级)

此外,还可以通过命令行参数--spring.config.location指定外部配置文件,或者使用SPRING_APPLICATION_JSON环境变量传递配置。命令行参数的优先级最高

这个特性非常有用。例如,你可以在src/main/resources/application.yml中存放开发环境的通用配置(如数据库连接池大小、日志级别),然后在项目根目录下放一个application-prod.yml文件,里面配置生产环境的数据库地址、密码等敏感信息。这个文件不应该提交到Git(通过.gitignore忽略),从而保证生产环境配置的安全。

5.3 多环境配置(Profile)

这是实际开发中最常用的功能。我们通常有开发(dev)、测试(test)、生产(prod)等不同环境,每个环境的数据库、Redis地址、日志级别等都不同。

Spring Boot使用spring.profiles.active属性来指定激活哪个环境。

操作步骤:

  1. 创建Profile-specific配置文件:命名规则为application-{profile}.yml

    • application-dev.yml(开发环境)
    • application-test.yml(测试环境)
    • application-prod.yml(生产环境)
  2. 编写各环境配置application.yml(主配置文件,存放所有环境共享的配置)

    spring: application: name: my-demo-app # 在这里可以定义一些默认配置

    application-dev.yml

    server: port: 8080 logging: level: root: INFO com.example.demo: DEBUG spring: datasource: url: jdbc:h2:mem:testdb # 开发环境使用内存数据库H2 driver-class-name: org.h2.Driver username: sa password:

    application-prod.yml

    server: port: 80 logging: level: root: WARN spring: datasource: url: jdbc:mysql://prod-db-host:3306/prod_db driver-class-name: com.mysql.cj.jdbc.Driver username: prod_user password: ${DB_PASSWORD} # 使用环境变量,更安全
  3. 激活Profile

    • application.yml中指定默认激活(不推荐用于生产):
      spring: profiles: active: dev
    • 通过命令行参数激活(推荐,灵活):
      java -jar myapp.jar --spring.profiles.active=prod
    • 通过系统环境变量激活
      export SPRING_PROFILES_ACTIVE=prod java -jar myapp.jar
    • 在IDEA运行配置中激活:编辑DemoApplication的运行配置,在Program arguments里添加--spring.profiles.active=dev

避坑指南:配置属性名中的短横线(-)和下划线(_)是等价的,Spring Boot会自动将spring.datasource.urlspring.datasource_url视为同一个属性。但在YAML中,推荐使用冒号加缩进;在Properties中,使用点号。另外,使用@Value注解或@ConfigurationProperties绑定配置时,属性名需要与配置文件中的键保持一致(支持松绑定,即驼峰、短横线、下划线可互换)。

6. 开发效率神器:Spring Boot DevTools与Lombok实战

在入门阶段,有两样工具能极大提升你的开发体验和代码简洁度,它们就是我们在创建项目时勾选的Spring Boot DevToolsLombok

6.1 Spring Boot DevTools:告别手动重启

传统开发中,每次修改Java代码或配置文件,都需要手动停止应用,然后再启动。这个过程耗时且打断思路。DevTools提供了自动重启功能。

工作原理:DevTools会监控classpath路径下的文件变动。当检测到变化时(如你保存了一个.java文件),它会触发一个“快速重启”。这个重启并非完全冷启动JVM,而是使用两个类加载器:

  • Base ClassLoader:加载那些不会变化的库(如第三方JAR包)。
  • Restart ClassLoader:加载你正在开发的代码。 重启时,只重启Restart ClassLoader,速度非常快。

如何使用

  1. 引入依赖后(Initializr已勾选),默认就已启用。
  2. 在IDEA中,确保Settings->Build, Execution, Deployment->Compiler->Build project automatically被勾选(这是自动编译的前提)。
  3. 还需要在IDEA中按Ctrl+Shift+A(Mac:Cmd+Shift+A),搜索Registry...,找到并勾选compiler.automake.allow.when.app.running
  4. 现在,当你修改代码并保存(Ctrl+S)后,IDEA会自动编译,DevTools检测到classpath变化,应用就会在1-2秒内快速重启。控制台会显示Restarted Main的日志。

注意事项

  • DevTools仅用于开发环境。打包生产JAR时,它会被自动排除(因为spring-boot-devtools依赖的scope默认是runtime,且Spring Boot的Maven/Gradle插件在打包时会排除它)。
  • 静态资源(/static,/public目录下的文件)的修改默认会触发重启。如果你想实现静态资源的热加载(无需重启,浏览器刷新即可),可以配置spring.devtools.livereload.enabled=true,并配合浏览器插件使用,但这在前后端分离项目中用处不大。
  • 某些资源的修改(如application.properties)可能需要手动触发重启。

6.2 Lombok:告别冗余的Getter/Setter/Constructor

在Java中,为实体类的每个字段编写Getter、Setter、toString、equals/hashCode、构造函数是非常重复且无趣的“样板代码”。Lombok通过在编译时使用注解处理器自动生成这些代码,让你的实体类保持简洁。

常用注解

  • @Data:一个组合注解,相当于@Getter+@Setter+@ToString+@EqualsAndHashCode+@RequiredArgsConstructor。这是最常用的注解,用于普通的POJO。
  • @Getter/@Setter:分别为所有字段或指定字段生成Getter/Setter。
  • @NoArgsConstructor:生成无参构造函数。
  • @AllArgsConstructor:生成全参构造函数。
  • @RequiredArgsConstructor:为所有final字段或标记了@NonNull的字段生成构造函数。
  • @ToString:生成toString方法。
  • @EqualsAndHashCode:生成equalshashCode方法。
  • @Slf4j:在类中自动注入一个日志对象log,可以直接使用log.info(...),无需再写private static final Logger log = LoggerFactory.getLogger(Xxx.class);

实战示例: 没有Lombok的User类:

public class User { private Long id; private String username; private String email; // 省略十几个字段的Getter/Setter/Constructor/toString... }

使用Lombok的User类:

import lombok.Data; import lombok.NoArgsConstructor; import lombok.AllArgsConstructor; @Data // 自动生成Getter, Setter, toString, equals, hashCode @NoArgsConstructor // 无参构造 @AllArgsConstructor // 全参构造 public class User { private Long id; private String username; private String email; // ... 其他字段 // 完了!没有其他代码了。 }

编译后,Lombok会为你生成所有必要的方法。在IDEA中,你可以通过Structure视图或反编译.class文件来查看生成的方法。

IDEA中安装Lombok插件: 这是必须的一步!否则IDEA无法识别Lombok注解,会报错“找不到getter/setter”。在IDEA的插件市场(Settings->Plugins)中搜索Lombok并安装,然后重启IDEA。

踩坑实录:Lombok虽然方便,但在团队协作中需要确保所有成员都安装了插件。另外,过度使用@Data在一些复杂继承关系的类中可能会导致equalshashCode方法不符合预期(可以使用@EqualsAndHashCode(callSuper = true)来解决)。对于简单的数据传输对象(DTO)或实体类,Lombok是绝佳选择。

7. 打包与部署:从开发环境到可运行JAR

我们开发的应用最终需要部署到服务器上运行。Spring Boot的打包方式极其简单,这要归功于spring-boot-maven-plugin

7.1 使用Maven打包

在项目根目录(pom.xml所在目录)打开终端,执行:

mvn clean package

这条命令会:

  1. clean:清理之前编译生成的target目录。
  2. package:执行编译、测试(如果跳过测试可加-DskipTests),并将项目打包。

打包完成后,在target目录下,你会找到两个主要的文件:

  • demo-0.0.1-SNAPSHOT.jar:这是普通的JAR包,只包含你项目编译后的类文件,不包含依赖。
  • demo-0.0.1-SNAPSHOT.jar.original:这是Maven标准打包生成的普通JAR。
  • demo-0.0.1-SNAPSHOT.jar(较大的那个):这才是Spring Boot生成的Fat JAR (可执行JAR)。它包含了所有依赖的第三方库和你自己的代码。

7.2 运行Fat JAR

直接使用Java命令运行即可:

java -jar target/demo-0.0.1-SNAPSHOT.jar

应用就会像在IDEA中一样启动。你可以通过--server.port=9090--spring.profiles.active=prod来传递运行参数。

7.3 打包时排除DevTools和Lombok

我们之前提到,DevTools和Lombok是开发时工具,不应该被打包到生产环境中。幸运的是,Spring Boot的Maven插件和依赖Scope已经帮我们处理好了。

  • DevTools:在pom.xml中,它的依赖scope是runtime,并且被标记为optionalspring-boot-maven-plugin在打包时会自动排除标记为optional的依赖。所以生产JAR中不会有DevTools。
  • Lombok:它的依赖scope是provided(意味着它由运行环境提供,编译时需要,打包时不需要)。因为Lombok是编译时注解处理器,它的代码在运行时并不需要。所以它也不会被打进生产JAR。

你可以通过解压Fat JAR来验证:jar tf target/demo-0.0.1-SNAPSHOT.jar | grep devtools... | grep lombok,应该找不到相关类。

7.4 分离依赖库以加速构建(可选)

Fat JAR虽然部署简单,但每次打包都要把所有依赖重新打进JAR,即使依赖没变,这在大项目中会浪费一些时间。一种优化策略是将依赖JAR包外置。

pom.xmlspring-boot-maven-plugin配置中,可以添加如下配置:

<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <layout>ZIP</layout> <!-- 或者使用 DIR 布局 --> </configuration> </plugin> </plugins> </build>

然后执行mvn clean package,在target目录下会生成一个.zip文件(或目录结构)。解压后,你会看到:

  • demo-0.0.1-SNAPSHOT.jar(仅包含应用代码,很小)
  • lib/目录 (包含所有依赖JAR)
  • bin/目录 (包含启动脚本,用于Linux/Windows)

运行方式变为执行bin/目录下的脚本。这种方式在持续集成/持续部署(CI/CD)流水线中,如果依赖不变,可以缓存lib目录,从而加速打包过程。但对于新手和小型项目,标准的Fat JAR方式更简单直接。

部署小技巧:在生产服务器上,建议使用像systemd(Linux) 或Supervisor这样的进程管理工具来管理Spring Boot应用,而不是简单地用nohup java -jar ... &。这样可以实现应用的自启动、崩溃重启、日志管理等功能,让运维更规范。另外,确保服务器上安装了正确版本的JDK。