java - 如何在 Spring 中执行将导出为 WAR 文件的文件 I/O

标签 java spring tomcat file-io war

我的 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 the ClassLoader or ServletContext to fetch resources is a more robust solution. This solution appears to use the ClassLoader 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 answerthe second highest suggests Resource


到目前为止我尝试了什么

根据 DwB 的回答,我尝试在 my Service 中使用 ServletContext 技术,因为那是需要它的地方(内部计算不适用于ControllerDAO)。我漏掉了以下内容:

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 但现在我迷失了 BufferedWriterOutputStream ( 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:/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();
    }
    

Updated based from the current answers

因为这些,现在我的问题和疑惑多于答案。请注意,我打算为导出为 WAR 文件的项目执行文件 I/O。

  1. 当项目位于本地机器和服务器(WAR 文件)时,是否可以成功执行文件 I/O?

    based from the answers, Yes

  2. 如果可能的话,哪个文件夹是放置这些特定文件的最理想位置?

    no particular folder was mentioned

  3. 我应该使用哪些实际函数来读取和写入这些文件?

    ???

这是我的 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 or InputStream form because I use the weka.core.SerializationHelper's read 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/

相关文章:

java - MySQL 查询错误 SQLException

java - 更改 Java 中 MessageBox 中按钮的预选?

java - Hibernate:@ManyToOne,@OneToMany 在结果中给出空值

regex - awk:计算tomcat日志中的错误

tomcat - 当 Tomcat 通过 IntelliJ Idea Ultimate 12 运行时,我无法访问 Tomcat 7 管理器

java - 写入保存在 ftp 服务器中的文件

java - 什么是NullPointerException,我该如何解决?

java - Hibernate 在没有事务的情况下持久化

spring - JBoss AS 7.1 JNDI远程连接

java - 从 Eclipse Mars EE 在 Tomcat 7 和 8 上部署应用程序时出现问题