【问题标题】:WildFly - getting resource from WARWildFly - 从 WAR 中获取资源
【发布时间】:2014-07-13 17:54:26
【问题描述】:

我在 WildFly 中使用以下方法从 WAR 文件中获取资源:

this.getClass().getResource(relativePath)

当应用程序部署为分解的 WAR 时,它可以工作。 它过去也可以与压缩 WAR 一起工作。昨天,我在 Eclipse 中对项目进行了清理和重建,但它刚刚停止工作。

当我检查资源根目录时:

logger.info(this.getClass().getResource("/").toExternalForm());

我明白了:

file:/C:/JBoss/wildfly8.1.0.CR1/modules/system/layers/base/org/jboss/as/ejb3/main/timers/

所以,难怪它不起作用。它可能与 JBoss 模块加载有关,但我不知道这是一个错误还是正常行为。

我在 StackOverflow 上发现了各种类似的问题,但没有适用的解决方案。建议之一是像这样使用 ServletContext:

@Resource
private WebServiceContext wsContext;
...
ServletContext servletContext = (ServletContext)this.wsContext.getMessageContext()
        .get(MessageContext.SERVLET_CONTEXT);
servletContext.getResource(resourcePath);

但是,当我尝试以这种方式获取 MessageContext 时,我得到了 IllegalStateException。所以我基本上被卡住了。有什么想法吗?

【问题讨论】:

  • 您试图从哪里访问此代码?
  • 来自 JAX-RS Web 服务中的 @GET 方法。
  • 更具体地说,来自 stateless JAX-RS Web 服务中的 @GET 方法。

标签: java jboss getresource wildfly-8


【解决方案1】:

我遇到了同样的问题,我没有将资源定义为共享模块,而是通过在我的 WAR 中使用 ServletContextListener 来解决这个问题。

在 contextInitialized 方法中,我从 ServletContextEvent 中获取了 ServletContext,并使用它的 getResource("/WEB-INF/myResource") 来获取我的 WAR 文件中资源的 URL。似乎在 ServletContextListener 中, .getResource() 方法按预期解析,而不是“/modules/system/layers/base/org/jboss/as/ejb3/main/timers/” url。然后,该 URL 可以存储在 ServletContext 中,供您的 servlet 或注入的 ApplicationScoped CDI bean 中使用。

@WebListener
public class ServletInitializer implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        try {
            final ServletContext context = sce.getServletContext();
            final URL resourceUrl = context.getResource("/WEB-INF/myResource");
            context.setAttribute("myResourceURL", resourceUrl);
        } catch (final MalformedURLException e) {
            throw new AssertionError("Resource not available in WAR file", e);
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {}
}

@WebListener
public class ServletInitializer implements ServletContextListener {

    @Inject
    private SomeApplicationScopedBean myBean;

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        try {
            final ServletContext context = sce.getServletContext();
            final URL resourceUrl = context.getResource("/WEB-INF/myResource");
            myBean.setResourceUrl(resourceUrl);
        } catch (final MalformedURLException e) {
            throw new AssertionError("Resource not available in WAR file", e);
        }  
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {}
}

