ログイン認証を行う

今回の記事はこちらの記事の続きとなっております。

現在Java(サーブレット・jsp) x PostgreSQLを使ってTodoアプリを作成しています。現時点での機能は次のとおりです。

前回作成したログイン機能はとりあえずidとパスワードを使って認証するだけというものでした。そのためログインしていない状態でも、Todoの一覧閲覧や、新規作成を行えてしまうという状態でした。そこで今回の記事ではログインしていない状態では一覧の閲覧や新規作成を行えないようにします。

今回は以下のような流れで開発を進めていきます。

  1. 認証を行うBaseServletの作成
  2. BaseServletを各Servletに継承させる

その他の機能の作成記事はこちらの記事にまとめています。

GitHubにソースがあるので、参考にしてください!ご質問等あればこちらのTwitterアカウントまでお願いします。

Java x MySQLでWebアプリの作り方が学べるUdemy講座

BaseServletの作成

まずはBaseServletを作成します。BaseServletの役割はユーザーがログインしているかどうか判定します。判定方法は、セッションにユーザーIDが存在するかどうかで判定します。ログインしていた場合、各画面の処理をよび、ログインしていなかった場合ログイン画面に遷移します。

このBaseServletをログインしている時のみ行わせたいServletが継承することで、ログイン認証を常に行うようにします。

BaseServletは以下のようになります。まずBaseServlet自体は継承されることを前提としたした抽象クラスとします。その上でdoGet, doPostメソッドを用意します。doGetメソッドはdoPostメソッドを呼び出すだけにします。doPostメソッド内でセッションのログイン情報をチェックします。ログインしていた場合はexecメソッドを実行します。このexecメソッドはBaseServletでは抽象メソッドとしておきます。BaseServletを継承した各Servletではそれぞれの処理を記述します。

package servlet;

import java.io.IOException;
import java.sql.SQLException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import constant.SessionInfo;

/**
 * Servlet implementation class BaseServlet
 */
public abstract class BaseServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public BaseServlet() {
        super();
    }

	/**
	 * doPostメソッドを呼び出す
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	/**
	 * ログイン済みかどうかを判定する
	 * ログイン済みの場合各処理を実行
	 * ログインしていない場合ログイン画面に遷移する
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// セッションからログイン中のユーザーIDを取得する
		HttpSession session = request.getSession();
		String loginUserId = (String)session.getAttribute(SessionInfo.LOGIN_USER_ID);

		// セッションにログイン中のユーザーIDが存在する時
		if (loginUserId != null) {
			try {
				exec(request, response);
			} catch (SQLException | ClassNotFoundException e) {
				e.printStackTrace();
			}
		} else {
			request.getRequestDispatcher("WEB-INF/jsp/login.jsp").forward(request, response);;
		}
	}

	/**
	 * 各サーブレットの処理を記述する
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	protected abstract void exec(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException, SQLException, ClassNotFoundException;
}

BaseServletを継承

各Servletで先ほど作成したBaseServletを継承します。

ListServlet

まずはListServletで継承します。クラスの宣言部分でHttpServletを継承していましたが、これをBaseServletに変更します。

public class ListServlet extends BaseServlet

その上でexecメソッドを定義し、doGetに書かれていた処理をこちらに移します。移しおえたらdoGetメソッドは全て削除してしまって大丈夫です。

/**
 * todoテーブルからtodoを取得し、一覧表示する
 */
