SpringBoot 学习

什么是 SpringBoot

SpringBoot 是基于 Spring 生态的开源框架 ,旨在简化 Spring 应用的初始化搭建开发配置 。它通过约定大于配置的理念,提供快速构建生产级应用的解决方案,显著降低开发者对 XML 配置和依赖管理的负担。

特点:

  • 快速创建独立 Spring 应用。

  • 直接嵌入 Tomcat、Jetty or Undertow(无需部署 war 包)(Servlet容器)。

  • 提供可选的 starter,简化应用整合。

  • 按需自动配置 Spring 以及第三方库。

  • 提供生产级特性:如 监控指标、健康检查、外部化配置等。

  • 无代码生成、无xml。

核心特性

  1. 自动配置
    • 原理 :根据项目依赖的 JAR 包(如 spring-boot-starter-data-jpa),自动推断并配置所需的 Bean(如数据源、事务管理器等)。
    • 示例 :引入 spring-boot-starter-web 后,自动配置内嵌 Tomcat、Spring MVC 和 Jackson 库。
    • 自定义 :通过 application.properties@Configuration 类覆盖默认配置。
  2. 起步依赖
    • 作用 :将功能相关的依赖打包成一组(如 spring-boot-starter-data-redis),解决版本冲突问题。
    • 本质 :基于 Maven/Gradle 的依赖传递机制,简化 pom.xmlbuild.gradle 配置。
  3. 内嵌服务器
    • 支持服务器:Tomcat(默认)、Jetty、Undertow。
    • 优势 :无需部署 WAR 包到外部服务器,直接通过 main() 方法运行 JAR 文件。
  4. 生产就绪功能
    • 集成 Spring Boot Actuator :提供监控端点(如 /health, /metrics),支持应用性能追踪和健康检查。
    • 外部化配置:支持多环境配置(如 application-dev.yml, application-prod.yml)。

为什么会出现 SpringBoot

  1. 传统 Spring 的痛点
    • 繁琐的 XML 配置和重复的注解配置。
    • 依赖版本冲突频繁,需手动协调。
    • 部署依赖外部服务器,开发效率低。
  2. Spring Boot 的优化
    • 零 XML 配置,通过注解和默认配置简化开发。
    • 起步依赖统一管理版本,避免冲突。
    • 内嵌服务器实现"一键启动"。

核心组件

  1. 启动流程
java 复制代码
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
  • @SpringBootApplication 组合了三个注解:
    • @SpringBootConfiguration:标识为配置类。
    • @EnableAutoConfiguration:启用自动配置。
    • @ComponentScan:扫描当前包及子包的组件。
  • SpringApplication.run() 启动内嵌服务器,加载自动配置类。
  1. 条件装配(Conditional)

Spring Boot 通过 @ConditionalOnClass@ConditionalOnMissingBean 等注解,动态判断是否装配某个 Bean。例如:

  • 当类路径存在 DataSource.class 时,才自动配置数据源。
  • 当容器中无自定义的 DataSource Bean 时,使用默认配置。

应用场景

  1. 快速构建 RESTful API

    使用 @RestControllerspring-boot-starter-web,几分钟内完成 API 开发与测试。

  2. 微服务开发

    作为 Spring Cloud 微服务架构的基础,轻松整合服务注册(Eureka)、配置中心(Config)等功能。

  3. 批处理任务

    结合 spring-boot-starter-batch 实现定时任务或大数据处理。

  4. 数据驱动应用

    整合 JPA(spring-boot-starter-data-jpa)或 MyBatis,快速操作数据库。

SpringBoot 与 Spring 关系

对比项 Spring Spring Boot
定位 基础框架,提供 IOC、AOP、事务管理等核心功能 Spring 的扩展,简化配置和开发流程
配置方式 需手动配置 XML 或 Java Config 约定大于配置,自动装配为主
依赖管理 需开发者自行解决依赖冲突 通过 Starter 管理依赖和版本
部署 依赖外部服务器(如 Tomcat) 内嵌服务器,打包为可执行 JAR

优缺点

  • 优点
    • 快速上手,适合新手和快速原型开发。
    • 生态丰富,与 Spring Cloud、Spring Security 无缝整合。
    • 社区活跃,文档完善。
  • 缺点
    • 过度依赖自动配置,可能隐藏底层细节(需理解原理以调试复杂问题)。
    • 大型项目可能需要自定义配置覆盖默认行为。

总结

简化开发,简化配置,简化整合,简化部署,简化监控,简化运维。

快速开始

场景:快速开发一个 SpringBoot Web 工程。

快速搭建一个 SpringBoot 项目有两种方式:

SpringBoot 3 要求的 jdk 最低版本为 17。

创建 Maven 项目,转成 SpringBoot 项目

步骤:

  1. 创建一个 Maven 项目。
  2. pom.xml 文件导入一个父工程(SpringBoot 项目)。
xml 复制代码
<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>3.4.4</version>
</parent>
  1. 导入 SpringBoot Web 依赖:
xml 复制代码
<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
</dependencies>

这个依赖不需要指定版本号

  1. 创建 SpringBoot 主程序:
java 复制代码
@SpringBootApplication
public class MainApplication {

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

}

要在类上添加注解 @SpringBootApplication

  1. 在主程序所在包下创建 controller 层:
java 复制代码
@RestController
public class HelloController {

	@GetMapping("/hello")
	public String hello(){
		return "Hello SpringBoot";
	}

}
  1. 启动项目,访问 localhost:8080/hello 进行测试,出现 hello SpringBoot 成功。

如果想要打成 jar 包,需要在 pom.xml 导入插件依赖:

xml 复制代码
<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
		</plugin>
	</plugins>
</build>

使用 Spring 初始化工具直接创建 SpringBoot 项目

  1. 使用初始化工具创建 SpringBoot 项目:

新版 idea 是 Spring Boot,老版是 Spring Initializr。

项目名自行取即可。

  1. 点 next 下一步,选中 Web 模块。

选中模块后 SpringBoot 项目会自动导入相应的模块。

创建好的项目可以看到 pom.xml 和主程序已经编写好了,我们只需要编写 controller 层即可。

pom.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.4.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.yigongsui</groupId>
    <artifactId>springboot-study</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-study</name>
    <description>springboot-study</description>
    <url/>
    <licenses>
        <license/>
    </licenses>
    <developers>
        <developer/>
    </developers>
    <scm>
        <connection/>
        <developerConnection/>
        <tag/>
        <url/>
    </scm>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <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>

主程序:

java 复制代码
package com.yigongsui.springbootstudy;

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

@SpringBootApplication
public class SpringbootStudyApplication {

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

}

之后步骤同上面。

