5

我正在使用以下方法从 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。所以我基本上被卡住了。有任何想法吗?

4

8 回答 8

4

我遇到了同样的问题,我没有将资源定义为共享模块,而是通过在我的 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) {}
}
于 2014-12-07T17:00:25.400 回答
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) {
    // ...
}
于 2014-12-02T08:40:02.377 回答
1

我最近试图弄清楚如何在我自己的 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 类的类文件夹位于同一文件夹中。希望其他人觉得这很有帮助。

于 2014-12-10T20:13:31.770 回答
1

我终于放弃了,把我的资源文件放在一个新的 JBoss 模块中,如这个链接中所述。

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

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

于 2014-05-26T09:42:43.660 回答
1

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

检查 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();
    }
}
于 2017-02-11T19:42:45.340 回答
0

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

于 2021-06-16T21:13:31.340 回答
0

我这样决定:

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

ctx.getRosource("classpath:" + path);
于 2020-02-20T06:56:28.717 回答
0

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

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

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

@Inject
private ServletContext servletContext;
于 2019-07-10T23:46:00.803 回答