SpringBoot如何读取war包jar包和Resource资源

这篇文章主要介绍了SpringBoot如何读取war包jar包和Resource资源,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

场景描述

在开发过程中我们经常会碰到要在代码中获取资源文件的情况,而我在最近在SpringBoot项目中时碰到一个问题,就是在本地运行时,获取本地的xml资源文件是能够获取到的,但是项目打成war包jar包启动运行时,就会发生问题,报找不到资源文件的错误。然后经过寻找排查确定了是下面代码通过ClassLoader获取路径的时候出错了。

常用方式:

/**
 * @author mazhq
 * @Title: TestMain
 * @ProjectName: zeus
 * @Description: TODO
 * @date 2019/3/5 16:10
 */
public class TestMain {
  public static void main(String[] args) {
    String path = TestMain.class.getClassLoader().getResource("1.xml").getPath();
    System.out.println(path);
  }
 /**
   * 输出:
   *
   */D:/demo_projects/sc-architecture/service-hi/target/classes/1.xml
   */
}

但是在将SpringBoot打包放到Linux服务器启动打印的目录为

/data/zeus/service-hi-1.0.0-SNAPSHOT.war!/WEB-INF/classes!/1.xml

可以看到在Linux中无法直接访问未经解压的文件,所以就会找不到文件。

解决办法

1. 通过ClassLoader的getResourceAsStream()方法获取其流,就能够获取到。

读取jar里面的文件,我们只能用流去读取,不能用File