简单介绍自动创建的 pom.xml 各标签信息(了解即可)

  1. <url>(根级别):项目基础信息。

    • 表示项目主页 URL。
    • 示例:<url>https://github.com/yourname/project</url>
    • 用于生成项目文档链接。
  2. <license>:许可证信息,需包含:

    • <name>:许可证名称(如 MIT License)。
    • <url>:许可证文本地址。
    • <distribution>:分发方式(通常为"repo")。
  3. <developers>:开发者信息:

    • 支持多开发者声明。
    • 包含开发者身份识别和联系方式。
    xml 复制代码
    <developers>
        <developer>
            <id>dev001</id>
            <name>张三</name>
            <email>[email protected]</email>
            <roles>
                <role>架构师</role>
            </roles>
        </developer>
    </developers>
  4. <scm>:版本控制配置

    • connection:只读访问路径。
    • developerConnection:开发者提交权限路径。
    • 协议差异:
      • https:匿名只读访问。
      • ssh:需认证的读写访问。
    • <tag> 标记当前代码版本。

starter 概述

定义与作用

  1. 简化依赖管理

    SpringBoot starter 是预定义的依赖描述模板(pom.xmlbuild.gradle 片段),通过约定大于配置原则,将特定功能所需的多组依赖库整合为单一依赖项,核心原理是依赖传递。

    示例:引入 spring-boot-starter-web 会自动包含 Spring MVC、Tomcat、Jackson 等 Web 开发基础依赖。

  2. 自动配置机制

    每个 starter 包含一个 spring.factories 文件,声明了关联的自动配置类(如 WebMvcAutoConfiguration)。SpringBoot启动时通过 @EnableAutoConfiguration 扫描这些配置类,根据条件注解 (如 @ConditionalOnClass)动态创建 Bean。

核心原理

  1. 依赖传递逻辑

    xml 复制代码
    <!-- 引入starter-web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    实际会传递依赖:

    • spring-boot-starter(核心启动器)
    • spring-boot-starter-json
    • spring-webmvc
    • tomcat-embed-core
  2. 自动配置流程

    java 复制代码
    @Configuration
    @ConditionalOnClass({ Servlet.class, DispatcherServlet.class })
    @AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
    public class WebMvcAutoConfiguration {
        // 自动配置DispatcherServlet、视图解析器等组件
    }

常见 starter 分类

类型 示例 功能描述
官方标准 starter spring-boot-starter-data-jpa 集成 JPA 与 Hibernate
技术整合 starter spring-boot-starter-security 添加安全认证与授权功能
第三方 starter mybatis-spring-boot-starter MyBatis orm 框架集成

自定义 Starter 开发步骤

  1. 创建模块结构

    复制代码
    my-starter/
    ├── src/main/java
    │   └── com/example/autoconfigure
    │       ├── MyServiceAutoConfiguration.java  // 自动配置类
    │       └── MyServiceProperties.java         // 配置属性绑定
    └── src/main/resources
        └── META-INF
            └── spring.factories                 // 注册自动配置
  2. 实现自动配置类

    java 复制代码
    @Configuration
    @EnableConfigurationProperties(MyServiceProperties.class)
    @ConditionalOnClass(MyService.class)
    public class MyServiceAutoConfiguration {
        @Bean
        @ConditionalOnMissingBean
        public MyService myService(MyServiceProperties properties) {
            return new MyService(properties.getConfig());
        }
    }
  3. 配置属性绑定

    java 复制代码
    @ConfigurationProperties(prefix = "my.service")
    public class MyServiceProperties {
        private String config = "default";
        // getters & setters
    }
  4. 注册自动配置

    spring.factories内容:

    factories 复制代码
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    com.example.autoconfigure.MyServiceAutoConfiguration

最佳实践与注意事项

  1. 依赖范围控制

    使用 <optional>true</optional> 标记非必要传递依赖,避免污染用户项目的依赖树。

  2. 条件注解使用

    合理应用 @ConditionalOnProperty@ConditionalOnWebApplication 等注解,确保配置仅在满足条件时生效。

  3. 调试技巧

    启动时添加 --debug 参数可查看自动配置报告。

通过 starter 机制,SpringBoot 实现了开箱即用的体验,开发者无需手动管理复杂依赖关系与 xml 配置,显著提升了开发效率。

SpringBoot 依赖管理机制

SpringBoot 通过统一版本管理模块化 Starter 设计实现高效的依赖管理:

  1. 版本管理

    • 维护了 spring-boot-dependencies BOM(Bill of Materials),预定义了所有官方支持的依赖版本

    • 开发者无需手动指定依赖版本号,例如:

      xml 复制代码
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
          <!-- 无需写<version> -->
      </dependency>
    • 所有 Starter 的版本由 SpringBoot 父 POM 统一控制。

  2. Starter 设计模式

    • 每个 Starter 是一个功能聚合包,例如:
      • spring-boot-starter-web:聚合 Spring MVC + Tomcat + JSON 处理等。
      • spring-boot-starter-data-jpa:聚合 Hibernate + Spring Data JPA。
    • Starter 间通过 META-INF/spring.provides 声明依赖关系。
    • Starter 命名规则:
      • 官方命名:spring-boot-starter-{功能模块},例如 spring-boot-starter-web
      • 第三方:{技术名称}-spring-boot-starter,例如 mybatis-spring-boot-starter

依赖管理实现方式

  1. 继承父项目 spring-boot-starter-parent(推荐,就是快速开始的第一个项目)