@Override
protected void exec(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException, SQLException, ClassNotFoundException {
	// todoの一覧を保持する変数を宣言
	List<TodoDTO> todoList = new ArrayList<>();

	// DAOを生成し、Todo一覧を取得する
	TodoListDAO dao = new TodoListDAO();

	// todo一覧を取得する
	todoList = dao.getTodoList();

	// todo一覧をリクエストスコープに設定する
	request.setAttribute("todoList", todoList);
	// todo一覧画面に遷移する
	RequestDispatcher rd = request.getRequestDispatcher("WEB-INF/jsp/list.jsp");
	rd.forward(request, response);
}

InsertServlet

ListServletとほとんど同じです。継承をHttpServletからBaseServletに変更し、execメソッド内に処理を記述します。

DeleteServlet

DeleteServletも同じです。継承をHttpServletからBaseServletに変更し、execメソッド内に処理を記述します。

updateServletは特別

UpdateServletだけ少し違います。UpdateServletではリクエストがGETかPOSTで処理を分けているので、execに一つの処理として記述することができません。いろいろ方法はありますが、今回は以下の様に対応します。

  • UpdateServletでもBaseServletを継承します
  • execメソッド内でGETリクエストなのかPOSTリクエストなのか判定する
  • getGetRequestメソッドとgetPostRequestメソッドを作成し、リクエストの種類によって呼ぶ方を変える

結果的にBaseServletは以下のようになります。またGETメソッドでリクエストを受けた時にTodoのidがint型に変換できなかった場合NumberFormatExceptionが発生してしまいますので、その時は一覧画面に遷移します。

package servlet;

import java.io.IOException;
import java.sql.Date;
import java.sql.SQLException;

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 constant.Parameters;
import model.dao.UpdateDAO;
import model.dao.dto.TodoDTO;

/**
 * Servlet implementation class UpdateServlet
 */
@WebServlet("/update-servlet")
public class UpdateServlet extends BaseServlet {
    /**
     * @see HttpServlet#HttpServlet()
     */
    public UpdateServlet() {
        super();
    }

	@Override
	protected void exec(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException, SQLException, ClassNotFoundException {
		// メソッドの取得
		String method = request.getMethod();

		// リクエストメソッドの種類によって呼ぶ関数を変える
		if (method.equals("GET")) {
			getGetRequest(request, response);
		} else if (method.equals("POST")) {
			getPostRequest(request, response);
		}
	}

	/**
	 * GETリクエストを受け取った時の処理
	 */
	protected void getGetRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException, SQLException, ClassNotFoundException {
		// リクエストパラメータからtodoIdを取得する
		int todoId = 0;
		try {
			todoId = Integer.parseInt(request.getParameter(Parameters.TODO_ID));
		} catch (NumberFormatException e) {
			request.getRequestDispatcher("list-servlet").forward(request, response);
		}

		UpdateDAO dao = new UpdateDAO();
		TodoDTO todo = new TodoDTO();

		// todoの取得
		todo = dao.getTodo(todoId);

		request.setAttribute("todo", todo);
		request.getRequestDispatcher("WEB-INF/jsp/update.jsp").forward(request, response);
	}

	/**
	 * POSTリクエストを受け取った時の処理
	 */
	protected void getPostRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException, SQLException, ClassNotFoundException {
		// リクエストパラメータから値を取得する
		request.setCharacterEncoding("UTF-8");
		int id = Integer.parseInt(request.getParameter(Parameters.TODO_ID));
		String todo = request.getParameter(Parameters.TODO);
		Date timeLimit = Date.valueOf(request.getParameter(Parameters.TIME_LIMIT));

		// DAOを生成し、Todoを更新する
		UpdateDAO dao = new UpdateDAO();

		// 受け取ったパラメータを元にデータベースを更新する
		dao.updateTodo(id, todo, timeLimit);

		response.sendRedirect("list-servlet");
	}
}

 

まとめ・次回予告

次は流石にデザインをなんとかします。後ログアウト機能もつけときましょう。

GitHubにソースがあるので、参考にしてください!ご質問等あればこちらのTwitterアカウントまでお願いします。

私はプログラミング学習はUdemyで行うのが以下のような理由で圧倒的におすすめです。

  • 動画で好きなときに学べる
  • 一流のエンジニアから教えてもらえる
  • 好きな技術を体系的に学べる
  • 実際に手を動かしながら学ぶことができる
  • セール時であれば1500円〜2000円ほどで購入できる(大半の技術書より安い)
  • 講座自体がアップデートされていくので情報が古くなりにくい

UdemyにはJava x MySQLでWebアプリの作り方が学べるUdemy講座 もあるので興味がある方は一度チェックしてみてください!なおUdemyは頻繁にセールをやっているので、セール時を狙って購入してください!

おすすめの参考書

コメント

タイトルとURLをコピーしました