我的 Spring 应用程序需要一些特殊的文件类型,因此我提出了这个具体问题,即如何在我的本地机器和 WAR
文件中进行万无一失的文件 I/O上传到服务器。
我自己做了一些研究,发现了一些略有帮助的文章:
问题 "Absolute file access in Spring Service layer" 询问如何在 Spring
Service
类中执行文件 I/O。accepted answer 建议使用 Spring 的
Resource
但它要求文件必须位于/WEB-INF/classes
中,不幸的是它与其中一条评论相矛盾最高投票数:Don't write inside your web content or
WEB-INF
folder. There is no guarantee that the war file will be exploded on the filesystem. Write to a well known (probaly configurable) file location.好的,那么我应该把它放在哪里???
Doesn't matter, find a nice location for your files. Maybe a user directory for your application, inside the TMP directory or whatever you like. Everything but writing inside your
web-apps
directories.所以我想将文件放在
/src
中是可以的。可怜的家伙再次询问,但这次它需要在 Tomcat 服务器中:"Tomcat server absolute file access in war webapp"。
This answer 表示 不要在
WAR
文件中执行文件 I/O。The accepted answer by OP 也没有帮助,因为评论说:
This solution will not work unless your webapp is deployed as an exploded-
WAR
file. It is therefore fragile. Using theClassLoader
orServletContext
to fetch resources is a more robust solution. This solution appears to use theClassLoader
but then mangles the URL and loads the resource using standard file I/O. :(好的,所以我看到了一个建议不要在名为 "How to really read text file from classpath in Java" 的
WAR
中执行文件 I/O 的人提供的链接。这个的问题是 the file needs to be somewhere outside the whole Spring project given by the accepted answer 和 the second highest suggests
Resource
。
到目前为止我尝试了什么
根据 DwB 的回答,我尝试在 my Service
层 中使用 ServletContext
技术,因为那是需要它的地方(内部计算不适用于Controller
或 DAO
)。我漏掉了以下内容:
private String myFile = null;
protected void init(final ServletConfig config) {
ServletContext context = config.getServletContext();
String contextPath = context.getContextPath();
myFile = contextPath + "resources/test.txt";
}
protected void doGet() {
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(myFile));
writer.append("Lorem ipsum dolor sit amet");
writer.close();
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
我在我的一个函数中调用了 doGet()
但它返回了
THE TIME org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [spring] in context with path [/bosom] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException
为什么下面的代码不起作用?
简单的写作
BufferedWriter bw = new BufferedWriter(new FileWriter("/src/resources/test.txt")); bw.append("Lorem ipsum dolor sit amet"); bw.close(); bw.flush();
InputStream
使用BufferedReader
但现在我迷失了BufferedWriter
或OutputStream
( source )InputStream is = getClass().getResourceAsStream("/test.txt"); BufferedWriter bw = new BufferedWriter(new FileWriter(is)); bw.append("Lorem ipsum dolor sit amet"); bw.close(); bw.flush();
Spring 的
Resource
也无济于事 (source)。我尝试过使用
resource.toString()
、resource.getURI()
、resource.getURI().toString()
、resource.getURL()
,resource.getURL().toString()
还是报错报错。Resource resource = new ClassPathResource("/src/resources/test.txt"); BufferedWriter bw = new BufferedWriter(new FileWriter(new File(resource.toString()))); bw.append("Lorem ipsum dolor sit amet"); bw.close(); bw.flush();
它只是返回:
java.io.FileNotFoundException: class path resource [src\resources\test.txt] (The system cannot find the path specified) java.io.FileNotFoundException: class path resource [src/resources/test.txt] cannot be resolved to URL because it does not exist java.io.FileNotFoundException: class path resource [src/resources/test.txt] cannot be resolved to URL because it does not exist
我在
Control Panel >> System >> Environment Variables
中创建了一个ENVIRONMENT_VARIABLE
并在中创建了
但是下面的代码没有向文件写入任何内容(虽然没有错误)。myData
D:/resourcesFile file = new File(System.getenv("myData"), "test.txt"); try { BufferedWriter bw = new BufferedWriter(new FileWriter(file.getAbsolutePath())); bw.write("Lorem ipsum dolor sit amet"); bw.flush(); bw.close(); } catch (IOException e) { e.printStackTrace(); }
Updated based from the current answers
因为这些,现在我的问题和疑惑多于答案。请注意,我打算为导出为 WAR
文件的项目执行文件 I/O。
当项目位于本地机器和服务器(
WAR
文件)时,是否可以成功执行文件 I/O?based from the answers, Yes
如果可能的话,哪个文件夹是放置这些特定文件的最理想位置?
no particular folder was mentioned
我应该使用哪些实际函数来读取和写入这些文件?
???
这是我的 Spring 应用程序的结构,如在 Eclipse 工作区的 Windows 资源管理器中所见(请注意):
root
|----> .settings
|----> build
|----> src
|--------> package.name
|--------> resources
|------------> THE_FILES
|----> WebContent
|----> .classpath
|----> .project
Note that I also need the absolute file path in
String
orInputStream
form because I use theweka.core.SerializationHelper
'sread
method.
我只想拥有一个可靠的文件 I/O,它既可以在我的本地机器上运行,也可以在服务器上以 WAR
文件的形式上传(我觉得这是可能的)。
最佳答案
您需要的关键信息是“我在哪里写入和/或读取文件”。
一个简单的技术是拥有一个环境变量(可能命名为 MY_FILE_LOCATION),其中包含将包含您关心的文件的目录。这假定您关心的文件不是 WAR 文件的一部分。
另一种技术是在 CLASSPATH 中有一个配置文件(xml 或属性),其中包含所需的位置信息(可能是 my.directory=/blam/hoot)。
在war中分发的文件可以读写,但是war文件部署的时候好像会爆掉所以IO应该没有问题,只是找文件的问题。 servletContext 有一个方法“getContextPath()”,它将返回当前上下文根目录的路径。您可以使用它来查找文件。
编辑:我将如何使用 Servletcontext。
在我的 servlet 中,我会做这样的事情:
private String blammoFileName;
protected void init(final ServletConfig config)
{
ServletContext context = config.getServletContext();
String contextPath;
contextPath = context.getContextPath();
blammoFileName = contextPath + "/path/to/file.txt";
}
protected void doGet(
final HttpServletRequest request,
final HttpServletResponse response)
{
BufferedWriter writer = new BufferedWriter(new FileWriter(blammoFileName));
... use writer.
}
关于java - 如何在 Spring 中执行将导出为 WAR 文件的文件 I/O,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21707276/