1. 程式人生 > >spring boot 原始碼解析57-actuator元件:info背後的密碼(全網獨家)

spring boot 原始碼解析57-actuator元件:info背後的密碼(全網獨家)

解析

我們平常訪問/info時會返回一些自定義的資訊,一般人只知道在application.properties中配置info.author=herry 開頭的配置,這樣就可以在訪問/info時,就會返回author: “herry”,但是如下的返回值是如何返回的,很多人就不會了

{
author: "herry",
git: {
commit: {
time: 1515694386000,
id: "自定義的commit.id.abbrev"
},
branch: "主幹"
},
build: {
version: "0.0.1-SNAPSHOT",
artifact: "demo",
description:
"Demo project for Spring Boot", group: "com.example", time: 1515694386000 } }

InfoEndpoint的解析在spring boot 原始碼解析23-actuate使用及EndPoint解析中有介紹,InfoContributor最終是通過InfoEndpoint來呼叫的.

解析

關於這部分的類圖如下:

InfoContributor-class-uml

InfoContributor

InfoContributor–> 新增 應用詳情.程式碼如下:

public interface InfoContributor {

    // 向Info.Builder中新增資訊
void contribute(Info.Builder builder); }

Info

很簡單的一個封裝類,使用了建造者模式

程式碼如下:

@JsonInclude(Include.NON_EMPTY)
public final class Info {

    private final Map<String, Object> details;

    private Info(Builder builder) {
        LinkedHashMap<String, Object> content = new LinkedHashMap<String, Object>();
        content.putAll(builder.content);
        this
.details = Collections.unmodifiableMap(content); } @JsonAnyGetter public Map<String, Object> getDetails() { return this.details; } public Object get(String id) { return this.details.get(id); } @SuppressWarnings("unchecked") public <T> T get(String id, Class<T> type) { Object value = get(id); if (value != null && type != null && !type.isInstance(value)) { throw new IllegalStateException("Info entry is not of required type [" + type.getName() + "]: " + value); } return (T) value; } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj instanceof Info) { Info other = (Info) obj; return this.details.equals(other.details); } return false; } @Override public int hashCode() { return this.details.hashCode(); } @Override public String toString() { return getDetails().toString(); } public static class Builder { private final Map<String, Object> content; public Builder() { this.content = new LinkedHashMap<String, Object>(); } public Builder withDetail(String key, Object value) { this.content.put(key, value); return this; } public Builder withDetails(Map<String, Object> details) { this.content.putAll(details); return this; } public Info build() { return new Info(this); } } }

EnvironmentInfoContributor

EnvironmentInfoContributor–> 一個提供所有environment 屬性中字首為info的InfoContributor.

程式碼如下:

public class EnvironmentInfoContributor implements InfoContributor {

    private final PropertySourcesBinder binder;

    public EnvironmentInfoContributor(ConfigurableEnvironment environment) {
        this.binder = new PropertySourcesBinder(environment);
    }

    @Override
    public void contribute(Info.Builder builder) {
        // 通過PropertySourcesBinder 將info為字首的環境變數抽取出來
        builder.withDetails(this.binder.extractAll("info"));
    }

}

MapInfoContributor

程式碼如下:

public class MapInfoContributor implements InfoContributor {

    private final Map<String, Object> info;

    public MapInfoContributor(Map<String, Object> info) {
        this.info = new LinkedHashMap<String, Object>(info);
    }

    @Override
    public void contribute(Info.Builder builder) {
        builder.withDetails(this.info);
    }

}

該類沒有自動裝配

SimpleInfoContributor

程式碼如下:

public class SimpleInfoContributor implements InfoContributor {

    private final String prefix;

    private final Object detail;

    public SimpleInfoContributor(String prefix, Object detail) {
        Assert.notNull(prefix, "Prefix must not be null");
        this.prefix = prefix;
        this.detail = detail;
    }

    @Override
    public void contribute(Info.Builder builder) {
        if (this.detail != null) {
            builder.withDetail(this.prefix, this.detail);
        }
    }

該類沒有自動裝配

InfoPropertiesInfoContributor

InfoPropertiesInfoContributor –> 一個暴露InfoProperties的InfoContributor.其泛型引數為T extends InfoProperties

  1. 欄位,構造器如下:

    private final T properties;
    
    // 暴露的模式
    private final Mode mode;
    