xml 复制代码
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.1.0</version>
</parent>
  • 自动获得:
    • 默认 JDK 版本(Java 17)
    • 资源文件编码(UTF-8)
    • 依赖管理(dependencyManagement
  1. 导入 BOM(非继承场景)
xml 复制代码
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>3.1.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

版本覆盖机制

当需要自定义依赖版本时:

xml 复制代码
<properties>
    <mysql.version>8.0.33</mysql.version> <!-- 覆盖Spring Boot默认的MySQL驱动版本 -->
</properties>
  • 优先级:项目指定版本 > BOM版本
  • 风险提示:覆盖版本可能导致兼容性问题

依赖排除技术

处理冲突依赖的典型场景,例如 Web 模块排除 Tomcat:

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
  • 此时可手动添加其他 Servlet 容器依赖(如 Jetty)

自动配置联动

依赖管理与自动配置的协同工作:

  1. 当引入 spring-boot-starter-data-redis 时:
    • 自动加入 Jedis、Lettuce 客户端。
    • 自动配置 RedisTemplate Bean。
  2. 条件化配置原理:
    • 通过 @ConditionalOnClass 检测类路径是否存在特定类。
    • 示例:当存在 DataSource.class 时,自动配置数据库连接池。

优势总结

特性 传统 Spring 项目 SpringBoot 项目
依赖版本管理 手动维护各依赖版本 统一版本仲裁
功能模块集成 需逐个添加相关依赖 通过 Starter 一键集成
配置复杂度 需要显式配置 Bean 基于依赖的自动配置
启动速度 较慢(需加载所有配置) 更快(条件化配置按需加载)

SpringBoot 自动配置机制

SpringBoot 的自动配置是其核心特性之一,通过智能推断和条件化加载 Bean 定义,大幅简化了手动配置的复杂度 ,核心是条件化加载 + 约定大于配置

核心目标

  • 零配置启动:根据项目依赖(如类路径中的 JAR 包)自动配置 Spring 应用。
  • 按需加载:仅当满足特定条件(如类存在、Bean 未定义等)时,才启用相关配置。
  • 可覆盖性:允许开发者通过显式配置或属性文件覆盖默认行为。

初步认识

自动配置

我们在编写 ssm 项目,都要自己导入相关的配置,例如 springmvc 的 DispatcherServlet 等,但在 SpringBoot 项目,则不需要导入这些配置,这是因为 SpringBoot 已经导入大量的相关配置类,我们可以通常这个代码查看 SpringBoot 都导入了哪些 bean:

java 复制代码
ConfigurableApplicationContext ioc = SpringApplication.run(SpringbootStudyApplication.class, args);
String[] names = ioc.getBeanDefinitionNames();
for (String name : names) {
  System.out.println(name);
}

可以看到,像是 DispatcherServlet 以及我们编写的 helloController 都已经导入到 IoC 容器了。

默认包扫描

在 ssm 时,我们需要在主配置类下扫描 controller 层,service 层,dao 层,这些组件才会注入到容器内,但是在 SpringBoot 中,我们并没有扫描包,这些组件也被注入了。

这是因为 SpringBoot 的主程序类的注解 @SpringBootApplication

这个注解主要由三个注解组成:@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan

会自动扫描主程序所在的包及其下面的子包

也可以自定义扫描路径:

java 复制代码
@SpringBootApplication(scanBasePackages = {"",""})
或
@ComponentScan({"",""})

默认配置值

SpringBoot 还编写了大量的默认配置属性,例如 Tomcat 启动的端口号是 8080。

  • 配置文件 的所有配置项是和某个类的对象值进行一一绑定的。

  • 绑定了配置文件中每一项值的类: 属性类

  • 比如:

    • ServerProperties 绑定了所有 Tomcat 服务器有关的配置。

    • MultipartProperties 绑定了所有文件上传相关的配置。

如果想要修改默认值,在 SpringBoot 的资源文件 application.properties 下编写:

properties 复制代码
server.port=8888

官方配置的默认值参照:官方文档

按需加载自动配置

  • 导入场景 spring-boot-starter-web

  • 场景启动器除了会导入相关功能依赖,导入一个 spring-boot-starter,是所有 starterstarter,基础核心 starter。

  • spring-boot-starter 导入了一个包 spring-boot-autoconfigure。包里面都是各种场景的 AutoConfiguration 自动配置类

  • 虽然全场景的自动配置都在 spring-boot-autoconfigure 这个包,但是不是全都开启的。

  • 导入哪个场景就开启哪个自动配置。

实现原理与关键组件

  1. @EnableAutoConfiguration 注解

    SpringBoot 应用主类上的 @SpringBootApplication 注解包含 @EnableAutoConfiguration,触发自动配置流程。

    1. 通过 AutoConfigurationImportSelector 类扫描并加载所有符合条件的自动配置类。
  2. spring.factories 文件

    • 自动配置类定义在 META-INF/spring.factories 文件中,键为 org.springframework.boot.autoconfigure.EnableAutoConfiguration

    • 示例:

      Properties 复制代码
      # spring-boot-autoconfigure.jar 中的 spring.factories
      org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
      org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
      org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
  3. 条件化注解(Conditional Annotations)

    自动配置类通过条件注解控制是否生效,优先级从高到低如下:

    条件注解 作用
    @ConditionalOnClass 类路径中存在指定类时生效
    @ConditionalOnMissingBean 容器中不存在指定 Bean 时生效(开发者可覆盖默认配置)
    @ConditionalOnProperty 配置文件中存在指定属性且匹配值时生效
    @ConditionalOnWebApplication 应用类型为 Web 应用时生效
    @ConditionalOnResource 类路径中存在指定资源文件时生效

    代码示例

    java 复制代码
    @Configuration
    @ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class})
    @EnableConfigurationProperties(DataSourceProperties.class)
    public class DataSourceAutoConfiguration {
        // 自动配置 DataSource
    }

自动配置的工作流程

  1. 启动阶段

    SpringBoot 启动时,AutoConfigurationImportSelector 读取所有 spring.factories 中的自动配置类。

  2. 条件过滤

    遍历所有配置类,通过条件注解过滤掉不满足条件的类(如缺少依赖类、Bean 已存在等)。

  3. Bean 注册

    将符合条件的配置类加载到 Spring 容器,生成对应的 Bean 定义。

  4. 属性绑定

    通过 @EnableConfigurationPropertiesapplication.propertiesapplication.yml 中的属性绑定到配置类。

流程细节梳理

  1. 导入starter-web:导入了 web 开发场景。

    1. 场景启动器导入了相关场景的所有依赖:starter-jsonstarter-tomcatspringmvc
    2. 每个场景启动器都引入了一个 spring-boot-starter,核心场景启动器。
    3. 核心场景启动器 引入了 spring-boot-autoconfigure包。
    4. spring-boot-autoconfigure 里面囊括了所有场景的所有配置。
    5. 只要这个包下的所有类都能生效,那么相当于 SpringBoot 官方写好的整合功能就生效了。
    6. SpringBoot 默认却扫描不到 spring-boot-autoconfigure 下写好的所有配置类 。(这些配置类 给我们做了整合操作),默认只扫描主程序所在的包
  2. 主程序@SpringBootApplication

    1. @SpringBootApplication 由三个注解组成 @SpringBootConfiguration@EnableAutoConfiguratio@ComponentScan

    2. SpringBoot 默认只能扫描自己主程序所在的包及其下面的子包,扫描不到 spring-boot-autoconfigure 包中官方写好的配置类

    3. @EnableAutoConfiguration:SpringBoot 开启自动配置的核心

      • 是由 @Import(AutoConfigurationImportSelector.class) 提供功能:批量给容器中导入组件。

      • SpringBoot 启动会默认加载142个配置类。

      • 142个配置类 来自于 spring-boot-autoconfigureMETA-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件指定的。

      • 项目启动的时候利用 @Import 批量导入组件机制把 autoconfigure 包下的142 xxxxAutoConfiguration 类导入进来(自动配置类)。

    4. 按需生效:

      • 并不是这142个自动配置类都能生效。

      • 每一个自动配置类,都有条件注解 @ConditionalOnxxx,只有条件成立,才能生效 。

  3. xxxxAutoConfiguration 自动配置类

    1. 给容器中使用@Bean 放一堆组件。

    2. 每个自动配置类 都可能有这个注解 @EnableConfigurationProperties(**ServerProperties**.class),用来把配置文件中配的指定前缀的属性值封装到 xxxProperties 属性类中。

    3. 以 Tomcat 为例:把服务器的所有配置都是以 server 开头的。配置都封装到了属性类中。

    4. 容器 中放的所有组件 的一些核心参数 ,都来自于 xxxProperties xxxProperties 都是和配置文件绑定。

    5. 只需要改配置文件的值,核心组件的底层参数都能修改

  4. 写业务,全程无需关心各种整合(底层这些整合写好了,而且也生效了)。

