Skip to content

Spring Boot Actuator 构建信息集成详解 🏗️

什么是 Spring Boot Actuator 构建信息?

Spring Boot Actuator 是 Spring Boot 提供的生产就绪功能模块,它可以帮助我们监控和管理应用程序。其中,构建信息(Build Info)是 Actuator 提供的一个重要功能,它能够展示应用程序的构建相关信息。

NOTE

构建信息功能需要在项目的 META-INF 目录下存在 build-info.properties 文件才能正常工作。

为什么需要构建信息? 🤔

在实际的生产环境中,我们经常遇到这样的问题:

  • 版本混乱:不知道当前运行的是哪个版本的应用
  • 构建追踪困难:无法快速确定应用的构建时间和构建环境
  • 问题排查复杂:出现问题时难以定位具体的构建版本

构建信息功能就是为了解决这些痛点而设计的。它让我们能够:

核心价值

  • 版本透明化:清楚知道当前运行的应用版本
  • 构建可追溯:记录构建时间、Java 版本等关键信息
  • 问题快速定位:通过构建信息快速排查问题
  • 运维友好:为运维人员提供关键的应用元数据

工作原理解析 ⚙️

让我们通过时序图来理解构建信息的生成和使用过程:

Maven 插件配置详解 🔧

基础配置

首先,让我们看看最基本的配置:

xml
<project>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>my-spring-boot-app</artifactId>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>build-info</goal> 
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
xml
<project>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>my-spring-boot-app</artifactId>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>build-info</goal>
                        </goals>
                        <configuration>
                            <!-- 添加自定义属性 -->
                            <additionalProperties> 
                                <encoding.source>UTF-8</encoding.source> 
                                <encoding.reporting>UTF-8</encoding.reporting> 
                                <java.version>${java.version}</java.version> 
                                <spring.boot.version>${spring.boot.version}</spring.boot.version> 
                            </additionalProperties> 
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

高级配置选项

让我们深入了解各个配置参数:

完整的高级配置示例
xml
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>build-info</goal>
            </goals>
            <configuration>
                <!-- 自定义输出文件位置 -->
                <outputFile>${project.build.outputDirectory}/META-INF/build-info.properties</outputFile>
                
                <!-- 排除某些默认属性 -->
                <excludeInfoProperties>
                    <excludeInfoProperty>time</excludeInfoProperty>
                </excludeInfoProperties>
                
                <!-- 添加额外属性 -->
                <additionalProperties>
                    <encoding.source>UTF-8</encoding.source>
                    <encoding.reporting>UTF-8</encoding.reporting>
                    <java.version>${java.version}</java.version>
                    <spring.boot.version>${spring.boot.version}</spring.boot.version>
                    <git.branch>${git.branch}</git.branch>
                    <git.commit.id>${git.commit.id}</git.commit.id>
                    <build.user>${user.name}</build.user>
                    <build.environment>${env.BUILD_ENV}</build.environment>
                </additionalProperties>
                
                <!-- 跳过构建信息生成 -->
                <skip>false</skip>
                
                <!-- 自定义构建时间 -->
                <time>${maven.build.timestamp}</time>
            </configuration>
        </execution>
    </executions>
</plugin>

生成的构建信息文件 📄

执行构建后,会在 target/classes/META-INF/build-info.properties 生成如下内容:

properties
# 默认生成的属性
build.artifact=my-spring-boot-app
build.group=com.example
build.name=My Spring Boot Application
build.time=2024-01-15T10:30:45.123Z
build.version=1.0.0

# 自定义添加的属性(都会加上 build. 前缀)
build.encoding.source=UTF-8
build.encoding.reporting=UTF-8
build.java.version=17
build.spring.boot.version=3.2.0

IMPORTANT

注意:所有通过 additionalProperties 添加的属性都会自动加上 build. 前缀。

Kotlin + Spring Boot 实战示例 🚀

让我们看看如何在 Kotlin 项目中使用构建信息:

1. 创建构建信息服务

kotlin
@Service
class BuildInfoService(
    private val buildProperties: BuildProperties? = null
) {
    
    /**
     * 获取应用构建信息
     */
    fun getBuildInfo(): Map<String, Any> {
        return buildProperties?.let { props ->
            mapOf(
                "name" to props.name,
                "version" to props.version,
                "artifact" to props.artifact,
                "group" to props.group,
                "time" to props.time,
                // 获取自定义属性
                "javaVersion" to (props.get("java.version") ?: "Unknown"), 
                "springBootVersion" to (props.get("spring.boot.version") ?: "Unknown") 
            )
        } ?: mapOf("error" to "Build info not available")
    }
    
    /**
     * 检查是否为生产环境构建
     */
    fun isProductionBuild(): Boolean {
        return buildProperties?.get("build.environment") == "production"
    }
}

2. 创建构建信息控制器

kotlin
@RestController
@RequestMapping("/api/build")
class BuildInfoController(
    private val buildInfoService: BuildInfoService
) {
    
    /**
     * 获取构建信息API
     */
    @GetMapping("/info")
    fun getBuildInfo(): ResponseEntity<Map<String, Any>> {
        val buildInfo = buildInfoService.getBuildInfo()
        return ResponseEntity.ok(buildInfo)
    }
    
    /**
     * 健康检查,包含版本信息
     */
    @GetMapping("/health")
    fun healthCheck(): ResponseEntity<Map<String, Any>> {
        val buildInfo = buildInfoService.getBuildInfo()
        
        return ResponseEntity.ok(mapOf(
            "status" to "UP",
            "version" to buildInfo["version"], 
            "buildTime" to buildInfo["time"], 
            "timestamp" to System.currentTimeMillis()
        ))
    }
}

