【问题标题】:loading from JAR files during deployment vs development在部署与开发期间从 JAR 文件加载
【发布时间】:2009-11-07 21:14:17
【问题描述】:

当我将一些数据加载到我的 java 程序中时,我通常使用 FileInputStream。但是我将程序部署为 jar 文件和 webstart,所以我必须使用 getRessource() 或 getRessourceAsStream() 直接从 jar 文件中加载数据。

现在总是在开发和部署之间切换这段代码很烦人?

有没有办法使这个自动化?即有没有办法知道代码是否从 jar 运行?

当我尝试用这样的 jar 加载它时:

InputStream is = this.getClass().getResourceAsStream("file.txt");

返回的输入流只是 null,尽管该文件肯定在应用程序的根目录中。

谢谢!

【问题讨论】:

    标签: java deployment jar


    【解决方案1】:

    为什么在开发过程中使用FileInputStream?为什么不从一开始就使用getResourceAsStream?只要您将文件放在类路径中的适当位置,就不会有任何问题。它仍然可以是本地文件系统中的文件,而不是 jar 文件。

    在开发时考虑到最终的部署环境会很有帮助。

    编辑:如果你想在你的类路径的 root 目录中找到一些东西,你应该使用:

    InputStream x = getClass().getResourceAsStream("/file.txt");
    

    InputStream x = getClass().getClassLoader().getResourceAsStream("file.txt");
    

    基本上Class.getResourceAsStream会将相关资源解析到包含该类的包; ClassLoader.getResourceAsStream 解析与“根”包相关的所有内容。

    【讨论】:

    • 因为如果文件在子目录中,它似乎不起作用
    • 这只是表明你做错了。如果您请求正确的资源,它肯定可以与子目录一起正常工作。请举一个详细的例子,我们可以帮助你。
    • 谢谢。实际上,在开发过程中,文件是根类的一个目录,因为我所有的类都在“src”目录中
    • @matt:在这种情况下,它不在类路径中。我建议您添加一个“资源”目录并将其添加到您的类路径中,然后它会使事情变得更清晰 - 并且可能更容易打包以进行部署。
    • 谢谢!这是否意味着,使用 GetResourceAsStream 无法从类路径外部加载文件?
    【解决方案2】:

    您可以始终将数据作为资源读取。您只需将数据所在的路径添加到您的类路径。

    如果您的数据保留在 jar 文件中的 WEB-INF/somewhere/mydata.txt 中,您将通过以下方式访问它:

    getClass().getResourceAsStream( "/WEB-INF/somewhere/mydata.txt" )
    

    现在,如果您创建一个开发目录/devel/WEB-INF/somewhere/mydata.txt 并将/devel 放入您的类路径,您的代码将在开发生产中工作。

    在有问题的解释后编辑:

    在您的情况下,this.getClass().getResourceAsStream( "mydata.txt" ) 资源取自 this 的类文件的同一位置。如果你想保留它,那么你必须创建一个目录/devel/<path of package>/mydata.txt 并再次将/devel 添加到你的类路径中。

    【讨论】:

      【解决方案3】:

      如何通过 -D 开关在您的开发环境中设置系统属性?例如java -D:mypropertyname=mypropertyvalue

      您可以在开发环境中的 ant 脚本中设置该属性,其他环境无法获取该属性: 例如

      public static boolean isDevEnvironment(){ return System.getProperty("mypropertyname")!=null;}
      

      您可能会找到一种更好的方法来从现有的System Properties 中破解它

      【讨论】:

        【解决方案4】:

        如果一个文件被认为是您部署的应用程序的一部分(而不是安装特定文件的一部分)并且可以通过类路径定位,那么请考虑始终使用 getResourceAsStream,因为它的工作原理与实际部署方案无关,只要它在类路径中。

        您还可以从相关的 JVM 中找到可用的信息(如果安全管理器允许):

         // Get the location of this class
            Class cls = this.getClass();
            ProtectionDomain pDomain = cls.getProtectionDomain();
            CodeSource cSource = pDomain.getCodeSource();
            URL loc = cSource.getLocation();  // file:/c:/almanac14/examples/
        

        http://www.exampledepot.com/egs/java.lang/ClassOrigin.html?l=rel

        【讨论】:

          【解决方案5】:

          开发与部署之间应该没有任何区别,IHMO。

          Classloader.getResource 或 getResourceAsStream 效果很好,你可以读取资源,甚至可以写入资源。你可以编写自己的Protocol handles 并以 URL/URI 的形式访问所有内容,这样你就可以读取和写入资源,也可以正确识别谁实际提供资源。

          唯一的问题是如果 URLStreamHandlerFactory 已经注册(在 J2EE 应用程序中,容器可以安装工厂,而您没有任何方法可以安装自己的工厂)并且您不能在任何地方使用您的处理程序”。

          知道了这一点,最好实现自己的“资源”。那时当我需要它时,我找不到类似的东西,所以我不得不实现自己的 ResourceManager。对我来说,访问像

          这样的资源看起来更直观
          Resource layout = ResourceManager.resolve("view://layout/main.jsp") 
          

          而不是

          URL layout = Classloader.getResource("some_package/view/layout/main.jsp")
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-06-09
            • 2017-02-07
            • 2012-12-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-12-30
            • 2015-08-27
            相关资源
            最近更新 更多