springboot 加载jar包内配置文件

1、springboot启动 如何加载jar包内注解类?

    springboot的 Application类会自动扫描加载其package 及其子package的类,但是其他package 或 jar中的类不会自动被扫描到, 这时需要配置 扫描路径:

@ComponentScan(basePackages = {"com.ysma.oschina", "com.ysma.csdn"},//指定package
		excludeFilters = {@ComponentScan.Filter(value = Other.class, 
                          type= FilterType.ASSIGNABLE_TYPE)})//排除csdn jar包中个别类
public class OschinaApplication {

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

}
  • @ComponentScan注释类型的参数含义

    basePackages:参数是用于扫描带注释组件的基本包

    basePackageClasses:对basepackages()指定扫描注释组件包类型安全的替代

    excludeFilters:指定不适合组件扫描的类型

    includeFilters:指定哪些类型有资格用于组件扫描

    lazyInit:指定是否应注册扫描的beans为lazy初始化

    useDefaultFilters:指示是否自动检测类的注释

  • @Filter中FilterType包含的类型及意义

    ANNOTATION:注解类型

    ASSIGNABLE_TYPE:ANNOTATION:指定的类型

    ASPECTJ:按照Aspectj的表达式,基本上不会用到

    REGEX:按照正则表达式

    CUSTOM:自定义规则  需实现自定义FilterType 如下:

    

 
public class MyFilterType implements TypeFilter {
 
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
 
        if (metadataReader.getClassMetadata().getClassName().contains("Department")){
            //获取当前类注解的信息
            AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
            for (String s : annotationMetadata.getAnnotationTypes()) {
                System.out.println("当前正在被扫描的类注解类型" + s);
            }
            //获取当前正在扫描类的信息
            ClassMetadata classMetadata = metadataReader.getClassMetadata();
            System.out.println("当前正在被扫描的类的类名" + classMetadata.getClassName());
            //获取当前类的资源信息(类存放的路径...)
            Resource resource = metadataReader.getResource();
            System.out.println("当前正在被扫描的类存放的地址" + resource.getURL());
            return true;
        }
        return false;
    }
}

 

2、jar包内加载资源

  •     路径问题  overview.properties放在resource根目录的config文件夹下

     resource工程路径不行,会自动指定到jar包所在工程资源路径,如 /config/overview.properties

     resource 类路径不行,会自动指定到jar包所在工程类路径,如 config/overview.properties

     classpath路径可行,会自动识别并加载类路径,如classpath:config/overview.properties   此时配置文件放在父工程的classpath目录下

    ResourceUtil实例如下

    


import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.ResourceUtils;

import java.io.*;
import java.net.URL;

/**
 * 资源加载工具
 * 本应用为jar包应用,主要使用classpath路径
 * @see this getClassPathFile
 */
@Slf4j
public class ResourceUtil {

    private static final String PATH_WINDOWS = "\\\\";

    private static final String PATH_LINUX = "/";

    /**
     * 读取jar包文件
     * @param pathName 路径
     * @return inputStream
     * @throws FileNotFoundException
     */
    public static URL getJarURL(String pathName) throws FileNotFoundException {
        try {
            ClassPathResource classPathResource = new ClassPathResource(pathName);
            return classPathResource.getURL();
        } catch (IOException e) {
            log.error("ResourceUtil.getResourcePath 文件不存在, path:{}", pathName);
            throw new FileNotFoundException(pathName + "文件不存在");
        }
    }

    /**
     * jar包内文件的获取
     * @param classPath 因为性对路径问题,通过classpath获取比较好
     * @return 文件 classpath:config/overview.properties
     * @throws FileNotFoundException ex
     */
    @Deprecated
    public static File getClassPathFile(String classPath) throws FileNotFoundException {
        try {
            return ResourceUtils.getFile(classPath);
        } catch (FileNotFoundException e) {
            log.error("ResourceUtil.getResourcePath 文件不存在, path:{}", classPath);
            throw new FileNotFoundException(classPath + "文件不存在");
        }
    }

    /**
     * 获取文件路径
     * @param path 文件路径
     * @return URL
     */
    public static URL getResourcePath(String path) throws FileNotFoundException {
        try {
            //1.以Linux路径为准
            path = path.replaceAll(PATH_WINDOWS, PATH_LINUX);

            /*
              2.依据开头自主选择加载方法
              第一:前面有 "/" 代表了工程的根目录,例如工程名叫做myproject,"/"代表了myproject
              第二:前面没有 "" 代表当前类的目录
             */
            return path.startsWith(PATH_LINUX) ?
                    ResourceUtil.class.getResource(path) :
                    ResourceUtil.class.getClassLoader().getResource(path);
        } catch (Exception e) {
            log.error("ResourceUtil.getResourcePath 文件不存在, path:{}", path);
            throw new FileNotFoundException(path + "文件不存在");
        }
    }

    /**
     * 获取文件
     * @see #getJarURL(String path)
     */
    public static File getJarFile(String path) throws FileNotFoundException {
        try {
            ClassPathResource classPathResource = new ClassPathResource(path);
            InputStream is = classPathResource.getInputStream();
            File tempFile = File.createTempFile("groovy", null);
            IOUtils.copy(is, new FileOutputStream(tempFile));
            return tempFile;
        } catch (IOException e) {
            log.error("ResourceUtil.getResourcePath 文件不存在, path:{}", path);
            throw new FileNotFoundException(path + "文件不存在");
        }
    }
}

 

3、classpath路径问题   如上2中如果配置文件放置在jar包中,则class地址应为:classpath*:config/overview.properties

    classpath和classpath*区别: 

    A:classpath:只会到你的class路径中查找找文件。

    B:classpath*:不仅包含class路径,还包括jar文件中(class路径)进行查找。

    C:在多个classpath中存在同名资源,都需要加载时,那么用classpath:只会加载第一个,这种情况下也需要用classpath*:前缀。

    注意: 用classpath*:需要遍历所有的classpath,所以加载速度是很慢的;因此,在规划的时候,应该尽可能规划好资源文件所在的路径,尽量避免使用classpath*。

转载于:https://my.oschina.net/ysma1987/blog/3092844

  • 1
    点赞
  • 0
    评论
  • 6
    收藏
  • 扫一扫,分享海报

表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
©️2022 CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值