[Servlet]Session機能の実装

2022/06/22に公開


◆はじめに

SessionのIdを取得します。

Session機能で、セッションがリセットされるまでパラメータが保持されます。


◆Sessionとは

簡単に言えば、
「セッションが続いている間は、パラメータが保持される仕組み」です。
以下の概略図を作りましたのでご覧ください。

セッションに対して、ユニークなキーであるセッションIDが与えられています。
なので、ページを更新しようが、ブラウザを閉じても、
パラメータを保持することが可能です。


このように、セッションで状態を保持することができるようになることで、
情報を更新する場合など、毎回全ての情報を送る必要がないので手間が省けます。
これを「ステートフル」といいます。


セッション機能を利用すれば、
例えば、ショッピングサイトのカートや、ページの訪問回数のカウントなど
ステートフルなWebアプリケーションを作成できます。


◆前提/環境など

本記事は、以下の記事の「InputFunction」プロジェクトをベースに作成しています。
Echo機能のServletの処理時間を計測するFilterを実装しています。
以下の記事の内容を踏まえた前提で、記事は書いていますのでご了承ください。

https://zenn.dev/nakohama/articles/5ba42253eddef1
https://zenn.dev/nakohama/articles/983510140fe9b9

仕様は以下です。
<Echo機能> ・文字列を入力し、送信ボタンを押すと、送信した文字列が画面に表示される。
<Validation機能> ・送信された文字列が空欄の場合は,「この項目は必須入力です。」と文字列が表示される。
<TimeFiletr機能(Listener)> ・Servletの処理時間を計測し、コンソールに表示


※本記事では、 eclipseは以下のバージョンでの画像を使用しています。
日本語化はしていません。
他のversionでの動作は確認しておりません。


◆手順

それでは、先ほど紹介した「InputFunction」プロジェクトに対して、
Session機能を追加していきます。
変更箇所と追加箇所をメインに記載しています。


①変更を加えるファイル

今回は、「EchoServlet.java」に変更を加えます。
それ以外のファイルのコードや追加しているライブラリーに関しては、特に変更はありません。
ディレクトリ構造は以下です。

②Session機能のコード

・以下のコードを、「EchoServlet.java」に記述
EchoServlet.java
package input;

import java.io.IOException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
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;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

  //URLを定義するアノテーション
    @WebServlet(urlPatterns = {"/echo"})  
    
  //Validation機能を持たせたEchoサーブレットクラス
public class EchoServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;
	
		
  //画面からPostされた場合に起動するメインとなるメソッド
	@Override
	protected void doPost(HttpServletRequest request , HttpServletResponse response)throws ServletException,
