【问题标题】:How to access file in the static resources(WEB-INF) folder from the referencing java project?如何从引用的java项目访问静态资源(WEB-INF)文件夹中的文件?
【发布时间】:2012-05-25 05:03:57
【问题描述】:

我有一个 Web 应用程序,其中包含我的一个应用程序服务的配置 xml 文件,该文件作为 spring bean 公开。 此外,我在同一个工作区中有一个独立的 java 应用程序(它从 pom.xml 引用我的 web 应用程序项目),它使用 Spring TestContext 框架运行测试,其中一个测试检查该 XML 文件的配置。

但是,我在从独立应用程序访问此 xml 文件时遇到问题:

在设置测试之前,在我之前的配置中,该文件是通过 ServletContext 访问的,位于 WEB-INF/ 文件夹中。但是,为了使其可以从测试项目中访问,我必须将其移动到 source/ 文件夹并使用 getClassLoader().getResourceAsStream() 方法而不是 ServletContext 方法加载它。但这使得编辑文件变得很麻烦,因为每次都必须重新部署应用程序。

是否可以将文件保留在 WEB-INF/ 文件夹中,但在测试运行期间从引用项目中加载它?

附:目前它是一个带有 Tomcat 服务器的 STS 项目。

【问题讨论】:

    标签: java spring jakarta-ee maven pom.xml


    【解决方案1】:

    如果该文件应该存放在 WEB-INF/ 文件夹下,请务必将其保存。

    对于从命令行执行的测试类。您可以在您知道位于类路径根目录中的文件(例如 application.properties 文件)上使用 getClassLoader().getResource()。从那里你知道你的项目的结构以及在哪里可以找到相对于属性文件的 WEB-INF/。由于它返回一个 URL,因此您可以使用它来找出您要查找的 XML 文件的路径。

    URL url = this.getClass().getClassLoader().getResource("application.properties");
    System.out.println(url.getPath());
    
    File file = new File(url.getFile());
    System.out.println(file);
    
    // now use the Files' path to obtain references to your WEB-INF folder
    

    希望你觉得这很有用。我不得不对您的测试类的运行方式等做出假设。

    看看File Class,它是可能对你有用的getPath()、getAbsolutePath()和getParent()方法。

    【讨论】:

    • 谢谢,我会考虑的。然而问题是,在一种情况下,文件应该通过 ServletContext 访问,但在另一种情况下,通过类加载器(我想这在某些应用程序服务器上可能无法正常工作)。所以问题是我应该在两种情况下(网络和测试运行)的资源加载方法之间切换。
    • 是的,您是正确的,因为您有一个 Web 应用程序,它应该使用标准 ServletContext 来访问 WEB-INF 文件夹中的文件。然后只为您的测试代码实现这个 jiggery-pokery。
    【解决方案2】:

    在测试运行之前,我最终使用 Spring MockServletContext 类并将其直接注入到我的服务 bean 中,因为我的服务实现了 ServletContextAware

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = { "/test-ctx.xml" } ) 
    public class SomeServiceTest {
    
    @Autowired
    private MyServletContextAwareService myService;
    
    @Before
    public void before(){
                //notice that I had to use relative path because the file is not available in the test project
        MockServletContext mockServletContext = new MockServletContext("file:../<my web project name>/src/main/webapp"); 
    
        myService.setServletContext(mockServletContext);        
    }
    

    如果我有几个使用 Servlet 上下文的类,那么更好的解决方案是使用 WebApplicationContext 而不是默认的(当前由 DelegatingSmartContextLoader 提供),但它需要实现自定义 ContextLoader 类并将其类名传递给@ContextConfiguration 注释。

    另一种更清洁的解决方案后来我想到的是重构服务并通过@Autowired注入ServletContext而不是与ServletContextAware混淆,并提供相应类型的bean (实际上是一个MockServletContext 实例)。

    将来可能会在 Spring 中添加对来自测试类的 MockServletContext 的直接支持,请参阅 SPR-5399SPR-5243

    春季 3.2 更新 在 Spring 3.2 中,servlet 上下文的初始化变得像添加一个 @WebAppConfiguration 注释一样简单:

    @RunWith(SpringJUnit4ClassRunner.class)
    @WebAppConfiguration("file:../<my web project name>/src/main/webapp")
    @ContextConfiguration(locations = { "/test-ctx.xml" } ) 
    public class SomeServiceTest {
    

    详情见the article

    【讨论】:

      【解决方案3】:

      这是一个类路径资源,所以把它放在类路径上:$webapp/WEB-INF/classes

      Maven 项目在打包 webapp 时会将 $module/src/main/resources 中的内容复制到此位置。 (前者是一个源路径,后者 - WEB-INF/classes - 根据规范,总是由 servlet 容器放在类路径中。)

      【讨论】:

      • 它已经在类路径中 - 现在我需要将它移回 Web 内容文件夹,因为每次文件更改时都需要重新部署应用程序,这会减慢开发速度。
      • 你可能想使用码头插件然后运行你的 webapp 'unassembled'...这应该会有所帮助:wiki.eclipse.org/Jetty/Feature/…
      • +1 用于有趣的码头链接,但现在我的测试在没有网络服务器的情况下运行良好(通过 Spring 测试上下文框架)
      【解决方案4】:

      在一个 Maven 项目中,我遇到了同样的问题。我没有 servletContext,无法访问静态文件 WEB-INF 目录。 我通过向 pom.xml 添加条目来获得解决方案,这使我可以访问该目录。它实际上包含了这个类路径的路径。

      PS:我使用的是Tomcat容器

      <project>
          <build>
          <resources>
              <resource>
                  <directory>src/main/webapp/WEB-INF</directory>
              </resource>
          </resources>
      </project>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-04-24
        • 2013-08-11
        • 2011-01-25
        • 1970-01-01
        • 2015-07-29
        • 2020-07-20
        相关资源
        最近更新 更多