    protected InfoPropertiesInfoContributor(T properties, Mode mode) {
        this.properties = properties;
        this.mode = mode;
    }

    Mode是1個列舉,程式碼如下:

    public enum Mode {
    
        // 暴露所有的資訊
        FULL,
    
        // 只暴露預設的資訊
        SIMPLE
    
    }
  2. 其聲明瞭如下幾個方法:

    1. generateContent –> 抽取出內容為info endpoint 使用.程式碼如下:

      protected Map<String, Object> generateContent() {
          // 1. 根據模式的不同暴露出所有的資料
          Map<String, Object> content = extractContent(toPropertySource());
          // 2. 預設空實現,子類可複寫
          postProcessContent(content);
          return content;
      }
      1. 根據模式的不同暴露出所有的資料.

        toPropertySource方法實現如下:

        protected PropertySource<?> toPropertySource() {
            //  如果模式為FULL,則返回所有的資料,否則,只暴露預設的資訊
            if (this.mode.equals(Mode.FULL)) {
                return this.properties.toPropertySource();
            }
            return toSimplePropertySource();
        }
        1. 如果模式為FULL,則返回所有的資料,否則,只暴露預設的資訊
        2. 返回PropertySource–>SIMPLE 模式,抽象方法,子類實現.程式碼如下:

          protected abstract PropertySource<?> toSimplePropertySource();

        extractContent程式碼如下:

        protected Map<String, Object> extractContent(PropertySource<?> propertySource) {
            return new PropertySourcesBinder(propertySource).extractAll("");
        }
      2. 預設空實現,子類可複寫.程式碼如下:

        protected void postProcessContent(Map<String, Object> content) {
        }
    2. copyIfSet –> 如果properties中有配置key的話,則copy到target中.程式碼如下:

      protected void copyIfSet(Properties target, String key) {
          String value = this.properties.get(key);
          if (StringUtils.hasText(value)) {
              target.put(key, value);
          }
      }
    3. replaceValue –> 替換值.程式碼如下:

      protected void replaceValue(Map<String, Object> content, String key, Object value) {
          if (content.containsKey(key) && value != null) {
              content.put(key, value);
          }
      }
    4. getNestedMap –> 獲得巢狀的map 如果map中有給定key的話,否則返回empty map.程式碼如下:

      protected Map<String, Object> getNestedMap(Map<String, Object> map, String key) {
          Object value = map.get(key);
          if (value == null) {
              return Collections.emptyMap();
          }
          return (Map<String, Object>) value;
      }

InfoProperties

InfoProperties實現了Iterable介面,其泛型為InfoProperties.Entry.Entry如下:

public final class Entry {

        private final String key;

        private final String value;

        private Entry(String key, String value) {
            this.key = key;
            this.value = value;
        }

        public String getKey() {
            return this.key;
        }

        public String getValue() {
            return this.value;
        }

}
  1. 欄位構造器如下:

    private final Properties entries;
    
    public InfoProperties(Properties entries) {
        Assert.notNull(entries, "Entries must not be null");
        this.entries = copy(entries);
    }

    copy 方法如下:

    private Properties copy(Properties properties) {
        Properties copy = new Properties();
        copy.putAll(properties);
        return copy;
    }
  2. 其它方法實現如下:

    1. get,如下:

      public String get(String key) {
          return this.entries.getProperty(key);
      }
    2. getDate,如下:

      public Date getDate(String key) {
          String s = get(key);
          if (s != null) {
              try {
                  return new Date(Long.parseLong(s));
              }
              catch (NumberFormatException ex) {
                  // Not valid epoch time
              }
          }
          return null;
      }
    3. iterator,如下:

      public Iterator<Entry> iterator() {
          return new PropertiesIterator(this.entries);
      }

      PropertiesIterator 程式碼如下:

      private final class PropertiesIterator implements Iterator<Entry> {
      
          private final Iterator<Map.Entry<Object, Object>> iterator;
      
          private PropertiesIterator(Properties properties) {
              this.iterator = properties.entrySet().iterator();
          }
      
          @Override
          public boolean hasNext() {
              return this.iterator.hasNext();
          }
      
          @Override
          public Entry next() {
              Map.Entry<Object, Object> entry = this.iterator.next();
              return new Entry((String) entry.getKey(), (String) entry.getValue());
          }
      