总结

  1. 导入 starter,就会导入 autoconfigure 包。

  2. autoconfigure 包里面有一个文件 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports,里面指定的所有启动要加载的自动配置类。

  3. @EnableAutoConfiguration 会自动的把上面文件里面写的所有自动配置类都导入进来,xxxAutoConfiguration 是有条件注解进行按需加载

  4. xxxAutoConfiguration 给容器中导入一堆组件,组件都是从 xxxProperties 中提取属性值。

  5. xxxProperties 又是和配置文件进行了绑定。

**效果:**导入 starter、修改配置文件,就能修改底层行为。

自动配置的调试与验证

  1. 查看生效的自动配置

    启动时添加 --debug 参数,输出 ConditionEvaluationReport

    bash 复制代码
    java -jar your-app.jar --debug
    • 报告中会显示:
      • Positive matches(已启用的配置)
      • Negative matches(未启用的配置及原因)
  2. 手动排除自动配置

    application.properties 中排除特定配置类:

    properties 复制代码
    spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

自动配置的典型场景

  1. 数据库配置
    • 条件 :类路径中存在 DataSource 相关类(如 HikariCP、JDBC Driver)。
    • 行为 :自动创建 DataSource Bean,并根据 spring.datasource.* 属性配置连接池。
  2. Web MVC 配置
    • 条件 :类路径中存在 spring-webmvc
    • 行为 :自动配置 DispatcherServlet、视图解析器、静态资源处理等。
  3. 缓存配置
    • 条件:类路径中存在缓存实现(如 Redis、EhCache)。
    • 行为:自动初始化缓存管理器。

自定义自动配置

  1. 编写自动配置类

    java 复制代码
    @Configuration
    @ConditionalOnClass(MyService.class) // 当 MyService 存在时生效
    @EnableConfigurationProperties(MyProperties.class) // 绑定属性
    public class MyAutoConfiguration {
        
        @Bean
        @ConditionalOnMissingBean // 容器中无 MyService 时创建
        public MyService myService(MyProperties properties) {
            return new MyService(properties.getConfig());
        }
    }
  2. 注册配置类

    src/main/resources/META-INF/spring.factories 中添加:

    properties 复制代码
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
      com.example.MyAutoConfiguration

自动配置的局限性

  1. 依赖冲突

    不同 Starter 可能引入冲突的自动配置(如多个数据源配置),需通过 @Primary@Qualifier 解决。

  2. 过度配置

    自动加载不必要的组件可能影响性能,需通过 exclude 显式排除。

  3. 版本兼容性

    第三方 Starter 的自动配置可能与 SpringBoot 版本不兼容,需注意版本匹配。

总结

Spring Boot 的自动配置通过 条件化加载 + 约定优于配置 的机制,实现了极简的项目初始化。开发者只需:

  1. 通过 Starter 引入依赖。
  2. 按需覆盖默认配置(如定义自定义 Bean 或修改属性)。
  3. 理解自动配置原理以高效调试。

这种机制在简化开发的同时,保留了高度的灵活性,是 SpringBoot 的核心竞争力之一。

常用注解介绍

核心注解 @SpringBootApplication

@SpringBootApplication 是 SpringBoot 应用的核心注解,其本质是一个组合注解(由三个关键注解构成)。

三个组合注解

@SpringBootConfiguration
  • 继承自 @Configuration

  • 标识当前类为配置类(允许通过 @Bean 定义组件)。

  • 示例:

    java 复制代码
    @Bean
    public DataSource dataSource() {
        return new HikariDataSource();
    }
@EnableAutoConfiguration
  • 启用自动配置机制(核心价值所在)。

  • 工作原理:

    • 扫描 META-INF/spring.factories 文件
    • 根据类路径依赖智能配置(如检测到 spring-boot-starter-web 自动配置 Tomcat)
  • 条件判断注解示例:

    java 复制代码
    @ConditionalOnClass(DataSource.class)
    @AutoConfigureAfter(DataSourceAutoConfiguration.class)
  • 配置排除:

    java 复制代码
    @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@ComponentScan
  • 默认扫描当前包及其子包
  • 自动注册以下注解标记的组件:
    • @Component@Service@Controller@Repository

配置参数详解

参数名称 作用描述 示例值
scanBasePackages 自定义组件扫描路径 {"com.pkg1", "com.pkg2"}
exclude 排除特定自动配置类 SecurityAutoConfiguration.class
proxyBeanMethods 控制 @Bean 方法代理行为 true(默认)/false

最佳实践

  1. 项目结构规范:主类应置于根包顶层以保证扫描范围
  2. 配置覆盖策略 :优先使用 application.properties 而非代码排除
  3. 调试技巧 :启动时添加 --debug 参数查看自动配置报告

与传统 Spring 对比

特性 SpringBoot 传统 Spring
配置方式 自动 + 注解 XML + 显式配置
依赖管理 starter POM 统一管理 手动添加依赖
部署方式 内嵌容器直接运行 需要外置容器部署

这个注解体现了 Spring Boot 的核心理念:约定大于配置,通过智能默认值大幅减少开发者的配置工作量。理解其底层机制有助于在需要深度定制时做出正确决策。

条件注解

条件注解(Conditional Annotations)是 SpringBoot 实现自动配置的核心机制,通过预定义条件控制 Bean 的创建与加载 。其本质是基于 @Conditional 元注解扩展的派生注解,仅在满足特定条件时才会生效。注解格式是 @ConditionalOnXxx

常用注解及场景

以下为常见的条件注解及其典型用法:

注解名称 触发条件 使用场景示例
@ConditionalOnClass 类路径中存在指定类时生效 自动配置 DataSource 时检查驱动类是否存在
@ConditionalOnMissingBean 容器中不存在指定 Bean 时生效 避免覆盖用户自定义的 Bean
@ConditionalOnProperty 配置文件中存在指定属性且匹配值时生效 根据 spring.datasource.enabled 开关配置
@ConditionalOnWebApplication 当前应用是 Web 应用时生效 仅 Web 环境下注册特定的过滤器
@ConditionalOnExpression SpEL 表达式结果为 true 时生效 复杂条件组合判断

底层实现原理

SpringBoot 通过 Condition 接口实现条件判断:

java 复制代码
public interface Condition {
    boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
  • ConditionContext:提供环境变量、类加载器等上下文信息。
  • AnnotatedTypeMetadata:读取注解元数据。

开发实战示例

  1. 类存在时自动配置
java 复制代码
@Configuration
@ConditionalOnClass(DataSource.class)
public class DataSourceAutoConfiguration {
    // 当类路径存在DataSource时自动配置
}
  1. 组合条件控制
java 复制代码
@Bean
@ConditionalOnProperty(name = "cache.enabled", havingValue = "true")
@ConditionalOnMissingBean
public CacheService cacheService() {
    // 当配置cache.enabled=true且容器无CacheService时创建
}
  1. 自定义条件注解

