为什么项目布局资源与Java源代码分开?

时间:2011-01-28 16:20:57

标签: java maven layout resources

为什么maven将资源保存在Java源的单独“源文件夹”中?

根据我的经验,在Java中,资源文件大多被视为Java源文件,当“编译”时,只需要按类复制,最终打包在jar中,并由< em> classloader 的方法getResource / getResourceAsStream,通过classpath

我个人认为将资源文件与Java源分开是一种无用的复杂性。

  1. 您怎么看?
  2. maven是否有充分理由将资源与资源分开?
  3. 在使用src/main/resourcessrc/test/resources并保留时,是否有任何反指示? 使用maven的src/main/javasrc/test/java中的资源?

8 个答案:

答案 0 :(得分:14)

尚未提出的一点是,您显然习惯于查看仅包含Java源代码的项目。但是,如果你投入其他一些源文件类型,我认为组织更有意义,例如:

  • 的src /主
    • 资源
    • 的java
    • 常规

每个子目录都有一个特定的文件分类:

  • java - &gt;编译为java文件的东西
  • groovy - &gt;编译为groovy脚本的东西
  • 资源 - &gt;用于任何...的未编译数据(也可以过滤这些数据以添加编译时信息)

也(正如我已经在一些评论中指出的那样),我通常不会使资源目录变平。文件可以根据需要嵌套到类似于包的结构或其他子目录中(对我的组织意识)。

答案 1 :(得分:8)

为了简单和更容易访问,我们在java源路径中保留了一些资源。这使得我们在GUI级别上作为速度模板进行开发时非常方便,因此它们接近于控制器Java代码。但是你必须告诉maven在src / main / java中加入非java东西,在你的pom文件中添加这样的东西。

<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.1.1</version>
                <configuration>
                <webResources>
                    <resource>
                        <directory>src/main/java</directory>
                        <targetPath>WEB-INF/classes</targetPath>
                      <includes>
                        <include>**/*.properties</include>
                        <include>**/*.xml</include>
                        <include>**/*.htm</include>
                        <include>**/*.html</include>
                        <include>**/*.css</include>
                        <include>**/*.js</include>
                      </includes>
                    </resource>
                    <resource>
                        <directory>src/main/resources</directory>
                      <excludes>
                        <exclude>**/log4j.xml</exclude>
                      </excludes>
                    </resource>
                </webResources>
                </configuration>
            </plugin>

答案 2 :(得分:6)

你怎么看? 我认为Maven背后的人应该进行一些“关注点分离”。使用Maven的首要原因是依赖管理,但为什么搅拌机应该告诉我如何剥果?对我来说根本没用。

maven是否有充分理由将资源与资源分开? 在一个java项目中,包结构的重复,不是一次,而是三次,给项目增加了不必要的工作,增加了错误的风险,降低了代码的敏捷性。

答案 3 :(得分:4)

我试着自己给出答案。

  

您怎么看?

这是一种无用的额外复杂性。因此是错误的:见下文。

  

maven是否有充分理由将资源与资源分开?

我想到的唯一原因是,对于某些平台而言,这可能是一种很好的做法。例如,在Mac OSX应用程序中,资源与二进制文件分开打包(在不同的子文件夹中)。

我认为“外部”资源和配置文件,即未在最终工件(jar文件)中打包的资源和配置文件,有充分的理由与源文件分开。因此,当maven打包jar时,他知道不必包含这些文件,因为例如,我们希望它们在jar外部,以便允许用户将这些文件编辑为配置。

但是,对于在jar中打包在一起的东西(比如翻译字符串和xml元数据,例如hibernate映射和spring配置),没有充分的理由将它们放在一个单独的位置,除非我们期望我们的用户在部署后手动更改它们,作为配置过程的一部分。

可以使用与类相同的包结构来组织资源,因此如果包xyz中有一个类,您可能希望在同一个包中拥有它所依赖的资源,因为它们代表相同的“逻辑单元” “:在这种情况下,将它们放在两个单独的文件夹中会导致在包重构和重组期间需要额外注意,因为您希望保持事物同步。 ClassLoader还提供了在getResourceAsStream()方法中指定相对路径的可能性。因此,如果您有类x.y.z.MyClass,则可以执行getClass()。getResourceAsStream(“foo-bar.properties”),并且将从相同的包“x.y.z”加载资源。因此,当它们具有严格的依赖性时,将它们保持在一起是非常有用的。

对于需要在可部署工件中保持独立的外部资源,将它们分开是一件好事,但在这种情况下我不明白为什么maven会对待src / main / resources作为“java源文件夹”(maven-eclipse-plugin),因为它们实际上不能在类路径中,而是通过文件系统作为普通文件访问,特别是你不希望那些文件包含在jar中在maven构建期间。这是应用程序图标,您可能希望放在/ etc目录中的配置文件等情况。

