拓展springboot-actuator,新增项目中依赖jar包版本查看功能

主要思路:

  1. 读取项目路径中所有META-INF下的pom.properties,读取每行的内容,将项目加入到springboot-actuator的endpoint中,最后加入spring的bean中即可;
  2. springboot-actuator的 1.x版本 和 2.x版本 的endpoint写法不同,需要注意
  3. 只需项目启动加载一次,然后放入guava缓存中,后续需要时读取即可
  • 首先需要引入guava版本依赖
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>29.0-jre</version>
</dependency>

  • 创建实体Dependency,用于返回对象属性
package com.xxx.xxx.actuator.entity;

import lombok.Data;

import java.util.Objects;

/**
 * @ author Daly.Dai
 * @ description
 * @ date 2021/6/10
 */
@Data
public class Dependency {
    private String groupId;
    private String artifactId;
    private String version;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Dependency that = (Dependency) o;
        return Objects.equals(groupId, that.groupId) &&
                Objects.equals(artifactId, that.artifactId) &&
                Objects.equals(version, that.version);
    }

    @Override
    public int hashCode() {
        return Objects.hash(groupId, artifactId, version);
    }
}

Endpoint  springboot-actuator 1.x 版本写法

  • Endpoint GetJarVersionEndpoint,用于具体业务代码处理,最后记得加入configuration
package com.xxx.xxx.actuator.endpoint;


import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.kedacom.kdip.actuator.entity.Dependency;
import lombok.SneakyThrows;
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.stereotype.Component;
import org.springframework.util.FileCopyUtils;

import javax.annotation.PostConstruct;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;


// getJarVersion 用于访问接口
@ConfigurationProperties(prefix = "endpoints.getJarVersion")
@Component
public class GetJarVersionEndpoint extends AbstractEndpoint<Set<Dependency>> {

    // 创建缓存对象,使用guava缓存,用于在项目初始加载时候进行缓存
    private static final Cache<String, Set<Dependency>> dependencyCache = CacheBuilder.newBuilder().build();

    private static final String DEPENDENCY_KEY = "dependencies";

    public GetJarVersionEndpoint() {
        super("getJarVersion");
    }

    // 从缓存获取
    @Override
    public Set<Dependency> invoke() {
        return dependencyCache.getIfPresent(DEPENDENCY_KEY);
    }


    // 项目初始i执行一次,并加入缓存
    @SneakyThrows
    @PostConstruct
    private void initDependency() {
        Set<Dependency> dependencies = new LinkedHashSet<>();
        // 此方法读取pom.properties文件
        PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver();
        Resource[] resources_1 = pathMatchingResourcePatternResolver.getResources(ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + "**/META-INF/**/pom.properties");
        for (Resource resource : resources_1) {
            Dependency dependency = new Dependency();
            // 从jar包读取的文件需要转为流,再转化为字节,然后解析
            byte[] data = FileCopyUtils.copyToByteArray(resource.getInputStream());
            // 转化为String后,根据实际内容进行分割,此处根据换行符进行分割
            String[] content = new String(data, Charset.forName("utf-8")).split("\n");
            List<String> list = Arrays.asList(content);
            for (String string : list) {
                if (string.startsWith("version=") || string.startsWith("groupId=") || string.startsWith("artifactId=")) {
                    if (string.startsWith("version=")) {
                        dependency.setVersion(string.replace("version=", ""));
                    }
                    if (string.startsWith("groupId=")) {
                        dependency.setGroupId(string.replace("groupId=", ""));
                    }
                    if (string.startsWith("artifactId=")) {
                        dependency.setArtifactId(string.replace("artifactId=", ""));
                    }
                }
            }
            dependencies.add(dependency);
        }
        // 存入guava缓存
        dependencyCache.put(DEPENDENCY_KEY, dependencies);
    }

    // 此代码未用到
    private static Resource[] concat(Resource[] a, Resource[] b) {
        if (a == null) {
            a = new Resource[0];
        }
        if (b == null) {
            b = new Resource[0];
        }
        Resource[] c = new Resource[a.length + b.length];
        System.arraycopy(a, 0, c, 0, a.length);
        System.arraycopy(b, 0, c, a.length, b.length);
        return c;
    }


}
  •  加入configuration,读取为spring bean

@Configuration
@EnableConfigurationProperties({GetJarVersionEndpoint.class})
public class ActuatorAutoConfiguration {

}

Endpoint  springboot-actuator 2.x 版本写法

package com.xxx.xxx.actuator.endpoint;


import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.kedacom.kdip.actuator.entity.Dependency;
import lombok.SneakyThrows;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpoint;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.stereotype.Component;
import org.springframework.util.FileCopyUtils;

import javax.annotation.PostConstruct;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

@WebEndpoint(id = "getJarVersion")
@Component
public class GetJarVersionEndpoint {

    private static final Cache<String, Set<Dependency>> dependencyCache = CacheBuilder.newBuilder().build();

    private static final String DEPENDENCY_KEY = "dependencies";

    @ReadOperation
    public Set<Dependency> list() {
        return dependencyCache.getIfPresent(DEPENDENCY_KEY);
    }

    @SneakyThrows
    @PostConstruct
    private void initDependency() {
        Set<Dependency> dependencies = new LinkedHashSet<>();
        PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver();
        Resource[] resources_1 = pathMatchingResourcePatternResolver.getResources(ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + "**/META-INF/**/pom.properties");
        for (Resource resource : resources_1) {
            Dependency dependency = new Dependency();
            byte[] data = FileCopyUtils.copyToByteArray(resource.getInputStream());
            String[] content = new String(data, Charset.forName("utf-8")).split("\n");
            List<String> list = Arrays.asList(content);
            for (String string : list) {
                if (string.startsWith("version=") || string.startsWith("groupId=") || string.startsWith("artifactId=")) {
                    if (string.startsWith("version=")) {
                        dependency.setVersion(string.replace("version=", ""));
                    }
                    if (string.startsWith("groupId=")) {
                        dependency.setGroupId(string.replace("groupId=", ""));
                    }
                    if (string.startsWith("artifactId=")) {
                        dependency.setArtifactId(string.replace("artifactId=", ""));
                    }
                }
            }
            dependencies.add(dependency);
        }
        dependencyCache.put(DEPENDENCY_KEY, dependencies);
    }

    private static Resource[] concat(Resource[] a, Resource[] b) {
        if (a == null) {
            a = new Resource[0];
        }
        if (b == null) {
            b = new Resource[0];
        }
        Resource[] c = new Resource[a.length + b.length];
        System.arraycopy(a, 0, c, 0, a.length);
        System.arraycopy(b, 0, c, a.length, b.length);
        return c;
    }
}
  • 最后通过 http://ip:port/actuator/getJarVersion 访问
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值