【讨论】:

    【解决方案2】:

    我们遇到了类似的问题,我们的错误是我们试图通过原始路径而不是使用资源提供的输入流来访问静态资源 - 即使在部署非爆炸的 .war 时,以下代码也适用于我们-文件。

    final URL resource = this.getClass().getResource(FILE);
    
    try (final InputStream inputStream = resource.openStream();
         final InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
         final BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
        // Use bufferedReader to read the content
    } catch (IOException e) {
        // ...
    }
    

    【讨论】:

    • 谢谢。我现在没有时间检查它,但也许它会帮助其他人。
    【解决方案3】:

    我终于放弃了,把我的资源文件放到了一个新的 JBoss 模块中,正如这个链接中描述的那样。

    https://community.jboss.org/wiki/HowToPutAnExternalFileInTheClasspath

    它可以工作,但缺点是有两个部署目标,所以事情更复杂。从好的方面来说,WAR 文件的大小减小了,如果只是部分资源发生了变化,我不必重新部署应用程序。

    【讨论】:

      【解决方案4】:

      我最近试图弄清楚如何在我自己的 Java 战争中访问文件。以下是java类和资源在war文件中的打包方式:

      WAR
       `-- WEB-INF
              `-- classes (where all the java classes are)
              `-- resourcefiles
                         `-- resourceFile1
      

      我的目标文件是resourceFile1。要获取该文件,我只是在代码中执行了以下操作:

      InputStream inStream = this.class.getClassLoader().getResourceAsStream("resourcefiles/resourceFile1");
      

      在这种情况下,资源文件需要与包含 java 类的类文件夹位于同一文件夹中。希望其他人觉得这很有帮助。

      【讨论】:

        【解决方案5】:

        此示例代码适用于在 openshift 上部署和测试的 Wildfly。 我认为这是一个野蝇问题,我降落野蝇并在本地尝试过,我也得到了错误。

        Check sample project on github

        import org.springframework.web.bind.annotation.RequestMethod;    
        import javax.servlet.http.HttpServletRequest;
        import javax.servlet.http.HttpServletResponse;
        import java.io.File;
        import java.io.FileNotFoundException;
        import java.io.IOException;
        import java.io.InputStream;
        import java.net.URLConnection;
        
        @Controller
        @RequestMapping
        public class FileDownloadController {
        
            private static final Logger logger = LoggerFactory.getLogger(FileDownloadController.class);
        
            private static final String DOC_FILE = "file/ibrahim-karayel.docx";
            private static final String PDF_FILE = "file/ibrahim-karayel.pdf";
        
        
            @RequestMapping(value = "/download/{type}", method = RequestMethod.GET)
            public void downloadFile(HttpServletRequest request, HttpServletResponse response,
                                     @PathVariable("type") String type) throws IOException {
        
                File file = null;
                InputStream inputStream;
                if (type.equalsIgnoreCase("doc")) {
                    inputStream = getClass().getClassLoader().getResourceAsStream(DOC_FILE);
                    file = new File(Thread.currentThread().getContextClassLoader().getResource(DOC_FILE).getFile());
                } else if (type.equalsIgnoreCase("pdf")) {
                    inputStream = getClass().getClassLoader().getResourceAsStream(PDF_FILE);
                    file = new File(Thread.currentThread().getContextClassLoader().getResource(PDF_FILE).getFile());
                } else{
                    throw new FileNotFoundException();
                }
                if (file == null && file.getName() == null) {
                    logger.error("File Not Found -> " + file);
                    throw new FileNotFoundException();
                }
        
                String mimeType = URLConnection.guessContentTypeFromName(file.getName());
                if (mimeType == null) {
                    System.out.println("mimetype is not detectable, will take default");
                    mimeType = "application/octet-stream";
                }
        
                System.out.println("mimetype : " + mimeType);
                response.setContentType(mimeType);
                /* "Content-Disposition : inline" will show viewable types [like images/text/pdf/anything viewable by browser] right on browser
                    while others(zip e.g) will be directly downloaded [may provide save as popup, based on your browser setting.]*/
                response.setHeader("Content-Disposition", String.format("inline; filename=\"" + file.getName() + "\""));
        
                /* "Content-Disposition : attachment" will be directly download, may provide save as popup, based on your browser setting*/
                //response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", file.getName()));
        
                response.setContentLength(inputStream.available());
                IOUtils.copy(inputStream, response.getOutputStream());
                response.flushBuffer();
                inputStream.close();
            }
        }
        

        【讨论】:

          【解决方案6】:

          与 Wildfly 和未爆炸的 WAR 有同样的问题,使用 Spring 和 ServletContextResource 我已经解决了这个问题:

          [org.springframework.core.io.]Resource resource = new ServletContextResource(servletContext, "WEB-INF/classes/resource.png");
          

          在同一个 @Service 类中我也有:

          @Inject
          private ServletContext servletContext;
          

          【讨论】:

            【解决方案7】:

            我决定了:

            @Autowired
            private final ApplicationContext ctx;
            private final Path path = Paths.get("testfiles/load")
            
            ctx.getRosource("classpath:" + path);
            

            【讨论】:

              【解决方案8】:

              我阅读了 this 解决方案,这导致我们在 Wildfly 中使用 getResourceAsStream(...) 而不是 getResource()。我只是在 Wildfly 19 上使用从控制台部署的 myApp.ear 对其进行测试。

              【讨论】:

                猜你喜欢
                • 2013-07-21
                • 2011-04-19
                • 2010-11-25
                • 2015-03-31
                • 2018-10-26
                • 2017-06-10
                • 1970-01-01
                • 2018-10-18
                • 2019-10-27
                相关资源
                最近更新 更多