总之,在我认为maven如何处理资源方面存在一些问题:如果它们是“外部”资源,那么maven就没有理由将它们打包在最终的工件(jar)中。如果它们不是“外部”,则没有理由将它们保存在单独的“源文件夹”中。

  

有没有使用src / main / resources和src / test / resources并使用maven在src / main / java和src / test / java中保留资源的计数器指示?

我不知道。

大部分时间我都使用默认的maven布局来玩资源,但有几次我没有;采取预防措施来声明pom中的非标准资源目录位置(请参阅resourcessuper-pom)。 可以改变maven项目的目录结构,在pom中指定它:

 <build>
    <directory>target</directory>
    <outputDirectory>target/classes</outputDirectory>
    <finalName>${artifactId}-${version}</finalName>
    <testOutputDirectory>target/test-classes</testOutputDirectory>
    <sourceDirectory>src/main/java</sourceDirectory>
    <scriptSourceDirectory>src/main/scripts</scriptSourceDirectory>
    <testSourceDirectory>src/test/java</testSourceDirectory>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
      </resource>
    </resources>
    <testResources>
      <testResource>
        <directory>src/test/resources</directory>
      </testResource>
    </testResources>
  </build>

我没有发现它的特殊问题。

我希望maven们再次考虑这个约定,因为拥有一个更简单的项目结构可以帮助开发人员更多地关注开发,而不是在浏览应用程序代码时在项目结构中找到几个文件夹周围的东西。

答案 4 :(得分:2)

我区分两者的方式是java文件夹默认不允许在生成的jar中构建任何内容,除了我列出的文件类型(例如*.class*.html*.properties如果你正在使用Wicket,而resources中的所有内容都将被复制到构建中,除了我列出的少数例外。

当然这只是我的私人约定,我自己也坚持。

答案 5 :(得分:2)

  

1)你怎么看?

我认为,这是一个很好的惯例。

  

2)maven是否有充分理由将资源与资源分开?

是。你遵循惯例。拥有项目代码访问权限的每个人都知道在哪里查找代码以及其他所有内容。当然,测试用例在哪里。当该插件执行时,将会发生什么文件。

  

3)是否有使用src / main / resources和src / test / resources以及使用maven在src / main / java和src / test / java中保留资源的计数器指示?

没有反指示。这是常规问题,您安排自己的代码的方式没有任何问题。实际上,如果您创建了一个Wicket项目,您将看到您的HTML和Java代码在Java包中保持并行。但是,它只是Wicket,你知道HTML将在Java文件的一边。但其他一切都在resources文件夹中。

答案 6 :(得分:0)

也许我是这里唯一一个不是来自Java背景的人。我认为混合资源和代码非常混乱。关注点分离使您的项目变得更清晰,更容易理解/维护。

我尝试将自己的目录约定应用于我的所有软件开发项目:

  • bin:用户使用的最终二进制文件
  • build:中间二进制文件,它们可能在构建后删除
  • lib:外部库
  • src:仅源代码(在本例中为Java源文件)
  • 资源:所有资源(配置文件,xmls,图像,html等)
  • docs:documentation

当我需要更改此目录结构时,我很少找到开发上下文。

使用Maven,如果要进行快速设置,请使用默认值。如果要使用目录约定,只需更改pom.xml中的设置,如前所述。但请注意,某些Maven插件会考虑将默认的Maven目录用于资源/源/输出二进制文件,如果更改这些目录,则需要调整一些插件设置。

答案 7 :(得分:0)

我认为代码/资源分离通常很有用:

  1. 包必须遵循Java规范规则,例如不允许使用保留字,如'int'。在源代码文件夹中包含非法包会令人困惑。

  2. 资源具有实例性,类具有,类,自然。例如,您可能在同一个包中有类ContinentCountry,但资源更好地组织为树:

    • 非洲/
      • morocco.txt
      • kenya.txt
    • 欧洲/
      • poland.txt
  3. 在我看来,资源结构比代码结构更稳定。代码重构经常发生,类从包到包移动以获得更好的可读性。在重构上移动资源的义务阻碍了开发人员重构。

  4. 如果仅需要1%的资源文件需要分离的资源文件夹,则将剩余的99%移至该文件夹并将资源仅保留在单个位置是合理的。

  5. 但是,有时将资源和Java代码保持在一起很有用。例如,单元测试比较输入和输出 - 很高兴将带有输入和输出的文件放在与单元测试代码相同的文件夹中。