我需要为Spring应用程序提供一些特殊的文件类型,因此我提出了如何在我的本地计算机上执行万无一失的文件I / O以及将WAR
文件上传到服务器。
我自己做了一些研究,发现了一些有用的文章:
问题"Absolute file access in Spring Service layer"询问如何在Spring Service
类中执行文件I / O.
accepted answer建议使用Spring的Resource
,但它要求文件必须位于/WEB-INF/classes
内,不幸的是它与其中一个最高投票评论相矛盾:
请勿在您的网络内容或
WEB-INF
文件夹中撰写。无法保证war文件将在文件系统上爆炸。写入一个众所周知的(可配置的)文件位置。
好的,我该把它放在哪里???
无所谓,为您的文件找到一个不错的位置。也许是您的应用程序的用户目录,在TMP目录中或您喜欢的任何内容。除了在
web-apps
目录中书写之外的所有内容。
所以我想把文件放在/src
中是可以的。
这个可怜的家伙再次问道,但这次需要在Tomcat服务器上:"Tomcat server absolute file access in war webapp"。
This answer对 NOT FILE I / O WAR
FILE 说。
The accepted answer by OP也没有帮助,因为评论说:
除非您将webapp部署为展开的
WAR
文件,否则此解决方案将无效。因此它很脆弱。使用ClassLoader
或ServletContext
获取资源是一种更强大的解决方案。此解决方案似乎使用ClassLoader
,但随后修改了URL并使用标准文件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的回答,我尝试在我的ServletContext
图层中使用Service
技术,因为这是需要的地方(内部计算不适合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
我在ENVIRONMENT_VARIABLE
中创建了Control Panel >> System >> Environment Variables
并创建了myData
D:/resources
,但是下面的代码没有写任何文件(尽管没有错误) )。
File 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();
}
根据当前答案更新
现在我因为这些而有更多的疑问和怀疑而不是答案。请注意,我打算为导出为WAR
文件的项目执行文件I / O.
当项目位于本地计算机和服务器(WAR
文件)中时,是否可以成功执行文件I / O?
根据答案,是
如果可能,在哪个文件夹中放置这些特定文件的最理想位置?
没有提到特定的文件夹
我应该使用哪些实际函数来读写这些文件?
???
这是我的Spring应用程序的结构,如Eclipse Workspace中的Windows资源管理器中所示(请注意):
root
|----> .settings
|----> build
|----> src
|--------> package.name
|--------> resources
|------------> THE_FILES
|----> WebContent
|----> .classpath
|----> .project
请注意,我还需要
String
或InputStream
形式的绝对文件路径,因为我使用的是weka.core.SerializationHelper
'sread
method。
我只想拥有一个可靠的文件I / O,它在我的本地机器上工作,甚至在服务器上作为WAR
文件上传时(我觉得可能)。
答案 0 :(得分:0)
您需要的关键信息是“我在哪里写和/或读取文件”。
一种简单的技术是拥有一个环境变量(可能名为MY_FILE_LOCATION),其中包含将包含您关注的文件的目录。这假设您关注的文件不是WAR文件的一部分。
另一种技术是在CLASSPATH中包含一个包含所需位置信息的配置文件(xml或属性)(可能是my.directory = / blam / hoot)。
你可以读取和写入在战争中分发的文件,但似乎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.
}
答案 1 :(得分:0)
看起来你混淆了几个问题/答案。
这是基础知识。
假设文件是静态的,即在构建WAR时将其添加到WAR中,则:
WEB-INF/classes
或WEB-INF/lib
中的JAR。在这两种情况下都不需要展开WAR以使应用程序使用该文件。
但是,如果文件是动态的,即它是由应用程序在运行时创建的,那么您需要创建一个与Tomcat分开的目录,并使用enivornment变量或类似变量引用它。如果该文件也可以通过http获得,那么您需要编写一个servlet,将文件内容写入http响应,设置适当的内容类型。
编辑 - 基于以下评论
有几种设置环境变量的方法,你可以Google。
绝对路径是相对于文件系统根目录的相对路径,而不是您碰巧所在的目录。在Unix上,您希望看到它以'/'开头,或者在Windows上以驱动器号{{1}开头例如。
在你的情况下,环境变量应该设置为类似C:\
的东西,可以使用/usr/myapp
在Java中读取,导致代码如下:
System.getenv
接下来,您询问如何将文件放入File file = new File(System.getenv("MY_ENVIRONMENT_VARIABLE"), "MY_FILE");
- WEB-INF/lib
中唯一应该是JAR的内容。正如我之前所说,静态文件(取决于它们的使用方式)应该位于WEB-INF/lib
或WAR的根目录或WEB-INF/classes
以外的子目录中。例如,属性文件应位于WEB-INF
中,而应用程序中使用的图像应位于WAR的根目录或某个子目录中,对于图像可能为WEB-INF/classes
。