    1. 实现 Condition 接口:
    java 复制代码
    public class EnvCondition implements Condition {
        @Override
        public boolean matches(...) {
            return context.getEnvironment().acceptsProfiles("prod");
        }
    }
    1. 定义注解:
    java 复制代码
    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Conditional(EnvCondition.class)
    public @interface ConditionalOnProduction {}

调试技巧

  • 启动时添加 --debug 参数查看匹配结果:
java 复制代码
============================
CONDITIONS EVALUATION REPORT
============================
Positive matches:
   DataSourceAutoConfiguration matched:
      - @ConditionalOnClass found required class 'javax.sql.DataSource'

最佳实践建议

  1. 避免条件冲突:多个条件注解组合使用时注意逻辑完整性。
  2. 谨慎覆盖默认配置 :优先使用 @ConditionalOnMissingBean 而非直接覆盖。
  3. 合理排序配置类 :使用 @AutoConfigureOrder 控制配置加载顺序。

典型应用场景

  • 多环境配置切换(dev、test、prod)。
  • 模块化功能开关控制。
  • 第三方库的自动适配。
  • 兼容性处理(如不同版本 JDK 的适配)。

属性绑定注解

核心注解 @ConfigurationProperties

  • 作用 :将外部配置文件(如 application.ymlapplication.properties)中的属性批量绑定到 Java Bean。

  • 使用场景 :需要注入多个关联属性层级化配置时。

  • 特点

    • 类型安全 :自动将属性值转换为 Java 类型(如 StringInteger)。
    • 松散绑定 :支持属性名多种格式(如 kebab-casecamelCase)。
    • 嵌套对象支持:通过层级结构绑定复杂对象。
  • 示例:

    java 复制代码
    @Component
    @ConfigurationProperties(prefix = "app")
    public class AppConfig {
        private String name;
        private List<String> servers;
        private Database database;
        
        // Getter/Setter 省略
    }
    
    public class Database {
        private String url;
        private String username;
    }
    properties 复制代码
    # application.properties
    app.name=MyApp
    app.servers=server1,server2
    app.database.url=jdbc:mysql://localhost:3306/db
    app.database.username=root

@EnableConfigurationProperties

启用属性绑定的开关

  • 核心作用

    • 注册配置类 :将 @ConfigurationProperties 标注的类显式注册为 Spring Bean

    • 触发绑定流程 :启用属性绑定机制,使 @ConfigurationProperties 生效。

  • 使用场景

    • 非自动扫描的类 :当配置类未被 @Component 扫描时(如第三方库中的类),需通过此注解手动注册。

    • 明确控制配置类的加载顺序:在特定配置类中集中管理属性绑定。

  • 示例

    java 复制代码
    @Configuration
    @EnableConfigurationProperties(AppConfig.class)
    public class MyConfiguration {
        // 其他 Bean 定义
    }

    或直接标注在启动类:

    java 复制代码
    @SpringBootApplication
    @EnableConfigurationProperties(AppConfig.class)
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }
  • 关键特性

    • 按需加载:仅在需要时启用特定配置类的绑定。

    • 避免组件扫描依赖 :不依赖 @ComponentScan 自动发现配置类。

逐项注入 @Value

  • 作用 :直接注入单个属性值到字段。

  • 适用场景:需要注入少量独立属性时。

  • 局限性

    • 不支持复杂类型(如嵌套对象)。
    • 缺乏类型安全校验。
  • 示例

    java 复制代码
    @Component
    public class MyService {
        @Value("${app.name}")
        private String appName;
    }

配置源扩展 @PropertySource

  • 作用 :加载自定义配置文件 (非 application.*)。

  • 限制 :默认仅支持 .properties 文件,需额外处理 .yml

  • 示例

    java 复制代码
    @Configuration
    @PropertySource("classpath:custom.properties")
    public class CustomConfig {
        // 使用 @Value 或 @ConfigurationProperties 绑定属性
    }

yaml 格式配置文件

SpringBoot 的默认配置文件是 application.properties,这种文件格式有一个问题:配置多以后难阅读和修改,层级结构辨识度不高。可以使用 yaml 格式的配置文件来解决这个问题。

yaml 格式概述

yaml 不是一种标记语言,设计目的就是为了方便人们读写 ,后缀名为:.yml.yaml

.properties 对比优势:

  • 层级结构更清晰。
  • 支持复杂数据结构支持复杂数据结构。
  • 减少重复配置减少重复配置。

核心语法规则

  • 缩进表示层级(使用空格,不要用 Tab 键,一般为2空格)
  • 键值对使用冒号 + 空格:key: value:value 之间必须有一个空格
  • 列表使用短横线 + 空格:
yaml 复制代码
servers:
  - dev.example.com
  - test.example.com
  • 对象嵌套:
yaml 复制代码
database:
  host: localhost
  port: 3306

语法格式

  1. 对象嵌套
yaml 复制代码
person:
  name: 张三
  address:
    province: 浙江
    city: 杭州
    street: 西湖大道
  education:
    - 小学: 西湖实验小学
    - 中学: 杭州二中
  1. 集合类型:有两种表示方法。
  • 行内列表:
yaml 复制代码
fruits: [苹果, 香蕉, 橙子]
  • 多行列表:每条数据格式为 - value 中间有一个空格。
yaml 复制代码
fruits:
  - 苹果
  - 香蕉
  - 橙子
  1. Map映射
  • 基础Map:
yaml 复制代码
http_codes:
  200: OK
  404: Not Found
  500: Internal Server Error
  • 复杂Map:
yaml 复制代码
employees:
  emp001:
    name: 李四
    department: 研发部
  emp002:
    name: 王五
    department: 市场部

示例

java 复制代码
@Component
@ConfigurationProperties(prefix = "person") //和配置文件person前缀的所有配置进行绑定
@Data //自动生成JavaBean属性的getter/setter
//@NoArgsConstructor //自动生成无参构造器
//@AllArgsConstructor //自动生成全参构造器
public class Person {
    private String name;
    private Integer age;
    private Date birthDay;
    private Boolean like;
    private Child child; //嵌套对象
    private List<Dog> dogs; //数组(里面是对象)
    private Map<String,Cat> cats; //表示Map
}

@Data
public class Dog {
    private String name;
    private Integer age;
}

@Data
public class Child {
    private String name;
    private Integer age;
    private Date birthDay;
    private List<String> text; //数组
}

@Data
public class Cat {
    private String name;
    private Integer age;
}
yaml 复制代码
person:
  name: 张三
  age: 18
  birthDay: 2010/10/10 12:12:12
  like: true
  child:
    name: 李四
    age: 20
    birthDay: 2018/10/10
    text: ["abc","def"]
  dogs:
    - name: 小黑
      age: 3
    - name: 小白
      age: 2
  cats:
    c1:
      name: 小蓝
      age: 3
    c2: {name: 小绿,age: 2} #对象也可用{}表示

