3

セッションで使用する一時ファイルを作成する Java サーブレットに取り組んでいます。セッションの最後 (つまり、ユーザーの「ログアウト」) で、一時ファイルを削除してから、ユーザーを最初の (「ログイン」) ページにリダイレクトする必要があります。リダイレクトは正常に機能しますが、一時ファイルはそのまま残ります。

ファイルへのパスと関係があると思いますが、何が原因かはよくわかりません。セッションの開始時にファイルを作成します。

String path = request.getSession().getServletContext().getRealPath("/");
File file = File.createTempFile("getter", ".html", new File(path + "/tmp/"));

次に、セッションを閉じるときに、次のことを行います。

file.delete();

については知ってfile.deleteOnExit()いますが、いつサーブレットを終了しますか? おそらく私は混乱していますが、何か助けていただければ幸いです!:)

前もって感謝します!

編集

だから、ここにいくつかの詳細があります:

先ほど言ったように、当面はセッションを処理せずにサーブレットを使用しています。セッションを実装する必要があるという@Joopに同意しますが、当面は簡単なテストを行いたいだけです。

したがって、私のサーブレットはハグルGETしてPOSTリクエストします。リクエストでフラグを使用して、ファイル (クラスで として宣言されている) を新しい一時ファイルPOSTにインスタンス化する内部関数を呼び出します。private File file;連続した呼び出しでは、ファイルが取り込まれて保存されます。ユーザーに表示されるページには、サーブレット (「this」、つまり「this」) を参照するアンカーがあり、パラメーターとしてフラグ (「ログアウト」を示すフラグ) を渡します。次に、以前にインスタンス化されたファイルを削除する別の内部関数を呼び出します。

セッションの問題である場合は、マネージャーを実装し、調査結果を投稿します。

編集2

を実装しましたHttpSessionListenerが、すべて正常に動作しているようです。ここで、セッションの作成時に、以前に宣言したディレクトリでファイルをインスタンス化します (これは一時ファイルではないことに注意してくださいFile file = new File(path + "/tmp/" + req.getSession().getId() + ".html");。ファイルの名前がセッション ID と同じになるように使用します)。次に、セッションに属性を追加します。この属性の値は、ファイルへのフル パスです。いつものようにファイルにデータを入力し、ユーザーがログアウトを選択すると、セッションを無効にします。次に、リスナー内でファイルへのパスを取得するため、ファイルへのポインターを取得できます。

String fname = ev.getSession().getAttribute("filename").toString();
File f = new File(fname);
f.delete();

だから、私が得ているメッセージは肯定的です。つまり、f.delete()trueを返します。この後、私はそうf.exists()しますfalse。だから大丈夫なはずです。ただし、ファイルは物理的に存在します。つまり、ファイルはまだディスク上に存在しています。

@A4L から親切に提供された例を試すことができます。私は何か間違ったことをした..?

4

4 に答える 4

9

実行時に deploy フォルダに任意のファイルを書き込むのはやめてください。代わりに、実際の一時フォルダーに書き込むだけです。次の行を完全に削除します。

path = request.getSession().getServletContext().getRealPath("/");

そしてただ使う

File file = File.createTempFile("getter", ".html");

deploy フォルダー内のファイルは通常、サーブレットコンテナーによってロックされているため、具体的な問題が発生する可能性があります。その中のファイルを削除することはできません。

将来へのヒント:getRealPath()で問題を解決できると思ったら、すぐにコードを書くのをやめて、それが具体的な問題を解決するための適切なツールであるかどうかをよく考えてください。私が Servlet ベースの Web アプリケーションを開発した 10 年間で、そのメソッドの現実世界での賢明な使用例はありませんでした。servletcontext.getRealPath("/") の意味と使用するタイミングについても参照してください。


file.deleteOnExit() については知っていますが、いつサーブレットを終了しますか?

あなたはそうしない。コンテナはそうです。ここでの「終了」とは、基本的に JVM 全体のシャットダウンを意味します。これは文字通りjavadocで言及されています(強調鉱山)。

仮想マシンの終了時に、この抽象パス名が示すファイルまたはディレクトリを削除するように要求します。

于 2013-07-26T12:19:40.290 に答える
0

ユーザーがログアウトしたときにファイルを削除しようとする前に、ファイルを閉じていることを確認し、何File#delete()が返されるかを確認してください。

@Test
public void createTempFile() throws IOException {
    File tf = File.createTempFile("hello", ".tmp", new File("."));
    FileOutputStream fos = new FileOutputStream(tf);
    fos.write("Hello, Temp!".getBytes());
    Assert.assertTrue(tf.delete()); // fails because the file could not be deleted
                                    // and delete() returns false
}

対。

@Test
public void createTempFile() throws IOException {
    File tf = File.createTempFile("hello", ".tmp", new File("."));
    FileOutputStream fos = new FileOutputStream(tf);
    fos.write("Hello, Temp!".getBytes());
    fos.close();
    Assert.assertTrue(tf.delete()); // passes, file deleted
}

File#deleteOnExit()を使用すると、VM の終了時にファイルが削除されます。これは、Tomcat がシャットダウンされたときに発生します。したがって、ユーザーのログアウトには役立ちません。

編集

ユーザーごとに、複数の要求にわたってファイルが 1 つだけであることを確認してください。SessionListenerJoop が提案したように使用することをお勧めします。HttpSessionListener#sessionCreatedが呼び出されたときにファイルを作成し、よく知られているキーを使用してセッションに配置すると、 HttpSessionEvent#getSession()を使用してセッション オブジェクトを取得できます。HttpSession.#invalidate()を呼び出してログアウトすると、Listner メソッドHttpSessionListener#sessionDestroyedが呼び出され、セッションからファイルを取得して削除できます。

簡単な例(doGet のみ、SessionListener なし)

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@WebServlet(urlPatterns = "/ptf.html")
public class PopulateTempFile extends HttpServlet { 
    private static final long serialVersionUID = -144949663400032218L;

    private static class TempFilePopulator {
        private File tf = null;
        public TempFilePopulator(String rootDir) throws IOException {
            tf = File.createTempFile("hello", ".tmp", new File(rootDir));
        }

        public void populate(String line) throws IOException {
            FileWriter fw = new FileWriter(tf, true);
            fw.write(line + "\n");
            fw.close();
        }

        public List<String> getContent() throws IOException {
            List<String> lines = new ArrayList<String>();
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(tf)));
            String line;
            while(null != (line = br.readLine())) {
                lines.add(line);
            }
            br.close();
            return lines;
        }

        public boolean deleteTempFile() { return tf.delete(); }
        public String toString() { return tf.getAbsolutePath(); }
    }


    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {

        HttpSession session = request.getSession();
        TempFilePopulator tfp = (TempFilePopulator) session.getAttribute("tempfilepopulator");

        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<html>");

        out.println("<a href=\"" + request.getServletContext().getContextPath()
            + request.getServletPath() + "\">Refresh</a>");
        out.println("&nbsp;|&nbsp;");
        out.println("<a href=\"" + request.getServletContext().getContextPath()
            + request.getServletPath() + "?logout=true\">Logout</a>");

        String logout = request.getParameter("logout");
        if("true".equals(logout)) {
            if(tfp != null) {
                if(tfp.deleteTempFile()) {
                    log("Temp file '" + tfp + "' deleted.");
                } else {
                    log("Unable to delete temp file '" + tfp + "'");
                }
            }
            session.invalidate();
        } else {
            if(tfp == null) {
                tfp = new TempFilePopulator(request.getServletContext().getRealPath("/"));
                log("Temp file '" + tfp + "' created.");
                session.setAttribute("tempfilepopulator", tfp);
            }
            tfp.populate(new Date().toString());
            out.println("<p>Content of temp file</p>");
            List<String> lines = tfp.getContent();
            for(String line : lines) {
                out.write(line);
                out.write("<br/>");
            }
        }
        out.println("</html>");
    }
}
于 2013-07-26T09:16:23.693 に答える
0

を呼び出すたびにcreateTempFile別のパスが提供されるため、パスを保存する必要があります。

SessionListenerを参照してください。- セッションのタイムアウトが関係している場合。

おそらく、一時ファイルを含むディレクトリとして JSESSIONID を使用し、ディレクトリを削除します。

ところで、そうしないと新しいセッションが作成されるため、後でセッションを無効にすると思います。 私はログに記録します。file.delete()getSession()file.getPath()

于 2013-07-26T09:18:53.233 に答える