Java WildFly - 从 WAR 获取资源
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23845031/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WildFly - getting resource from WAR
提问by Nik?a Baldun
I am using the following method to get a resource from WAR file in WildFly:
我使用以下方法从 WildFly 的 WAR 文件中获取资源:
this.getClass().getResource(relativePath)
It works when the application is deployed as exploded WAR. It used to workwith compressed WAR, too. Yesterday, I did a clean and rebuild of project in Eclipse, and it just stopped working.
当应用程序部署为爆炸式 WAR 时,它会起作用。它曾经也适用于压缩的 WAR。昨天,我在 Eclipse 中对项目进行了清理和重建,但它刚刚停止工作。
When I check the resource root:
当我检查资源根目录时:
logger.info(this.getClass().getResource("/").toExternalForm());
I get this:
我明白了:
file:/C:/JBoss/wildfly8.1.0.CR1/modules/system/layers/base/org/jboss/as/ejb3/main/timers/
So, no wonder it doesn't work. It probably has something to do with JBoss module loading, but I don't know if this is a bug or normal behavior.
所以,难怪它不起作用。它可能与 JBoss 模块加载有关,但我不知道这是错误还是正常行为。
I found various similar problems on StackOverflow, but no applicable solution. One of the suggestions is to use ServletContext like so:
我在 StackOverflow 上发现了各种类似的问题,但没有适用的解决方案。建议之一是像这样使用 ServletContext:
@Resource
private WebServiceContext wsContext;
...
ServletContext servletContext = (ServletContext)this.wsContext.getMessageContext()
.get(MessageContext.SERVLET_CONTEXT);
servletContext.getResource(resourcePath);
But, when I try to obtain MessageContext in this manner, I get an IllegalStateException. So I am basically stuck. Any ideas?
但是,当我尝试以这种方式获取 MessageContext 时,我得到了一个 IllegalStateException。所以我基本上被卡住了。有任何想法吗?
采纳答案by Nik?a Baldun
I finally gave up and put my resource files in a new JBoss module, as described in this link.
我终于放弃了,将我的资源文件放在一个新的 JBoss 模块中,如本链接所述。
https://community.jboss.org/wiki/HowToPutAnExternalFileInTheClasspath
https://community.jboss.org/wiki/HowToPutAnExternalFileInTheClasspath
It works, but the downside is that there are two deployment targets so things are more complicated. On the upside, the size of the WAR file is reduced, and I don't have to redeploy the application if only some of the resources have changed.
它有效,但缺点是有两个部署目标,所以事情更复杂。从好的方面来说,WAR 文件的大小减小了,如果只有某些资源发生了变化,我就不必重新部署应用程序。
回答by Smutje
We had a similar problem and our fault was that we tried to access the static resource through the raw path instead of using the input stream the resource is providing - the following code works for us even when deploying a non-exploded .war-file.
我们遇到了类似的问题,我们的错误在于我们试图通过原始路径而不是使用资源提供的输入流访问静态资源 - 即使在部署未爆炸的 .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) {
// ...
}
回答by djmorton
I ran into this same problem, and rather than define the resource as a shared module, I ended up working around this by using a ServletContextListener in my WAR.
我遇到了同样的问题,我没有将资源定义为共享模块,而是通过在我的 WAR 中使用 ServletContextListener 解决了这个问题。
In the contextInitialized method, I got the ServletContext from the ServletContextEvent and used its getResource("/WEB-INF/myResource") to get the URL to the resource inside my WAR file. It appears that in the ServletContextListener, the .getResource() method resolves as expected rather than to the "/modules/system/layers/base/org/jboss/as/ejb3/main/timers/" url. That URL can then be stored in the ServletContext for later use by your servlets or in an injected ApplicationScoped CDI bean.
在 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) {}
}
or
或者
@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) {}
}
回答by Chuck L
I was recently trying to figure out how to access a file within my own war in Java. The following is how the java classes and resources are packaged in the war file:
我最近试图弄清楚如何在我自己的 Java War中访问文件。下面是java类和资源在war文件中的打包方式:
WAR
`-- WEB-INF
`-- classes (where all the java classes are)
`-- resourcefiles
`-- resourceFile1
My target file was resourceFile1. To get that file, I just did the following in code:
我的目标文件是 resourceFile1。要获取该文件,我只是在代码中执行了以下操作:
InputStream inStream = this.class.getClassLoader().getResourceAsStream("resourcefiles/resourceFile1");
In this case the resource files would need to be in the same folder as the classes folder containing the java classes. Hopefully others find this helpful.
在这种情况下,资源文件需要与包含 java 类的 classes 文件夹位于同一文件夹中。希望其他人觉得这有帮助。
回答by ikarayel
This sample code works for wildfly deployed and tested on openshift. I think it is a wildfly problem I downland wildfly and tried on local I also get the error.
此示例代码适用于在 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();
}
}
回答by Tasos Zervos
Had the same issue with Wildfly and not-exploded WAR and using Spring and ServletContextResource I have got around it like this:
Wildfly 和未爆炸的 WAR 有同样的问题,使用 Spring 和 ServletContextResource 我已经解决了这个问题:
[org.springframework.core.io.]Resource resource = new ServletContextResource(servletContext, "WEB-INF/classes/resource.png");
In the same @Serviceclass I also had:
在同一个@Service类中,我也有:
@Inject
private ServletContext servletContext;
回答by Safargaleev Ruslan
I decided so:
我是这样决定的:
@Autowired
private final ApplicationContext ctx;
private final Path path = Paths.get("testfiles/load")
ctx.getRosource("classpath:" + path);