细节

  • birthDay 推荐写为 birth-day

  • 文本

    • 单引号 不会转义(\n 则为普通字符串显示)

    • 双引号 会转义(\n 会显示为换行符

  • 大文本

    • | 开头,大文本写在下层,保留文本格式换行符正确显示

    • > 开头,大文本写在下层,折叠换行符。

  • 多文档合并

    • 使用 --- 可以把多个 yaml 文档合并在一个文档中,每个文档区依然认为内容独立。

SpringBoot 特有语法规则

  • 多环境配置示例:
yaml 复制代码
spring:
  profiles:
    active: dev
---
spring:
  profiles: dev
server:
  port: 8080
---
spring:
  profiles: prod
server:
  port: 80

便于多个环境灵活切换。

日志配置

规范:项目开发不要编写 System.out.println(),应该用日志记录信息。

SpringBoot 有一套默认的日志体系:

  • 采用 Logback 作为默认实现(需排除 spring-boot-starter-logging 才能切换)。
  • 兼容 SLF4J 门面接口。
  • 支持 Log4j2(需引入spring-boot-starter-log4j2)。

SpringBoot 是如何配置日志的

  1. 每个 starter 场景,都会导入一个核心场景 spring-boot-starter
  2. 核心场景引入了日志的所用功能 spring-boot-starter-logging
  3. 默认使用了 logback + slf4j 组合作为默认底层日志。
  4. 日志是系统一启动就要用,xxxAutoConfiguration 是系统启动好了以后放好的组件,后来用的。
  5. 日志是利用监听器机制 配置好的。ApplicationListener
  6. 日志所有的配置都可以通过修改配置文件实现。以 logging 开始的所有配置。

示例:

  1. 使用 LoggerFactory.getLogger(类对象)
java 复制代码
@RestController
public class HelloController {

	Logger log = LoggerFactory.getLogger(HelloController.class);

	@GetMapping("/hello")
	public String hello(){
		log.info("日志------方法进来了");
		return "hello SpringBoot";
	}

}
  1. 使用注解 @Slf4j
java 复制代码
@RestController
@Slf4j
public class HelloController {

	@GetMapping("/hello")
	public String hello(){
		log.info("日志------方法进来了");
		return "hello SpringBoot";
	}

}

日志格式

默认输出格式:

  • 时间和日期:毫秒级精度。
  • 日志级别:ERRORWARNINFODEBUG or TRACE
  • 进程 ID。
  • ---: 消息分割符。
  • 线程名: 使用 [] 包含。
  • Logger 名: 通常是产生日志的类名
  • 消息: 日志记录的内容。

注意: logback 没有 FATAL 级别,对应的是 ERROR

日志级别

  • 由低到高:ALLTRACEDEBUGINFOWARNERRORFATALOFF

  • 只会打印指定级别及以上级别的日志

    • ALL:打印所有日志。

    • TRACE:追踪框架详细流程日志,一般不使用。

    • DEBUG:开发调试细节日志。

    • INFO:关键、感兴趣信息日志。

    • WARN:警告但不是错误的信息日志,比如:版本过时。

    • ERROR:业务错误日志,比如出现各种异常。

    • FATAL:致命错误日志,比如 jvm 系统崩溃。

    • OFF:关闭所有日志记录。

  • 不指定级别的所有类,都使用 root 指定的级别作为默认级别。

  • SpringBoot 日志默认级别是 INFO

配置示例:

yaml 复制代码
logging:
  level:
    root: INFO          # 全局日志级别
    org.springframework: WARN
    com.example: DEBUG  # 包级日志控制
  file:
    name: app.log       # 日志文件名(优先于path)
    path: /var/log      # 日志目录(自动生成spring.log)
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
    file: "%d{ISO8601} [%15.15t] %-5level %40.40logger{39} : %message%n"

日志分组

将相关的 logger 分组在一起,统一配置。SpringBoot 也支持。比如:Tomcat 相关的日志统一设置

properties 复制代码
logging.group.tomcat=org.apache.catalina,org.apache.coyote,org.apache.tomcat
logging.level.tomcat=trace

SpringBoot 默认有两个组

组名 成员
web org.springframework.core.codecorg.springframework.httporg.springframework.weborg.springframework.boot.actuate.endpoint.weborg.springframework.boot.web.servlet.ServletContextInitializerBeans
sql org.springframework.jdbc.coreorg.hibernate.SQLorg.jooq.tools.LoggerListener

日志输出

将日志输出成一个文件:

properties 复制代码
# 指定文件路径
logging.file.path=
# 指定文件名字
logging.file.name=a.log

如果没有指定文件路径则默认为项目目录。

也可以只在指定文件名字写日志文件的全路径名。

properties 复制代码
logging.file.name=D:\\a.log

归档与切割

归档:每天的日志单独存到一个文档中。

切割:每个文件10MB,超过大小切割成另外一个文件。

  1. 每天的日志应该独立分割出来存档。如果使用 logback(SpringBoot 默认整合),可以通过 application.properties 文件指定日志滚动规则。
  2. 如果是其他日志系统,需要自行配置(添加 log4j2.xmllog4j2-spring.xml
  3. 支持的滚动规则设置如下:
配置项 描述
logging.logback.rollingpolicy.file-name-pattern 日志存档的文件名格式(默认值:${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz
logging.logback.rollingpolicy.clean-history-on-start 应用启动时是否清除以前存档(默认值:false)。
logging.logback.rollingpolicy.max-file-size 存档前,每个日志文件的最大大小(默认值:10MB)。
logging.logback.rollingpolicy.total-size-cap 日志文件被删除之前,可以容纳的最大大小(默认值:0B)。设置1GB则磁盘存储超过 1GB 日志后就会删除旧日志文件。
logging.logback.rollingpolicy.max-history 日志文件保存的最大天数(默认值:7)。

Web 开发

静态资源管理

  1. 默认静态资源路径

    SpringBoot自动映射以下目录的静态资源:

    1. classpath:/static/
    2. classpath:/public/
      例如:src/main/resources/static/js/main.js 可通过 http://localhost:8080/js/main.js 访问2。
  2. 自定义资源路径与缓存控制

    properties 复制代码
    spring.web.resources.static-locations=classpath:/custom-static/
    spring.web.resources.cache.period=3600  # 缓存1小时

控制器与请求处理

  1. 定义控制器

    java 复制代码
    @RestController  // 或 @Controller(需配合模板引擎)
    public class UserController {
        @GetMapping("/hello")
        public String hello() {
            return "Hello, Spring Boot!";
        }
    }
  2. Restful风格API

    java 复制代码
    @GetMapping("/user/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.findById(id);
    }
    
    @PostMapping("/user")
    public User createUser(@RequestBody User user) {
        return userService.save(user);
    }         
  3. 参数绑定注解

    • @RequestParam:获取 URL 参数。
    • @RequestBody:解析 JSON 请求体。
    • @ModelAttribute:绑定表单数据。

高级功能

  1. 异常统一处理

    java 复制代码
    @ControllerAdvice
    public class GlobalExceptionHandler {
        @ExceptionHandler(Exception.class)
        public ResponseEntity<String> handleException(Exception e) {
            return ResponseEntity.status(500).body("服务器错误: " + e.getMessage());
        }
    }
  2. 拦截器实现权限验证

    java 复制代码
    public class AuthInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            if (request.getSession().getAttribute("user") == null) {
                response.sendRedirect("/login");
                return false;
            }
            return true;
        }
    }

    注册拦截器:

    java 复制代码
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new AuthInterceptor()).addPathPatterns("/admin/**");
        }
    }

SpringBoot 整合 SSM

  1. 导入依赖:
xml 复制代码
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.8</version>
</dependency>             
  1. 配置数据源

application.yml

yaml 复制代码
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test_db?useSSL=false
    username: root
    password: 123456
    type: com.alibaba.druid.pool.DruidDataSource

mybatis:
  mapper-locations: classpath:mapper/*.xml
  configuration:
    map-underscore-to-camel-case: true
  1. 实体类与 Mapper 接口

实体类:

java 复制代码
public class User {
    private Integer id;
    private String username;
    // getters/setters
}            

Mapper 接口:

java 复制代码
@Mapper
public interface UserMapper {
    @Select("SELECT * FROM user WHERE id = #{id}")
    User selectById(Integer id);
}           
  1. Service 层实现:
java 复制代码
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    
    @Transactional
    public User getUserById(Integer id) {
        return userMapper.selectById(id);
    }
}          
  1. Controller
java 复制代码
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping("/{id}")
    public User get(@PathVariable Integer id) {
        return userService.getUserById(id);
    }
}            
  1. 事务配置

在主启动类添加注解:

java 复制代码
@SpringBootApplication
@EnableTransactionManagement
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}            

关键优化点

  1. 使用 @MapperScan("com.yigongsui.mapper") 替代单个 @Mapper 注解。
  2. 多数据源需配置 @Primary 注解。
  3. MyBatis 分页插件整合:
java 复制代码
@Configuration
public class MyBatisConfig {
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}

Profile 环境配置

核心功能

Profile 是 SpringBoot 用于区分多环境配置的核心机制,通过激活不同的 Profile 可加载对应环境的配置。例如:

  • 开发环境application-dev.yml
  • 测试环境application-test.yml
  • 生产环境application-prod.yml

使用方法

命名规则

配置文件名需遵循 application-{profile}.propertiesapplication-{profile}.yml 格式,例如 application-dev.yml

激活方式

  • 配置文件激活 :在主配置文件中设置 spring.profiles.active=dev
  • 命令行激活java -jar app.jar --spring.profiles.active=dev,test(支持多 Profile)
  • 环境变量激活export SPRING_PROFILES_ACTIVE=prod

多 Profile 共存

  • 通用配置写在 application.yml
  • 环境特有配置写在 application-{profile}.yml
  • 优先级:Profile 专属配置 > 通用配置

外部配置加载顺序与优先级规则

SpringBoot 按从高到低的优先级加载配置,高优先级配置会覆盖低优先级的同名属性,非冲突配置会互补共存:

配置来源 路径示例 优先级
命令行参数 --server.port=8080 最高
外部目录配置文件 file:../config/application.yml 1
项目根目录配置文件 file:./application.yml 2
classpath 配置目录 classpath:/config/application.yml 3
classpath 根目录 classpath:/application.yml 最低
Nacos 远程配置 通过 spring.cloud.nacos.config 指定 覆盖本地配置

特殊规则说明

  1. 同目录文件优先级

    若同一路径存在 .properties.yml 文件,优先加载 .properties

  2. Profile 配置文件加载顺序

    1. 加载主配置文件(如 application.yml
    2. 加载激活的 Profile 文件(如 application-dev.yml
    3. 远程配置中心配置最后加载。
  3. 覆盖逻辑示例

    • application.yml 中定义 server.port=8080
    • application-dev.yml 中定义 server.port=9090
    • 最终生效端口为 9090

SpringBoot 生命周期

生命周期机制介绍

SpringBoot 应用的生命周期由 Spring 框架的 ApplicationContextBean 生命周期机制驱动,分为以下核心阶段:

  1. 应用启动阶段
    • 初始化 SpringApplication,加载配置文件和环境变量。
    • 触发 ApplicationStartingEvent 事件。
    • 创建 ApplicationContext,加载 Bean 定义。
    • 执行 CommandLineRunnerApplicationRunner 接口实现类的逻辑。
  2. Bean 生命周期阶段
    • 实例化:通过构造函数或工厂方法创建 Bean。
    • 依赖注入 :通过 @Autowired 或 XML 配置注入依赖。
    • 初始化 :通过 @PostConstruct 注解或实现 InitializingBean 接口执行初始化逻辑。
    • 销毁 :通过 @PreDestroy 注解或实现 DisposableBean 接口执行销毁逻辑。
  3. 应用关闭阶段
    • 触发 ContextClosedEvent 事件。
    • 销毁所有单例 Bean。
    • 关闭 ApplicationContext

使用方法

  1. 自定义 Bean 生命周期方法

    使用注解定义初始化和销毁逻辑:

    java 复制代码
    @Component
    public class MyService {
        @PostConstruct
        public void init() {
            System.out.println("Bean 初始化完成");
        }
    
        @PreDestroy
        public void cleanup() {
            System.out.println("Bean 销毁前清理");
        }
    }           
  2. 监听应用生命周期事件

    实现 ApplicationListener 接口监听事件:

    java 复制代码
    @Component
    public class MyListener implements ApplicationListener<ApplicationReadyEvent> {
        @Override
        public void onApplicationEvent(ApplicationReadyEvent event) {
            System.out.println("应用启动完成");
        }
    }         
  3. 使用 Actuator 监控生命周期状态

    通过 /actuator/health 端点监控应用健康状态3

    yaml 复制代码
    # application.yml
    management:
      endpoints:
        web:
          exposure:
            include: health,info         

性能优化建议

  • 避免在 @PostConstruct 中执行耗时操作。
  • 使用 SmartLifecycle 接口控制 Bean 启动顺序。
  • 结合 Actuator 的 /actuator/shutdown 端点实现优雅停机。

Swagger

Swagger 是一套用于设计、构建和记录 RESTful API 的开源工具,基于 OpenAPI 规范。它支持自动生成交互式 API 文档,并提供可视化界面用于接口测试。在 SpringBoot 中,Swagger 的集成主要通过依赖库(如 springdoc-openapi)实现。

SpringBoot 集成 Swagger 的步骤

  1. 添加依赖

    pom.xml 中添加以下依赖(注意:SpringBoot 3.x 需使用 springdoc-openapi,而非旧版 springfox):

    xml 复制代码
    <dependency>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
        <version>2.3.0</version> <!-- 确保版本兼容 -->
    </dependency>
  2. 配置 Swagger

    application.yml 中配置基础信息:

    yaml 复制代码
    springdoc:
      swagger-ui:
        path: /swagger-ui.html  # 访问路径
        tags-sorter: alpha      # 标签排序规则
      api-docs:
        path: /v3/api-docs      # OpenAPI 描述文件路径
      info:
        title: API 文档
        version: 1.0.0
        description: Swagger 示例          
  3. 添加注解

    Controller 类和方法上使用注解描述接口:

    java 复制代码
    @RestController
    @OpenAPIDefinition(info = @Info(title = "用户管理接口"))
    public class UserController {
        
        @Operation(summary = "获取用户列表", description = "分页查询用户")
        @GetMapping("/users")
        public List<User> getUsers() {
            // 业务逻辑
        }
    } 
  4. 访问文档界面

    启动应用后,通过以下 URL 访问 Swagger UI:http://localhost:端口/swagger-ui.html

关键注解说明

注解 用途
@OpenAPIDefinition 定义全局 API 信息
@Operation 描述单个接口功能
@Parameter 定义接口参数
@Tag 对接口分组(替代旧版 @Api

注意事项

  1. 兼容性 :SpringBoot 3.x 需使用 springdoc-openapi,旧版 springfox 不再支持。
  2. 安全性:生产环境需通过权限控制 Swagger 访问,避免暴露敏感信息。
  3. 配置简化:若无需自定义配置,依赖添加后即可自动生成文档。

SpringBoot 远程调用

基于 HTTP 的远程调用

WebClient(响应式非阻塞)

适用于异步场景,需引入 spring-boot-starter-webflux 依赖:

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>  

示例:

java 复制代码
// 创建 WebClient 实例
WebClient client = WebClient.create("http://api.example.com");

// 发起 GET 请求
Mono<String> response = client.get()
    .uri("/data")
    .retrieve()
    .bodyToMono(String.class);

// 处理响应(异步)
response.subscribe(result -> System.out.println("响应结果: " + result));

RestTemplate(同步阻塞)

传统同步方式,需注意在 SpringBoot 3.x 中未完全弃用但推荐使用 WebClient

java 复制代码
@Bean
public RestTemplate restTemplate() {
    return new RestTemplate();
}

// 调用示例
String result = restTemplate.getForObject("http://api.example.com/data", String.class);           

声明式 HTTP 客户端(OpenFeign)

通过接口注解简化调用,需整合 SpringCloud OpenFeign。

步骤

  1. 添加依赖

    xml 复制代码
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
  2. 启用 Feign 客户端(使用注解 @EnableFeignClients

    java 复制代码
    @SpringBootApplication
    @EnableFeignClients
    public class Application { ... }
  3. 定义接口

    java 复制代码
    @FeignClient(name = "example-service", url = "http://api.example.com")
    public interface ExampleClient {
        @GetMapping("/data")
        String getData();
    }    
  4. 注入使用

    java 复制代码
    @Autowired
    private ExampleClient exampleClient;
    
    public void callRemote() {
        String data = exampleClient.getData();
    }      

RPC 框架(如 gRPC)

适用于高性能二进制通信,需额外配置协议文件和服务端/客户端实现。

实现步骤

  1. 添加 grpc-spring-boot-starter 依赖。
  2. 定义 .proto 文件描述服务接口。
  3. 生成 Java 代码并实现服务逻辑。

注意事项

  1. 版本兼容性:SpringBoot 3.x 需搭配 SpringCloud 2022.x 及以上版本。
  2. 性能优化 :异步场景优先选择 WebClient,同步场景可使用 RestTemplate
  3. 异常处理 :需捕获 WebClientResponseExceptionFeignException 等特定异常。

SpringSecurity

SpringSecurity 是 Spring 生态中专注于安全管理的框架,提供身份验证 (Authentication)、授权 (Authorization)、会话管理等核心功能,通过声明式配置简化安全控制逻辑。

核心功能

  • 身份验证:验证用户身份(如用户名密码、OAuth2)。
  • 授权:控制用户对资源的访问权限(如角色/权限校验)。
  • 会话管理:管理用户会话生命周期与安全性。
  • 安全防护:防御 CSRF、XSS、SQL 注入等攻击。

SpringBoot 集成 SpringSecurity

  1. 导入依赖:
xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
  1. 配置基础安全规则

创建 SecurityConfig 类,配置默认安全策略:

java 复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class SecurityConfig {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/public/**").permitAll()  // 公开路径
                .anyRequest().authenticated()              // 其他路径需认证
            )
            .formLogin(form -> form
                .loginPage("/login")        // 自定义登录页
                .permitAll()
            )
            .logout(logout -> logout
                .permitAll()
            );
        return http.build();
    }
}
  1. 自定义用户服务(内存示例)
java 复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

@Bean
public UserDetailsService userDetailsService() {
    InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
    manager.createUser(User.withUsername("admin")
            .password("{noop}admin123")  // {noop} 表示明文密码(仅测试用)
            .roles("ADMIN")
            .build());
    return manager;
}
  1. 启动并测试

运行项目后,访问受保护接口(如 /home)将自动跳转到默认登录页,使用配置的用户名密码登录。

进阶配置

  1. 基于注解的权限控制

    使用 @PreAuthorize 实现方法级权限校验:

    java 复制代码
    @GetMapping("/admin")
    @PreAuthorize("hasRole('ADMIN')")
    public String adminPage() {
        return "Admin Panel";
    }
  2. 密码加密配置

    推荐使用 BCryptPasswordEncoder

    java 复制代码
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
  3. 动态权限管理

    通过实现 UserDetailsService 和自定义权限逻辑,从数据库加载用户权限。

总结

SpringSecurity 通过声明式配置简化安全逻辑,SpringBoot 通过自动配置进一步降低集成成本。实际项目中需结合数据库、加密算法和动态权限管理实现完整方案。

相关推荐
豆沙沙包?2 小时前
8.学习笔记-Maven进阶(P82-P89)
笔记·学习·maven
lybugproducer2 小时前
创建型设计模式之:简单工厂模式、工厂方法模式、抽象工厂模式、建造者模式和原型模式
java·设计模式·建造者模式·简单工厂模式·工厂方法模式·抽象工厂模式·面向对象
南客先生2 小时前
马架构的Netty、MQTT、CoAP面试之旅
java·mqtt·面试·netty·coap
Minyy112 小时前
SpringBoot程序的创建以及特点,配置文件,LogBack记录日志,配置过滤器、拦截器、全局异常
xml·java·spring boot·后端·spring·mybatis·logback
百锦再2 小时前
Java与Kotlin在Android开发中的全面对比分析
android·java·google·kotlin·app·效率·趋势
醉暮天3 小时前
4.25学习——文件上传之00截断
学习
武昌库里写JAVA3 小时前
39.剖析无处不在的数据结构
java·vue.js·spring boot·课程设计·宠物管理
画个大饼4 小时前
Go语言实战:快速搭建完整的用户认证系统
开发语言·后端·golang
Nelson_hehe5 小时前
Java基础第四章、面向对象
java·语法基础·面向对象程序设计
Thomas_YXQ5 小时前
Unity3D Lua集成技术指南
java·开发语言·驱动开发·junit·全文检索·lua·unity3d