          @Override
          public void remove() {
              throw new UnsupportedOperationException("InfoProperties are immutable.");
          }
      }
    4. toPropertySource,程式碼如下:

      public PropertySource<?> toPropertySource() {
          return new PropertiesPropertySource(getClass().getSimpleName(),
                  copy(this.entries));
      }

BuildProperties

BuildProperties–> 繼承自InfoProperties,提供專案構建相關的資訊

  1. 構造器如下:

    public BuildProperties(Properties entries) {
        super(processEntries(entries));
    }

    processEntries–>從給的Properties 將time所對應的值轉換為時間戳的格式.程式碼如下:

    private static Properties processEntries(Properties properties) {
        coerceDate(properties, "time");
        return properties;
    }
    
    private static void coerceDate(Properties properties, String key) {
        String value = properties.getProperty(key);
        if (value != null) {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
            try {
                String updatedValue = String.valueOf(format.parse(value).getTime());
                properties.setProperty(key, updatedValue);
            }
            catch (ParseException ex) {
                // Ignore and store the original value
            }
        }
    }
  2. 其他方法,都是最終呼叫InfoProperties#get,如下:

    public String getGroup() {
        return get("group");
    }
    
    public String getArtifact() {
        return get("artifact");
    }
    
    public String getName() {
        return get("name");
    }
    
    public String getVersion() {
        return get("version");
    }
    
    public Date getTime() {
        return getDate("time");
    }

GitProperties

GitProperties–> 繼承自InfoProperties,提供git相關的資訊比如 commit id 和提交時間。

  1. 構造器如下:

    public GitProperties(Properties entries) {
        super(processEntries(entries));
    }

    processEntries–>將git.properties中的commit.time,build.time 轉換為yyyy-MM-dd’T’HH:mm:ssZ 格式的資料.程式碼如下:

    private static Properties processEntries(Properties properties) {
        coercePropertyToEpoch(properties, "commit.time");
        coercePropertyToEpoch(properties, "build.time");
        return properties;
    }

    coercePropertyToEpoch程式碼如下:

    private static void coercePropertyToEpoch(Properties properties, String key) {
        String value = properties.getProperty(key);
        if (value != null) {
            properties.setProperty(key, coerceToEpoch(value));
        }
    }

    coerceToEpoch –> 嘗試將給定的字串轉換為紀元時間.Git屬性資訊被指定為秒或使用yyyy-MM-dd’T’HH:mm:ssZ 格式的資料.程式碼如下:

    private static String coerceToEpoch(String s) {
        Long epoch = parseEpochSecond(s);
        if (epoch != null) {
            return String.valueOf(epoch);
        }
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
        try {
            return String.valueOf(format.parse(s).getTime());
        }
        catch (ParseException ex) {
            return s;
        }
    }
    
    private static Long parseEpochSecond(String s) {
        try {
            return Long.parseLong(s) * 1000;
        }
        catch (NumberFormatException ex) {
            return null;
        }
    }
  2. 其他方法,都是最終呼叫InfoProperties#get,如下:

    public String getBranch() {
        return get("branch");
    }
    
    
    public String getCommitId() {
        return get("commit.id");
    }
    
    
    public String getShortCommitId() {
        // 1. 獲得commit.id.abbrev
        String shortId = get("commit.id.abbrev");
        if (shortId != null) {
            return shortId;
        }
        // 2.commit.id,如果不等於null並且id長度大於7,則擷取前7位
        String id = getCommitId();
        if (id == null) {
            return null;
        }
        return (id.length() > 7 ? id.substring(0, 7) : id);
    }
    
    
    public Date getCommitTime() {
        return getDate("commit.time");
    }

BuildInfoContributor

BuildInfoContributor–>繼承自InfoPropertiesInfoContributor,將BuildProperties暴露出去

  1. 構造器如下:

    public BuildInfoContributor(BuildProperties properties) {
        super(properties, Mode.FULL);
    }
  2. 方法實現如下:

    1. contribute,程式碼如下:

      public void contribute(Info.Builder builder) {
          builder.withDetail("build", generateContent());
      }

      由於BuildInfoContributor預設的Mode為FULL,因此該方法最終會將BuildProperties中的所有資料暴露出去,其key為build

    2. toSimplePropertySource–> 當BuildInfoContributor的Mode為SIMPLE時呼叫,一般不會呼叫該方法程式碼如下:

      protected PropertySource<?> toSimplePropertySource() {
          Properties props = new Properties();
          // 1. 預設讀取META-INF/build-info.properties中的build.group
          copyIfSet(props, "group");
          copyIfSet(props, "artifact");
          copyIfSet(props, "name");
          copyIfSet(props, "version");
          copyIfSet(props, "time");
          return new PropertiesPropertySource("build", props);
      }
      1. 將META-INF/build-info.properties中的build.group, build.artifact, build.name, build.version, build.time 複製到Properties中
      2. 例項化PropertiesPropertySource,名字為build
    3. postProcessContent–> 將build.time 轉換為time.程式碼如下:

      protected void postProcessContent(Map<String, Object> content) {
          // 將build.time 轉換為time
          replaceValue(content, "time", getProperties().getTime());
      }

GitInfoContributor

GitInfoContributor–>繼承自InfoPropertiesInfoContributor,將GitProperties暴露出去

  1. 構造器如下:

    public GitInfoContributor(GitProperties properties, Mode mode) {
        // 預設是SIMPLE
        super(properties, mode);
    }
    
    public GitInfoContributor(GitProperties properties) {
        this(properties, Mode.SIMPLE);
    }
  2. 方法實現如下:

    1. contribute–>當Mode為full時呼叫,由於預設是SIMPLE,因此該方法一般不會呼叫.程式碼如下:

      public void contribute(Info.Builder builder) {
          builder.withDetail("git", generateContent());
      }
    2. toSimplePropertySource–> 預設呼叫,程式碼如下:

      protected PropertySource<?> toSimplePropertySource() {
          Properties props = new Properties();
          // 1. 從git.properties中獲得branch
          copyIfSet(props, "branch");
          // 2. 從git.properties中獲得commit.id.abbrev
          String commitId = getProperties().getShortCommitId();
          if (commitId != null) {
              props.put("commit.id", commitId);
          }
          // 2. 從git.properties中獲得commit.time
          copyIfSet(props, "commit.time");
          return new PropertiesPropertySource("git", props);
      }
      1. 從git.properties中獲得branch,複製到props中
      2. 從git.properties中獲得commit.id.abbrev,複製到props中
      3. 從git.properties中獲得commit.time,複製到props中
      4. 例項化 PropertiesPropertySource,名字為git
    3. postProcessContent,程式碼如下:

      protected void postProcessContent(Map<String, Object> content) {
          // 1. 獲得commit所對應的map中time所對應的值,將其轉換為Date,然後將其進行替換
          replaceValue(getNestedMap(content, "commit"), "time",
                  getProperties().getCommitTime());
          // 2. 獲得build所對應的map中time所對應的值,將其轉換為Date,然後將其進行替換
          replaceValue(getNestedMap(content, "build"), "time",
                  getProperties().getDate("build.time"));
      }
      1. 獲得commit所對應的map中time所對應的值,將其轉換為Date,然後將其進行替換
      2. 獲得build所對應的map中time所對應的值,將其轉換為Date,然後將其進行替換

自動裝配

InfoProperties

InfoProperties相關的類–>GitProperties,BuildProperties的自動裝配是在ProjectInfoAutoConfiguration中, ProjectInfoAutoConfiguration聲明瞭如下註解:

@Configuration
@EnableConfigurationProperties(ProjectInfoProperties.class)

ProjectInfoProperties程式碼如下:

@ConfigurationProperties(prefix = "spring.info")
public class ProjectInfoProperties {

    // 構建的具體的資訊,預設載入路徑為META-INF/build-info.properties
    private final Build build = new Build();

    // git具體的資訊,預設載入路徑為classpath:git.properties
    private final Git git = new Git();

    public Build getBuild() {
        return this.build;
    }

    public Git getGit() {
        return this.git;
    }

    /**
     * Make sure that the "spring.git.properties" legacy key is used by default.
     * @param defaultGitLocation the default git location to use
     */
    @Autowired
    void setDefaultGitLocation(
            @Value("${spring.git.properties:classpath:git.properties}") Resource defaultGitLocation) {
        getGit().setLocation(defaultGitLocation);
    }

    /**
     * Build specific info properties.
     */
    public static class Build {

        /**
         * Location of the generated build-info.properties file.
         */
        private Resource location = new ClassPathResource(
                "META-INF/build-info.properties");