3. 自定义 Actuator Info 贡献者

kotlin
@Component
class CustomInfoContributor : InfoContributor {
    
    override fun contribute(builder: Info.Builder) {
        // 添加自定义运行时信息
        builder.withDetail("runtime", mapOf(
            "activeProfiles" to getActiveProfiles(),
            "jvmVersion" to System.getProperty("java.version"),
            "osName" to System.getProperty("os.name"),
            "availableProcessors" to Runtime.getRuntime().availableProcessors(),
            "maxMemory" to "${Runtime.getRuntime().maxMemory() / 1024 / 1024} MB"
        ))
        
        // 添加应用特定信息
        builder.withDetail("application", mapOf(
            "description" to "My awesome Spring Boot application",
            "features" to listOf("REST API", "Database", "Caching"),
            "maintainer" to "Development Team"
        ))
    }
    
    private fun getActiveProfiles(): List<String> {
        // 这里可以注入 Environment 来获取激活的配置文件
        return listOf("default") // 简化示例
    }
}

实际应用场景 💡

场景1:生产环境版本确认

kotlin
@Component
class DeploymentValidator(
    private val buildInfoService: BuildInfoService
) {
    
    @EventListener(ApplicationReadyEvent::class)
    fun validateDeployment() {
        val buildInfo = buildInfoService.getBuildInfo()
        
        logger.info("=== 应用部署信息 ===")
        logger.info("应用名称: ${buildInfo["name"]}")
        logger.info("版本号: ${buildInfo["version"]}") 
        logger.info("构建时间: ${buildInfo["time"]}") 
        logger.info("Java版本: ${buildInfo["javaVersion"]}")
        
        // 生产环境额外检查
        if (buildInfoService.isProductionBuild()) {
            logger.warn("🚀 生产环境部署确认完成!")
        }
    }
    
    companion object {
        private val logger = LoggerFactory.getLogger(DeploymentValidator::class.java)
    }
}

场景2:API 响应中包含版本信息

kotlin
@RestControllerAdvice
class GlobalResponseHandler {
    
    @Autowired
    private lateinit var buildProperties: BuildProperties
    
    /**
     * 为所有API响应添加版本信息
     */
    @ModelAttribute("apiVersion")
    fun addVersionInfo(): String {
        return buildProperties.version 
    }
}

// 使用示例
@RestController
class UserController {
    
    @GetMapping("/users")
    fun getUsers(@ModelAttribute("apiVersion") version: String): ResponseEntity<Any> {
        return ResponseEntity.ok(mapOf(
            "data" to listOf(/* 用户数据 */),
            "meta" to mapOf(
                "apiVersion" to version, 
                "timestamp" to System.currentTimeMillis()
            )
        ))
    }
}

配置参数详解 ⚙️

参数名类型默认值说明
additionalPropertiesMap-添加到构建信息中的额外属性
excludeInfoPropertiesList-要排除的属性列表
outputFileFileMETA-INF/build-info.properties输出文件位置
skipbooleanfalse是否跳过构建信息生成
timeString${project.build.outputTimestamp}构建时间

TIP

使用 excludeInfoProperties 可以排除敏感信息,比如在某些环境下不想暴露构建时间。

常见问题与解决方案 ⚠️

问题1:构建信息不显示

常见原因

  • Maven 插件配置错误
  • build-info.properties 文件未生成
  • Actuator 依赖缺失

解决方案:

kotlin
// 1. 确保添加了 Actuator 依赖
// build.gradle.kts
dependencies {
    implementation("org.springframework.boot:spring-boot-starter-actuator") 
}

// 2. 检查 application.yml 配置
// application.yml
management:
  endpoints:
    web:
      exposure:
        include: info # [!code highlight]
  info:
    build:
      enabled: true # [!code highlight]

问题2:自定义属性未显示

xml
<!-- 错误配置 -->
<additionalProperties>
    <property name="custom.value">test</property> 
</additionalProperties>

<!-- 正确配置 -->
<additionalProperties>
    <custom.value>test</custom.value> 
</additionalProperties>

问题3:构建时间格式问题

xml
<!-- 自定义时间格式 -->
<configuration>
    <time>2024-01-15T10:30:45.123Z</time> 
    <!-- 或者禁用时间 -->
    <time>off</time> 
</configuration>

最佳实践建议 ⭐

  1. 版本管理

    xml
    <additionalProperties>
        <git.branch>${git.branch}</git.branch>
        <git.commit.id>${git.commit.id}</git.commit.id>
    </additionalProperties>
  2. 环境区分

    xml
    <additionalProperties>
        <build.environment>${env.BUILD_ENV}</build.environment>
        <build.profile>${spring.profiles.active}</build.profile>
    </additionalProperties>
  3. 安全考虑

    xml
    <excludeInfoProperties>
        <excludeInfoProperty>build.user</excludeInfoProperty>
        <excludeInfoProperty>build.machine</excludeInfoProperty>
    </excludeInfoProperties>

总结 🎉

Spring Boot Actuator 的构建信息功能为我们提供了强大的应用元数据管理能力。通过合理配置和使用,我们可以:

  • 🎯 提升运维效率:快速识别应用版本和构建信息
  • 🔍 简化问题排查:通过构建信息快速定位问题版本
  • 📊 增强监控能力:为监控系统提供丰富的应用元数据
  • 🛡️ 保障生产安全:确保部署的是正确版本的应用

NOTE

构建信息功能虽然简单,但在实际的生产环境中却是不可或缺的。它就像应用的"身份证",让我们随时能够了解应用的"出身"和"履历"。

记住,好的构建信息配置不仅能帮助开发团队,更能为运维团队提供宝贵的应用洞察! 🚀