IOException {
		
	    //取得文字のエンコード設定(文字化け防止)
		request.setCharacterEncoding("UTF-8");
			
			
		//セッションの取得
		HttpSession session = request.getSession();  
				
	//Validation機能
        //テキストボックスのtextを保持したFormの作成
		TextForm SetForm = toSetForm(request);
		
		//toValidationFormをバリデーションに通す。
		//引っかかった場合はrequestにvalidationMessageをセットする
		setValidationAttribute(session,SetForm);
		
		
	//Echo機能
	    //Echoメッセージのセット
		if(session.getAttribute("validationMessage")  == null) {			
			
	        //バリデーションメッセージがrequestに付与されていない場合、
	        //Formに保持していたtextをrequestにEcho用に付与する
			String EchoMessage = SetForm.getTextMessage();
				
			//取得したセッションのmessageに対してセットする
			session.setAttribute("message",EchoMessage);
		}
		
		//Echo保持されている時の、バリデーションが働いた時,EchoMessageは初期化
	if(session.getAttribute("validationMessage")  != null) {			
			//取得したセッションのmessageに対してセットする
			session.setAttribute("message",null);
		}
	
	//セッションIDの取得
	 String session_id = session.getId();
			
		
		//コンソールに出力
	 System.out.println("セッションID:" + session_id );
	 System.out.println("validationMessage<session>):"+session.getAttribute("validationMessage"));
	 System.out.println("message<session>):"+session.getAttribute("message"));	
		
		
//		//RequestDispatcher
		RequestDispatcher dispatcher = request.getRequestDispatcher("echo.jsp");
		dispatcher.forward(request, response);	
	}
	
	
	//「セッションのリセット」のリクエストパラメータが渡された場合が押された場合、セッションを無効にする
	@Override
	protected void doGet(HttpServletRequest request , HttpServletResponse response) throws ServletException,IOException {
		Map<String , String[]> parameterMap = request.getParameterMap();
		if(parameterMap.containsKey("reset") == true) {
			//セッションの取得
			HttpSession session = request.getSession();
			//セッションを無効にする
			session.invalidate();
		}
			

		RequestDispatcher dispatcher = request.getRequestDispatcher("echo.jsp");
		dispatcher.forward(request,response);
	}
	
	
	
	//テキストを保持したFormを作成するメソッド
	private TextForm toSetForm(HttpServletRequest request) {
		//バリデーションに通すためのフォームのインスタンス作成
		TextForm SetForm = new TextForm();
		
		//テキストボックスの文字列を取得
		String text = request.getParameter("m");
		
		//テキストボックスが空欄ではない場合
		if(text.isEmpty() == false) {
			//テキストを保持したFormを返す(今回は実装してないがNull以外のバリデーション機能もあるため)
			SetForm.setTextMessage(text);
		}
		return SetForm;
	}
	

	
	//バリデーション用のメソッド
	private void setValidationAttribute(HttpSession session, TextForm toValidationForm) {
			
		//toValidationFormに対してバリデーションを実行
		Map<String,List<String>> validationMessage = validate(session,toValidationForm);
		
		//バリデーションメッセージがセットされている場合、requestにバリデーションメッセージを付与
		if(validationMessage.isEmpty() == false) {
			session.setAttribute("validationMessage", validationMessage);
			return;
		}   
		
		//Sessionで保持されていたバリデーションメッセージの初期化
		if(validationMessage.isEmpty() == true) {
			session.setAttribute("validationMessage", null);
			return;
		}    
	}
	
	
	//validate
	private Map<String , List<String>> validate(HttpSession session,TextForm toSetForm){
		
		ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
		Validator validator = validatorFactory.getValidator();
		Set<ConstraintViolation<TextForm>> validationResult = validator.validate(toSetForm);
		
		Map<String , List<String>> ret = new HashMap<String , List<String>>();
		
		for(ConstraintViolation<TextForm> violation : validationResult) {	
			String propertyPath = violation.getPropertyPath().toString();
			List<String> messages = ret.get(propertyPath);
			if(messages == null) {
				messages = new ArrayList<String>();
				ret.put(propertyPath, messages);
			}
			messages.add(violation.getMessage());
		}
		return ret;	
	}
}


③動作チェック

・Tomcatなどアプリケーションサーバーを起動
・実装後に以下のURLにアクセス

http://localhost:8080/InputFunction/echo.jsp

以下の画面が表示されます。

それでは、以下の操作を行って、
Session機能について確認していきましょう。

(1)セッションの取得

・テキストボックスに「セッションの保持」と入力

・送信ボタンを押す

・コンソールを確認
すると、取得したSessionIdが表示されていることが確認できます。

(2)セッションの保持

・ブラウザを更新する。または、ブラウザを閉じて再度アクセスする

・コンソールを確認
すると、同じSessionIdで、保持されたテキストが表示されていることを確認できます。

(3)セッションのリセット

・「セッションのリセット」を押す
すると、保持されたテキストが消えます。
また、この時にSessionIdは破棄されています。

(4)セッションの再取得

・テキストボックスに「セッションの再取得」と入力
・送信ボタンを押す
すると、初めとは別のSessionIdが取得されたことを確認できます。


◆さいごに

以上です。いかがだったでしょうか。
Sessionの実装はできたでしょうか。
今回のポイントです。


①request.getSession()を使用して、セッションを取得する

②セッションは破棄されるまで同じなので、パラメータが保持される

③セッションをリセットすると新しいセッションIDになる


コードに関しての詳しい説明に関しては、
あまり書いていません。少し、コード内にコメントはつけてます。
あとは、他の参考に載せている書籍やサイトなど調べてみてください。


最後まで、ご覧いただきありがとうございました。


◆参考

本記事は、以下の書籍を大いに参考にしています。
より詳しく知りたい方は、どうぞ。

https://www.amazon.co.jp/dp/4797362596

・関連記事、その他

https://office54.net/iot/programming/http-stateless-session

Discussion