        public Resource getLocation() {
            return this.location;
        }

        public void setLocation(Resource location) {
            this.location = location;
        }

    }

    /**
     * Git specific info properties.
     */
    public static class Git {

        /**
         * Location of the generated git.properties file.
         */
        private Resource location;

        public Resource getLocation() {
            return this.location;
        }

        public void setLocation(Resource location) {
            this.location = location;
        }

    }

}

其中Build的預設配置為META-INF/build-info.properties,Git的預設配置為classpath:git.properties

可通過如下屬性來配置:

spring.info.build.location=classpath:META-INF/build-info.properties # Location of the generated build-info.properties file.
spring.info.git.location=classpath:git.properties # Location of the generated git.properties file.

在ProjectInfoAutoConfiguration中宣告2個@Bean方法:

  1. buildProperties,程式碼如下:

    @ConditionalOnResource(resources = "${spring.info.build.location:classpath:META-INF/build-info.properties}")
    @ConditionalOnMissingBean
    @Bean
    public BuildProperties buildProperties() throws Exception {
        return new BuildProperties(
                loadFrom(this.properties.getBuild().getLocation(), "build"));
    }
    • @ConditionalOnResource(resources = “${spring.info.build.location:classpath:META-INF/build-info.properties}”)–>滿足如下條件時生效:

      1. 如果spring.info.build.location配置了,則如果spring.info.build.location:classpath配置路徑下存在資原始檔,則返回true
      2. 如果spring.info.build.location沒配置,則如果在classpath:META-INF/build-info.properties中存在的話,則生效
    • @ConditionalOnMissingBean –> BeanFactory中不存在BuildProperties型別的bean時生效

    其建立BuildProperties時呼叫了loadFrom方法,來載入配置的檔案,並且將檔案中不是build開頭的配置進行過濾.

    loadFrom–> 方法只加載給定location的Properties檔案中以prefix開頭的配置.如下:

    protected Properties loadFrom(Resource location, String prefix) throws IOException {
        String p = prefix.endsWith(".") ? prefix : prefix + ".";
        Properties source = PropertiesLoaderUtils.loadProperties(location);
        Properties target = new Properties();
        for (String key : source.stringPropertyNames()) {
            if (key.startsWith(p)) {
                target.put(key.substring(p.length()), source.get(key));
            }
        }
        return target;
    }
  2. gitProperties,程式碼如下:

    @Conditional(GitResourceAvailableCondition.class)
    @ConditionalOnMissingBean
    @Bean
    public GitProperties gitProperties() throws Exception {
        return new GitProperties(loadFrom(this.properties.getGit().getLocation(), "git"));
    }
    • @ConditionalOnMissingBean–> BeanFactory中不存在GitProperties型別的bean時生效
    • @Conditional(GitResourceAvailableCondition.class) –> 如果以下路徑中任意1個存在則生效:

      1. spring.info.git.location配置的路徑
      2. spring.git.properties配置的路徑
      3. classpath:git.properties配置的路徑

    其建立GitProperties時呼叫了loadFrom方法,來載入配置的檔案,並且將檔案中不是git開頭的配置進行過濾.

InfoContributor

InfoContributor相關的子類的自動裝配在InfoContributorAutoConfiguration中進行了配置,其聲明瞭如下註解:

@Configuration
@AutoConfigureAfter(ProjectInfoAutoConfiguration.class)
@AutoConfigureBefore(EndpointAutoConfiguration.class)
@EnableConfigurationProperties(InfoContributorProperties.class)

InfoContributorProperties程式碼如下:

@ConfigurationProperties("management.info")
public class InfoContributorProperties {

    private final Git git = new Git();

    public Git getGit() {
        return this.git;
    }

    public static class Git {

        /**
         * Mode to use to expose git information.
         */
        private GitInfoContributor.Mode mode = GitInfoContributor.Mode.SIMPLE;

        public GitInfoContributor.Mode getMode() {
            return this.mode;
        }

        public void setMode(GitInfoContributor.Mode mode) {
            this.mode = mode;
        }

    }

}

因此可以通過management.info.git.mode,來配置GitInfoContributor的輸出模式,預設為SIMPLE

InfoContributorAutoConfiguration聲明瞭3個bean方法:

  1. envInfoContributor,程式碼如下:

    @Bean
    @ConditionalOnEnabledInfoContributor("env")
    @Order(DEFAULT_ORDER)
    public EnvironmentInfoContributor envInfoContributor(
            ConfigurableEnvironment environment) {
        return new EnvironmentInfoContributor(environment);
    }
    • @Bean –> 註冊1個id為envInfoContributor,型別為EnvironmentInfoContributor的bean
    • @ConditionalOnEnabledInfoContributor(“env”) –> 如果配置有management.info.env .enabled= true或者配置有management.info.enabled = true. 或者沒有配置時預設匹配
  2. gitInfoContributor,程式碼如下:

    @Bean
    @ConditionalOnEnabledInfoContributor("git")
    @ConditionalOnSingleCandidate(GitProperties.class)
    @ConditionalOnMissingBean
    @Order(DEFAULT_ORDER)
    public GitInfoContributor gitInfoContributor(GitProperties gitProperties) {
        return new GitInfoContributor(gitProperties, this.properties.getGit().getMode());
    }
    • @Bean –> 註冊1個id為gitInfoContributor,型別為GitInfoContributor的bean
    • @ConditionalOnEnabledInfoContributor(“git”) –> 如果配置有management.info.git.enabled= true或者配置有management.info.enabled = true. 或者沒有配置時預設匹配
    • @ConditionalOnMissingBean–> BeanFactory中不存在型別為GitInfoContributor的bean時生效
    • @ConditionalOnSingleCandidate(GitProperties.class) –> 如果BeanFactory中只存在1個GitProperties型別的bean或者存在多個,但是存在1個被指定為Primary的bean時生效
  3. buildInfoContributor,程式碼如下:

    @Bean
    @ConditionalOnEnabledInfoContributor("build")
    @ConditionalOnSingleCandidate(BuildProperties.class)
    @Order(DEFAULT_ORDER)
    public InfoContributor buildInfoContributor(BuildProperties buildProperties) {
        return new BuildInfoContributor(buildProperties);
    }
    • @Bean –> 註冊1個id為buildInfoContributor,型別為InfoContributor的bean
    • @ConditionalOnEnabledInfoContributor(“build”) –> 如果配置有management.info.build.enabled= true或者配置有management.info.enabled = true. 或者沒有配置時預設匹配

實戰

  1. 要先在spring boot的專案中啟用 BuildInfoContributor的配置,需要在META-INF目錄下存在build-info.properties,我們可以spring-boot-maven-plugin來完成,其有5個goal:

    1. spring-boot:repackage,預設goal。在mvn package之後,再次打包可執行的jar/war,同時保留mvn package生成的jar/war為.origin
    2. spring-boot:run,執行Spring Boot應用
    3. spring-boot:start,在mvn integration-test階段,進行Spring Boot應用生命週期的管理
    4. spring-boot:stop,在mvn integration-test階段,進行Spring Boot應用生命週期的管理
    5. spring-boot:build-info,生成Actuator使用的構建資訊檔案build-info.properties.預設輸出路徑為${project.build.outputDirectory}/META-INF/build-info.properties

    因此,我們可以修改pom檔案為如下:

    <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>build-info</goal>
                        </goals>
                    </execution>
                </executions>
    </plugin>

    此時我們執行mvn: clean install ,就可以發現在最終生成的jar包中存在build-info.properties,如下:

    build-info

  2. 同樣,要啟用GitInfoContributor,我們可以在pom檔案中加入如下配置:

    <plugin>
                <groupId>pl.project13.maven</groupId>
                <artifactId>git-commit-id-plugin</artifactId>
                <version>2.1.15</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>revision</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <dotGitDirectory>${project.basedir}/.git</dotGitDirectory>
                </configuration>
    </plugin>

    執行mvn:git-commit-id:revision,就可以發現在最終生成的jar包中存在build-info.properties,如下:

    git-info

  3. {
    git: {
        commit: {
            time: 1517484030000,
            id: "8973672"
        },
        branch: "master"
        },
    build: {
        version: "0.0.1-SNAPSHOT",
        artifact: "spring-boot-analysis",
        name: "spring-boot-analysis",
        group: "com.roncoo",
        time: 1517484169000
        }
    }

    當然我們可以配置management.info.git.mode=FULL,來輸出更多的資訊,試一下吧

參考連結: