JSP/Servlet | サーブレットとJSP/HTML | アプリケーションに値を保存する

HttpServletRequestとHttpSessionは、利用可能な範囲、つまりスコープが異なる。HttpServletRequestは現在のリクエストが存在する間だけ存在する。HttpSessionはセッションが接続されている間は常に存在する。この2つを使い分け、「どの範囲で値を保存し続けるか」を考えてデータを保存できる。

実は、このほかにも値を保存できるものがある。それがServletContextである。これはWebアプリケーション自体を管理するクラスである。ここに保存された値は、Webアプリケーションが存在する間ずっと保持される。

ここで重要なのは「これは1つしかない」という点である。HttpServletRequestとHttpSessionはアクセスするクライアントごとに用意される。つまり、同時に複数人が使っても、それぞれ別のオブジェクトが用意され、個別に値が保存される。

ところがServletContextはWebアプリケーションに1つしか存在しない。これは誰がアクセスしても同じインスタンスにアクセスするということである。つまり、そこに保存された値は誰がアクセスしても同じものが取得される。

これを利用すると、全員で共有できるデータを簡単に持てる。実際に試してみよう。

hello.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"
        pageEncoding="utf-8"%>
<%@ page import="java.util.ArrayList" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Sample jsp</title>
<style>
h1{
    font-size: 16pt;
    background: #AAFFAA;
    padding: 5px;
}
table tr td {
    background: #DDFFDD;
    padding: 2px;
}
</style>
</head>
<body>
    <h1>Hello App Engine!</h1>
    <hr>
    <p id="msg">メッセージ: </p>
    <form method="post" action="/mygaeapp">
    <table>
        <tr>
            <td>入力</td>
            <td><input type="text" id="input" name="text1"></td>
        </tr>
        <tr>
            <td></td>
            <td><input type="submit" value="送信"></td>
        </tr>
    </table>
    </form>
    <hr>
    <table>
    <%
    ArrayList<String> datas = (ArrayList<String>)application.getAttribute("datas");
    if (datas != null){
        for(String str : datas){
            out.println("<tr><td>" + str + "</td></tr>");
        }
    }
    %>
    </table>
</body>
</html>

MyGaeAppServlet.java

package com.devkuma.mygaeapp;

import java.io.*;
import java.util.ArrayList;

import javax.servlet.ServletContext;
import javax.servlet.http.*;

@SuppressWarnings("serial")
public class MyGaeAppServlet5 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/plain");
        request.setCharacterEncoding("utf8");
        response.setCharacterEncoding("utf8");
        PrintWriter out = response.getWriter();
        out.println("Hello, world!");
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/html");
        request.setCharacterEncoding("utf8");
        response.setCharacterEncoding("utf8");
        String param = request.getParameter("text1");
        ServletContext application = this.getServletContext();
        ArrayList<String> datas = (ArrayList<String>) application.getAttribute("datas");
        if (datas == null) {
            datas = new ArrayList<String>();
        }
        datas.add(param);
        application.setAttribute("datas", datas);
        response.sendRedirect("/hello.jsp");
    }
}

上の例は、送信されたメッセージをArrayListに保存する。あちこちのPCからアクセスしてメッセージを入力し、送信してみよう。全員が入力したすべてのデータが保存され、すべてのブラウザーに同じデータが表示されることがわかるはずだ。

ServletContextは、サーブレットではthisに用意されているメソッドを呼び出して取得する。

ServletContext application = this.getServletContext();

JSPではもっと簡単である。applicationという暗黙オブジェクトとして用意されているため、そのまま使用すればよい。

このServletContextにも、やはりsetAttributegetAttributeというメソッドが用意されており、値を保存したり取得したりできる。使い方はHttpServletRequestなどと完全に同じである。

このHttpServletRequest、HttpSession、ServletContextの3つのクラスを使い分けることで、さまざまな形で値を保存できる。サーブレットとJSPで必要な値をやり取りするとき、これらは非常に重要である。この3つはセットで覚えておこう。