public class TestMain {
  public static void main(String[] args) {
    try {
      List<String> content = IOUtils.readLines(TestMain.class.getClassLoader().getResourceAsStream("1.xml"), "UTF-8");
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

2. 采用绝对路径将文件放到服务器某个路径,在application.properties中配置路径读取。

3. 不推荐:将内容放到数据库中。

获取资源的两种方式

通常在开发过程中会碰到读取配置文件的问题,一般有两种方式进行读取。一种是Class.getResource(String path),一种是ClassLoader.getResource(String path),这两种虽然都能读取文件,但是在path的填写上有一点点的不同。

Class.getResource

path以/开头:则是从ClassPath根下获取

path不以/开头:默认是从此类所在的包下取资源

下面有个例子

public class TestMain {
  public static void main(String[] args) {
    System.out.println(TestMain.class.getResource("/"));
    System.out.println(TestMain.class.getResource(""));
  }
  /**
   * 输出:
   *
   * file:/D:/demo_projects/sc-architecture/service-hi/target/classes/
   * file:/D:/demo_projects/sc-architecture/service-hi/target/classes/com/mazhq/servicehi/
   */
}

那么读取在resource下的1.xml,就如下的获取方法

public class TestMain {
  public static void main(String[] args) {
    System.out.println(TestMain.class.getResource("/1.xml"));
    System.out.println(TestMain.class.getResource("../../../1.xml"));
  }
  /**
   * 输出:
   *
   * file:/D:/demo_projects/sc-architecture/service-hi/target/classes/1.xml
   * file:/D:/demo_projects/sc-architecture/service-hi/target/classes/1.xml
   */
}

ClassLoader.getResource

ClassLoader.getResource的path中不能以/开头,path是默认是从根目录下进行读取的

代码如下:

public class TestMain {
  public static void main(String[] args) {
    System.out.println(TestMain.class.getClassLoader().getResource(""));
    System.out.println(TestMain.class.getClassLoader().getResource("/"));
  }
  /**
   * 输出:
   *
   * file:/D:/demo_projects/sc-architecture/service-hi/target/classes/
   * null
   */
}

从上面例子我们可以看到

TestMain.class.getClassLoader().getResource("")=TestMain.class.getResource("/")

两个获取资源文件的差别

其实查看Class.getResource中可以看到

public java.net.URL getResource(String name) {
    name = resolveName(name);
    ClassLoader cl = getClassLoader0();
    if (cl==null) {
      // A system class.
      return ClassLoader.getSystemResource(name);
    }
    return cl.getResource(name);
  }

他最后调用的还是ClassLoader.getResource这个方法,那么为什么会有path的差别呢,因为其resolveName方法中对传的/进行了解析,解析为了空字符串。

resolveName 方法实现如下:

private String resolveName(String name) {
    if (name == null) {
      return name;
    }
    if (!name.startsWith("/")) {
      Class<?> c = this;
      while (c.isArray()) {
        c = c.getComponentType();
      }
      String baseName = c.getName();
      int index = baseName.lastIndexOf('.');
      if (index != -1) {
        name = baseName.substring(0, index).replace('.', '/')
          +"/"+name;
      }
    } else {
      name = name.substring(1);
    }
    return name;
  }<br><br>  //传入 "/" 返回 ""

最后:大家用的时候注意一下这些问题,避免在这个上面耽误时间。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Spring实战之ResourceLoader接口资源加载用法示例

    本文实例讲述了Spring实战之ResourceLoader接口资源加载用法.分享给大家供大家参考,具体如下: 一 代码 package lee; import org.springframework.context.*; import org.springframework.context.support.*; import org.springframework.core.io.Resource; import org.dom4j.*; import org.dom4j.io.*; impo

  • vue-resource post数据时碰到Django csrf问题的解决

    公司最近用vue写前端,用vue-resource遇到的一些问题,现在记录下来. vue-resource post数据 this.$http.post('/someUrl',data, [options]).then(function(response){ // 响应成功回调 }, function(response){ // 响应错误回调 }); vue-resource 向后端请求api, 公司的后台是用Django 开发的,Django为了防止跨站请求伪造,即csrf攻击,提供了Csrf

  • Java try-with-resource语法使用解析

    背景 众所周知,所有被打开的系统资源,比如流.文件或者Socket连接等,都需要被开发者手动关闭,否则随着程序的不断运行,资源泄露将会累积成重大的生产事故. 在Java的江湖中,存在着一种名为finally的功夫,它可以保证当你习武走火入魔之时,还可以做一些自救的操作.在远古时代,处理资源关闭的代码通常写在finally块中.然而,如果你同时打开了多个资源,那么将会出现噩梦般的场景: public class Demo { public static void main(String[] arg

  • Springboot项目打war包docker包找不到resource下静态资源的解决方案

    前一段时间遇到一个问题,是关于读取项目中文件资源的问题.我是一个maven工程 我把一张照片放到resource下面,然后在本地读取的时候可以读取到,但是一旦打成WAR包以后就总是包找不到文件资源错误.我的war包是springboot打的war包,是内嵌的tomcat所以不解压,然后系统去找路径的时候会发现是个WAR包,而图片在WAR包内,所以找不到. 为了解决这个问题,我走了好多弯路,一直在路径上花费时间. 一开始使用修改配置文件的方式: # 配置静态资源访问前缀 spring.mvc.st

  • SpringBoot读取resource文件代码实例

    Java标准库中的java.net.URL类和标准处理器对于处理低层的资源没有提供很好的功能.例如,并没有提供一个URL的实现能够从classpath或者ServletContext中读取资源等等.因此,在Spring中提供了这样一个Resource接口,能够更加方便的读取各种资源. 1.使用resourceUtil File file = ResourceUtils.getFile("classpath:config/city.config.json"); 2.注解,注入 publi

  • Spring Boot读取resources目录文件方法详解

    这篇文章主要介绍了Spring Boot读取resources目录文件方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在Java编码过程中,我们常常希望读取项目内的配置文件,按照Maven的习惯,这些文件一般放在项目的src/main/resources下,因此,合同协议PDF模板.Excel格式的统计报表等模板的存放位置是resources/template/test.pdf,下面提供两种读取方式,它们分别在windows和Linux

  • 详解SpringBoot开发使用@ImportResource注解影响拦截器

    问题描述 今天在给SpringBoot项目配置拦截器的时候发现怎么都进不到拦截器的方法里面,在搜索引擎上看了无数篇关于配置拦截器的文章都没有找到解决方案. 就在我准备放弃的时候,在 CSDN 上发现了一篇文章,说的是SpringBoot 用了@ImportResource 配置的拦截器就不起作用了.于是我就赶紧到Application启动类看了一眼,果然项目中使用了@ImportResource 注解用于配置系统的参数. 代码如下: 启动类配置 package com.xx.xxx; impor

  • SpringBoot如何读取war包jar包和Resource资源

    这篇文章主要介绍了SpringBoot如何读取war包jar包和Resource资源,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 场景描述 在开发过程中我们经常会碰到要在代码中获取资源文件的情况,而我在最近在SpringBoot项目中时碰到一个问题,就是在本地运行时,获取本地的xml资源文件是能够获取到的,但是项目打成war包jar包启动运行时,就会发生问题,报找不到资源文件的错误.然后经过寻找排查确定了是下面代码通过ClassLoader获

  • springboot的war和jar包的使用详解

    本篇和大家分享的是通过maven对springboot中打war包和jar包:war通常来说生成后直接放到tomcat的webapps下面就行,tomcat配置自动解压war,而jar一般通过命令行部署和启动: 首先,来实战怎么生成war包,主要来说可以分为3个步骤: •程序入口改造 •排除springboot内置tomcat •spring-boot-maven-plugin插件中配置程序入口 程序入口改造,我们需要把springboot的main入口屏蔽掉,然后继承SpringBootSer

  • SpringBoot项目引入第三方sdk jar包的解决方案

    目录 场景 解决方案 总结 参考资料 场景 对接第三方接口,他们有自己封装的SDK jar包,但是没有对外统一的maven仓库.我们自己项目需要集成这个离线的jar包? 解决方案 1. jar上传到本地的maven仓库,然后通过pom依赖,引入第三方jar包.个人觉得这个是比较理想的解决方案. 2.第二种方案,将第三方的sdk jar包放到项目里面.我们是微服务应用打成的jar包,有类似的可以做个参考. 具体的做法: 2.1 引用本地jar包,我的是将jar包放在/resources/lib/下

  • 解决springboot 部署到 weblogic 中 jar 包冲突的问题

    目录 背景 问题1 问题2 背景 某项目,客户要求使用已有的 weblogic 部署已经开发好的 springboot,于是乎对 springboot 进行了部分配置的调整,主要包括去除 tomcat 依赖,增加启动类的处理. 一般都会比较顺利,实际上总会遇到些小问题. 本文不赘述如何在 weblogic 中部署项目,如果你有需要,可以访问https://www.jb51.net/article/218458.htm 参考该文章. 问题1 打包后发布到 weblogic 上启动时,如下图所示的错

  • 浅谈SpringBoot项目打成war和jar的区别

    首先给大家来讲一个我们遇到的一个奇怪的问题: 1.我的一个springboot项目,用mvn install打包成jar,换一台有jdk的机器就直接可以用java -jar 项目名.jar的方式运行,没任何问题,为什么这里不需要tomcat也可以运行了? 2.然后我打包成war放进tomcat运行,发现端口号变成tomcat默认的8080(我在server.port中设置端口8090)项目名称也必须加上了. 也就是说我在原来的机器的IDEA中运行,项目接口地址为 ip:8090/listall,

  • springboot读取文件,打成jar包后访问不到的解决

    springboot读取文件,打成jar包后访问不到 最新开发出现一种情况,springboot打成jar包后读取不到文件,原因是打包之后,文件的虚拟路径是无效的,只能通过流去读取. 文件在resources下 public void test() { List<String> names = new ArrayList<>(); InputStreamReader read = null; try { ClassPathResource resource = new ClassP

  • 解决IDEA无法读取maven镜像,jar包下载失败的问题

    最近从公司私服下载jar包一直失败,之前的解决方法是手动下载项目,自己打包来解决的,最近忍无可忍,自己研究了o(╥﹏╥)o. 原因 idea现在的版本要求maven的镜像必须是https的,而之前的配置的镜像都是http的,所以镜像加载失败了,读取的是maven默认的仓库,所以下不下来. 我为什么要手贱升级,明明18年版的也可以用的o(╥﹏╥)o 解决 设置https库 国内的镜像基本都有https版本了(公司的就要公司自己配置了),设置一下 <!--阿里仓库--> <mirror>

  • SpringBoot项目打成war和jar的区别说明

    目录 jar包和war包的区别 [格式特点] [建立的条件] 给大家讲讲如何将springboot项目打包成jar和war 一.打包成jar 1.先new 一个Spring Starter Project 2.创建完成后项目的pom如下 3.打成jar包(通过maven命令的方式) 二.打包成war包形式 1.可以在刚才创建的项目上做改动 2.修改pom.xml 3.如果我们的SpringBoot是使用html作为前端页面开发没有问题 4.打包成war:使用mvn clean package 首

  • 仿iPhone风格对话框(附件包含例子/jar包/jar包源码)

    效果图: 这个对框完全继承.仿照AlertDialog,只是实现了自定义效果.另外,没有实现setIcon,因为iphone中的对话框多数都没有图标. 附件包含例子.jar包.jar包源码.文件简介: aIphoneDialogTest.rar 这是示例工程 使用时注意先要在build path中导入iPhoneDialogLib.rar中的jar包 iPhoneDialogLib.rar 这是控件jar包及资源文件 使用时先备份自己的strings.xml,然后将三个目录下的资源文件复制到项目

  • 使用Springboot 打jar包实现分离依赖lib和配置

    目录 打jar包实现分离依赖lib和配置 操作步骤 Springboot中jar包分离(分离lib包) jar包分离介绍 jar包分离实施步骤 小结一下 打jar包实现分离依赖lib和配置 为了业务需要配置文件和jar分离,便于使用者修改配置信息,在网上找了很久,最终找到一个简单有效的方法. 操作步骤 打开project工程的pom.xml文件,将下列配置粘贴到pom文件中: <properties> <java.version>1.8</java.version> &

随机推荐