我使用以下方法从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模块加载有关,但我不知道这是一个bug还是正常行为。
我在StackOverflow上发现了各种类似的问题,但没有适用的解决方案。其中一个建议是像这样使用ServletContext:
@Resource
private WebServiceContext wsContext;
...
ServletContext servletContext = (ServletContext)this.wsContext.getMessageContext()
.get(MessageContext.SERVLET_CONTEXT);
servletContext.getResource(resourcePath);
但是,当我尝试以这种方式获取MessageContext时,我得到一个IllegalStateException。所以我基本上卡住了。有什么想法吗?
答案 0 :(得分:3)
我遇到了同样的问题,而不是将资源定义为共享模块,我最后通过在WAR中使用ServletContextListener来解决这个问题。
在contextInitialized方法中,我从ServletContextEvent获取了ServletContext,并使用其getResource(" / WEB-INF / myResource")来获取WAR文件中资源的URL。似乎在ServletContextListener中,.getResource()方法按预期解析而不是" / modules / system / layers / base / org / jboss / as / ejb3 / main / timers /"网址。然后,该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) {}
}
答案 1 :(得分:2)
我们遇到了类似的问题,我们的错是我们尝试通过原始路径访问静态资源而不是使用资源提供的输入流 - 即使在部署非爆炸的.war时,以下代码也适用于我们-file。
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) {
// ...
}
答案 2 :(得分:1)
我终于放弃并将我的资源文件放在一个新的JBoss模块中,如本链接所述。
https://community.jboss.org/wiki/HowToPutAnExternalFileInTheClasspath
它有效,但缺点是有两个部署目标,所以事情更复杂。从好的方面来说,WAR文件的大小会减少,如果只有部分资源发生了变化,我就不必重新部署应用程序。
答案 3 :(得分:1)
此示例代码适用于在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();
}
}
答案 4 :(得分:0)
Wildfly和未爆炸的WAR以及使用Spring和ServletContextResource都存在相同的问题,我已经这样解决了:
dprintf(3)
在同一个 @Service 类中,我还拥有:
[org.springframework.core.io.]Resource resource = new ServletContextResource(servletContext, "WEB-INF/classes/resource.png");
答案 5 :(得分:0)
我决定是这样
@Autowired
private final ApplicationContext ctx;
private final Path path = Paths.get("testfiles/load")
ctx.getRosource("classpath:" + path);
答案 6 :(得分:0)
我阅读了 this 解决方案,这导致我们在 Wildfly 中使用 getResourceAsStream(...)
而不是 getResource()
。我只是在 Wildfly 19 上测试它,并从控制台部署 myApp.ear。