转载

在springboot中从classpath下加载文件(翻译)

创建 Spring Boot Web应用程序时,有时需要从类路径加载文件,例如,数据仅作为文件提供。就我而言,我使用 MAXMIND GeoLite2 database 进行位置索引。因此我需要加载文件并创建一个存储在服务器内存中的DatabaseReader对象。

在下面您将找到在WAR和JAR中加载文件的解决方案。

The ResourceLoader

用java开发时,你可以用当前线程获取classloader,然后用它去加载文件,但是在spring框架中提供了你更优雅得解决方法,如 ResourceLoader

你只需要注入对象 ResourceLoader 之后调用它的 getResource("yourPath") 方法即可。

在Spring Boot(WAR)中从资源目录/ classpath加载文件的示例

在以下示例中,我们从类路径中加载一个名为GeoLite2-Country.mmdb的文件作为资源,然后将其作为File对象进行检索。

@Service("geolocationservice")
public class GeoLocationServiceImplimplements GeoLocationService{

    private static final Logger LOGGER = LoggerFactory.getLogger(GeoLocationServiceImpl.class);

    private static DatabaseReader reader = null;

    private ResourceLoader resourceLoader;

    @Autowired
    public GeoLocationServiceImpl(ResourceLoader resourceLoader){
        this.resourceLoader = resourceLoader;
    }

    @PostConstruct
    public void init(){
        try {
            LOGGER.info("GeoLocationServiceImpl: Trying to load GeoLite2-Country database...");

            Resource resource = resourceLoader.getResource("classpath:GeoLite2-Country.mmdb");
            File dbAsFile = resource.getFile();

            // Initialize the reader
            reader = new DatabaseReader
                        .Builder(dbAsFile)
                        .fileMode(Reader.FileMode.MEMORY)
                        .build();

            LOGGER.info("GeoLocationServiceImpl: Database was loaded successfully.");

        } catch (IOException | NullPointerException e) {
            LOGGER.error("Database reader cound not be initialized. ", e);
        }
    }

    @PreDestroy
    public void preDestroy(){
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException e) {
                LOGGER.error("Failed to close the reader.");
            }
        }
    }
}

从Spring Boot JAR中加载文件

如果你期望在springboot jar中从classpath中加载文件,你必须要使用 resource.getInputStream() 方法用输入流去获取文件,如果你试图使用 resource.getFile() 方法,你将会遇到错误,因为这样的话,spring试图去访问(主机的)文件系统的路径,但是在JAR中是做不到的。

@Service("geolocationservice")
public class GeoLocationServiceImplimplements GeoLocationService{

    private static final Logger LOGGER = LoggerFactory.getLogger(GeoLocationServiceImpl.class);

    private static DatabaseReader reader = null;
    private ResourceLoader resourceLoader;

    @Inject
    public GeoLocationServiceImpl(ResourceLoader resourceLoader){
        this.resourceLoader = resourceLoader;
    }

    @PostConstruct
    public void init(){
        try {
            LOGGER.info("GeoLocationServiceImpl: Trying to load GeoLite2-Country database...");

            Resource resource = resourceLoader.getResource("classpath:GeoLite2-Country.mmdb");
            InputStream dbAsStream = resource.getInputStream(); // <-- this is the difference

            // Initialize the reader
            reader = new DatabaseReader
                        .Builder(dbAsStream)
                        .fileMode(Reader.FileMode.MEMORY)
                        .build();

            LOGGER.info("GeoLocationServiceImpl: Database was loaded successfully.");

        } catch (IOException | NullPointerException e) {
            LOGGER.error("Database reader cound not be initialized. ", e);
        }
    }

    @PreDestroy
    public void preDestroy(){
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException e) {
                LOGGER.error("Failed to close the reader.");
            }
        }
    }
}

原文链接

下面说一下我在开发文本分类后台服务时遇到的问题

问题1说明:

用IntelijIEDA开发spring boot web服务时,项目有一个文件需要加载到项目中,因为项目没有构建成jar,在项目中使用 ResourceUtils.getFile("classpath:filepath") 时,项目没有问题,打包成jar部署时,遇到了

java.io.FileNotFoundException: class path resource [static/Sample.txt] cannot be resolved to absolute file path because it does not reside in the  file system: jar:file:/C:/workspace-test/XXX/target/XXX-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/static/Sample.txt

这样的错误,百度查了一大堆没有实质性帮助的结果,后来去StackOverflow上查到了,这样回答的

I have checked your code.If you would like to load a file from classpath in a Spring Boot JAR, then you have to use the resource.getInputStream() rather than resource.getFile().If you try to use resource.getFile() you will receive an error, because Spring tries to access a file system path, but it can not access a path in your JAR

解决方法:

因为项目中用了第三方jar包(这里还有一个开发问题),接口需要文件路径字符串,jar中又不能getFile().getURL(),所以不能获取相对路径,网上有一个把文件读入inputStream中,然后再写到项目的路径下,保存问临时文件,在获取路径。尝试了,还是不行。最后是在jar中读取部署服务的主机上真实存在的资源文件,使用绝对路径(其实我是把jar中文件拷贝到主机的目录下,然后再写上绝对路径)。

问题2说明:

使用了第三方jar,用maven构建项目打包时,会找不到第三方jar资源,因此会报 ClassNotFound 错误

棘角方法

解决方法有很多,我才用把第三方jar发布到本地maven仓库中,但是这样做项目的协同开发不太友好,其他开发者电脑上的本地maven仓库也需要进行相同的jar发布才可以。考虑到我是一个人开发,就没有但有这么多。

翻译它是因为最近写一个web服务时遇到了点问题,这篇文章起了一点作用

谢谢你的打赏

在springboot中从classpath下加载文件(翻译) 支付宝

在springboot中从classpath下加载文件(翻译) 微信

原文  http://tellenw.top/2018/03/23/在springboot中从classpath下加载文件/
正文到此结束
Loading...