ログイン処理(Daoを使った改良版)

前回のデータベースを使ったユーザ管理:ログイン処理(書き下し版)のプログラム構造を改良し、保守性、拡張性を向上させましょう。

まず、前回のプログラム構造を振り返ってみましょう。
ログイン処理(書き下し版)は四つのユースケース:ユーザ情報の一覧、ログインチェック、ユーザの追加、ユーザの削除をJSPとServletが個々に担当し、それぞれがデーターベースにアクセスして機能を実現していました。従って、

<ログイン処理(書き下し版)のプログラム構造的な問題>

  1. JSPは全体のUIを担当しているユーザ情報の一覧機能だけであるため、他のユースケースを担当するServletは処理の結果をユーザ情報の一覧機能に返して表示するしかなく、独自に自由な画面設計が出来ません。
  2. Javaプロググラム処理(ビジネスロジック・レイヤ)とデータベース処理(データベース・レイヤ)の切り分けが行われておらず、レイヤ間が密結合の状態で、データーベースの種類が変わったり、データの保存先がデータベースではなくファイルシステムに変わるような場合、全てのプログラムに変更が必要になり修正に手間がかかるだけでなく、修正時のミス防止やテストケースの増加などが予想されます。

1.はUIはJSP、コントロールはServletと役割を明確にしてプログラムを構成すれば改善できますが、2.の改善にはビジネスロジック・レイヤとデータベース・レイヤのレイヤごとの役割を明確化し、レイヤ間を疎結合にする必要があります。

そもそもオブジェクト指向プログラミング(Javaで作るビジネスロジック)とリレーショナルデータベース(データの永続化機構)との間には概念や構造の違いから発生するギャップ:インピーダンスミスマッチがあるといわれています。リレーショナルデータベースにアクセスするためのJDBCはJavaから直接呼び出すことが出来るのに「ギャップがある」というのは分かりにくいかもしれません。
これは例えばショッピングカートを考えた場合、ビジネスロジック側はショッピングカートをユーザごとにモデル化したオブジェクトとして扱うでしょうが、データベース側は正規化した複数のテーブルとテーブル間のリレーションで扱うため、両者の異なるデータ形式の変換が必ず必要になるという事です。

そこで、インピーダンスミスマッチの対応策の一つとしてJavaの開発元であったサン・マイクロシステムズがベスト・プラクティス・ガイドラインで提案したのがDAO:Data Access Objectです。
これはデータの永続化機構(例えばデータベース)とビジネスロジック間にDAOを位置付け、データベースに対するアクセスインターフェースを用意して、全てのデータアクセスをこのインターフェースを通して行わせ、データベースから取得した結果はDTO:Data Transfer Objectに格納する事により、永続化機構をビジネスロジックから隠蔽します。

ビジネスロジックに対するDAOを使ったデータ永続化機構隠蔽の概念図

DAOを使ったデータ永続化機構隠蔽
DAOとDTOを使ったユーザ管理処理の構成をクラス関連図にまとめました。

DaoとDtoを使ったユーザ管理のクラス関連図

この構成ではUIをJSP、コントロールをServletが担当するように事前に決めたので、いろいろな条件による画面の切り替えが容易になっていますし、Daoによりコントロールからデータベースアクセスが切り離されたのでコントロールの中が見やすくなっています。

まず、一連の操作を見てみましょう。
画像をクリックすると拡大画像が表示されます。
1. 初期画面

ログイン処理(Daoを使った改良版)01

選択できる4っの機能が表示されています。
2. 登録済みユーザの一覧

ログイン処理(Daoを使った改良版)02

初期画面でを選択すると表示されます。
3. ユーザログイン

ログイン処理(Daoを使った改良版)03

初期画面でを選択し、IDにあああ、パスワードに222と入力します。
4. 入力内容のチェック

ログイン処理(Daoを使った改良版)04

入力されたユーザ情報を登録されている情報と比較した結果、該当するユーザが見つからなかったので、再入力を促します。
5. 再ログイン

ログイン処理(Daoを使った改良版)05

今度はIDにあああ、パスワードに111と入力します。
6. ログイン成功

ログイン処理(Daoを使った改良版)06

入力されたユーザ情報と同じユーザ情報が登録されていたので、ログインを許可しメッセージを表示します。
7. 新規ユーザの登録

ログイン処理(Daoを使った改良版)07

初期画面でを選択し、IDにあああ、パスワードに111と入力します。
8. ユーザ情報の確認

ログイン処理(Daoを使った改良版)08

入力されたユーザ情報が登録されているユーザ情報と一致したため、既登録のユーザと判断し再入力を促します。
9. ユーザ情報の再入力

ログイン処理(Daoを使った改良版)09

今度はIDに山下、パスワードに555と入力します。
10. ユーザ登録成功

ログイン処理(Daoを使った改良版)09

入力されたユーザ情報と一致する既存ユーザ情報が発見されなかったので、新規のユーザ登録を許可し、メッセージを表示。
11. ユーザ一覧の再表示

ログイン処理(Daoを使った改良版)09

初期画面でを選択し、現在のユーザ一覧を表示します。
12. ユーザの削除

ログイン処理(Daoを使った改良版)09

初期画面でを選択し、削除するユーザのidをああああ、パスワードを111と入力します。
13. ユーザ情報確認

ログイン処理(Daoを使った改良版)09

入力されたユーザ情報と一致するユーザ情報が見つからなかったため、削除該当ユーザ無しとしてメッセージを表示し、再入力を促します。
14. ユーザ情報の再入力

ログイン処理(Daoを使った改良版)09

今度はユーザのidをあああ、パスワードを111と入力します。
15. ユーザ削除成功

ログイン処理(Daoを使った改良版)09

入力されたユーザ情報が既に登録済だったので、当該ユーザの情報を削除し、メッセージを表示。
16. 登録済みユーザの再表示

ログイン処理(Daoを使った改良版)09

初期画面でを選択し、現在の登録済みユーザ情報を確認します。
それでは、次に各処理のソースコードを見てみましょう。
特定のソースコードのみ確認したい場合は以下のボタンをクリックしてください。
登録済みユーザ一覧処理
ユーザログイン処理
ユーザ登録処理
ユーザ削除処理
DAOとDTO
まず、ユーザ管理処理のメインメニュー:login_main.jspです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ユーザ管理UI</title>
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/login.css">
</head>
<body>
<h1>登録済みユーザ一覧</h1>
<form action="./UserListServlet" method="post">
    <button type="submit"><pre><big>登録済みユーザ一覧</big></pre></button>
</form>
<hr>
<h1>ユーザログイン</h1>
<form action="./user_login.jsp" method="post">
    <button type="submit"><pre><big>ログイン</big></pre></button>
</form>
<hr>
<h1>ユーザ登録</h1>
<form action="./user_regist.jsp" method="post">
    <button type="submit"><pre><big>ユーザ登録</big></pre></button>
</form>
<hr>
<h1>ユーザ削除</h1>
<form action="./user_delete.jsp" method="post">
    <button type="submit"><pre><big>ユーザ削除</big></pre></button>
</form>
<hr>
</body>
</html>

各機能ごとに専用のUIを読んでいるので、構造はシンプルです。
登録済みユーザ一覧については専用のUIによる入力が不要なので、直接コントロールのサーブレット:UserListServletを呼んでいます。

次は登録済みユーザ一覧のコントロールを行うサーブレット:UserListServlet.javaです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.example;
 
import java.io.IOException;
import java.util.ArrayList;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
/**
 * Servlet implementation class UserListServlet
 */
@WebServlet("/UserListServlet")
public class UserListServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
 
    /**
     * @see HttpServlet#HttpServlet()
     */
    public UserListServlet() {
        super();
    }
 
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
 
    UserDao dao = new UserDao();
    ArrayList<UserDto> list = dao.getUserList();
    request.setAttribute("list", list);
    request.getRequestDispatcher("user_list.jsp").forward(request, response);
    }
 
}

実際の処理はマーキングした部分でDAOのgetUserListメソッドで得たユーザ一覧情報をrequestオブジェクトの属性に乗せて、結果を表示するUI:user_list.jspにフォーワードしているだけで、処理は簡潔です。

ユーザ一覧情報の表示を行うUI:user_list.jspでは、マーキング部が示すようにrequestオブジェクトの属性からユーザ情報をArrayListにに取り出し、拡張For文で一行づつHTMLに配置し表示し、戻るボタンで初期画面に戻れるようにしています。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.ArrayList" %>
<%@ page import="com.example.UserDto" %>
<% ArrayList<UserDto> list = (ArrayList<UserDto>)request.getAttribute("list"); %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登録済みユーザ一覧</title>
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/login.css">
</head>
<body>
    <h1>登録済みユーザ一覧</h1>
    <table>
        <tr><th>登録番号</th><th>ユーザID</th><th>パスワード</th></tr>
        <% for (UserDto ud: list) { %>
        <tr>
        <td><%= ud.getNo() %></td>
        <td><%= ud.getUserid() %></td>
        <td><%= ud.getPassword() %></td>
        </tr>
        <% } %>
    </table>
    <br>
    <hr>
    <form action="./login_main.jsp" method="post">
        <button type="submit"><pre><big>戻る</big></pre></button>
    </form>
</body>
</html>

次はユーザのログイン処理のための入力情報を受取るUI:user_login.jspです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ログインフォーム</title>
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/login.css">
</head>
<body>
<h1>ユーザログイン</h1>
<form action="./UserLoginServlet" method="post">
    <table>
        <tr>
            <th>ID</th>
            <th>パスワード</th>
            <th></th>
        </tr>
        <tr>
            <td><input type="text" name="id"  /></td>
            <td><input type="password" name="password" /></td>
            <td><input type="submit" value="実行"></td>
        </tr>
    </table>
</form>
<%
    String error = (String)request.getAttribute("error");
    if (error != null) {
%>
    <p style="color:red; font-size: larger;"><%= error %></p>
<%   } %>
<br>
<hr>
<form action="./login_main.jsp" method="post">
    <button type="submit"><pre><big>戻る</big></pre></button>
</form>
</body>
</html>

ユーザIDとパスワードを受取ったら、ログイン処理のコントロールを行っているサーブレット:UserLoginServletを呼びます。
一方、UserLoginServletで入力情報のエラーを発見するとエラーメッセージをrequestオブジェクトの属性に乗せてuser_login.jspを呼ぶので、本JSPの後半ではエラーメッセージがあれば表示しています。
また、戻るボタンで初期画面に戻るようになっています。

UserLoginServletでは、DAOのfindUserで入力されたユーザ情報が既に登録済か確認し、登録されていればログイン成功としてユーザIDをrequestオブジェクトの属性に乗せuser_login_success.jspを呼び、登録されていなければエラーメッセージをrequestオブジェクトの属性に乗せuser_login.jsp呼びます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.example;
 
import java.io.IOException;
 
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;
 
/**
 * Servlet implementation class LoginServlet
 */
@WebServlet("/UserLoginServlet")
public class UserLoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
 
    /**
     * @see HttpServlet#HttpServlet()
     */
    public UserLoginServlet() {
        super();
    }
 
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    request.setCharacterEncoding("UTF-8");
 
    String id = request.getParameter("id");
    String password = request.getParameter("password");
 
    UserDao dao = new UserDao();
    UserDto user = dao.findUser(id);
 
    boolean isLogin = (user != null && id.equals(user.getUserid()) &&
        password.equals(user.getPassword()));
    HttpSession session = request.getSession();
    session.setAttribute("isLogin", isLogin);
 
    if (isLogin) {
        request.setAttribute("username", user.getUserid());
        request.getRequestDispatcher("/user_login_success.jsp").forward(request, response);
    } else {
        request.setAttribute("error", "IDかパスワードが間違っています。\n再入力してください。");
        request.getRequestDispatcher("/user_login.jsp").forward(request, response);
    }
 
    }
}
ログインが成功した場合呼ばれるUIがuser_login_success.jspです。本JSPでは受け取ったユーザIDを使って、ログイン成功のメッセージを表示し、戻るボタンで初期画面に戻れるようにしています。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<%@ page language="HTML" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ユーザログイン成功</title>
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/login.css">
</head>
<body>
<h1>ユーザログイン成功</h1>
<hr>
<%
    String username = (String)request.getAttribute("username");
    if (username != null) {
%>
    <p style="color:blue; font-size: larger;">ようこそ<%= username %>さん!</p>
<%   } %>
<br>
<hr>
<form action="./login_main.jsp" method="post">
    <button type="submit"><pre><big>戻る</big></pre></button>
</form>
</body>
</html>

次はユーザの登録処理です。
まず登録のためのユーザ情報を受取るUI:user_regist.jspは、
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ログインフォーム</title>
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/login.css">
</head>
<body>
<h1>ユーザ登録</h1>
<form action="./UserRegServlet" method="post">
    <table>
        <tr>
            <th>ID</th>
            <th>パスワード</th>
            <th></th>
        </tr>
        <tr>
            <td><input type="text" name="id"  /></td>
            <td><input type="password" name="password" /></td>
            <td><input type="submit" value="登録"></td>
        </tr>
    </table>
</form>
<%
    String error = (String)request.getAttribute("error");
    if (error != null) {
%>
    <p style="color:red; font-size: larger;"><%= error %></p>
<%   } %>
<br>
<hr>
<form action="./login_main.jsp" method="post">
    <button type="submit"><pre><big>戻る</big></pre></button>
</form>
</body>
</html>

ユーザIDとパスワードを受取ったら、ユーザ登録処理のコントロールを行っているサーブレット:UserRegServletを呼びます。
一方、UserRegServletで入力情報のエラーを発見するとエラーメッセージをrequestオブジェクトの属性に乗せて本jspにフォーワードするので、後半でエラーメッセージがあればそれを表示しています。
また、戻るボタンで初期画面に戻るようになっています。

UserRegServletでは、DAOのfindUserで入力されたユーザ情報が既に登録済か確認し、登録されていればエラーメッセージをrequestオブジェクトの属性に乗せuser_regist.jspにフォーワードし、登録されていなければDAOのregUserを使ってユーザを登録し、ユーザ登録成功としてユーザIDをオブジェクトの属性に乗せuser_reg_success.jspをフォーワードします。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package com.example;
 
import java.io.IOException;
 
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;
 
/**
 * Servlet implementation class UserRegServlet
 */
@WebServlet("/UserRegServlet")
public class UserRegServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
 
    /**
     * @see HttpServlet#HttpServlet()
     */
    public UserRegServlet() {
        super();
    }
 
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    request.setCharacterEncoding("UTF-8");
 
    String id = request.getParameter("id");
    String password = request.getParameter("password");
 
    UserDao dao = new UserDao();
    UserDto user = dao.findUser(id);
 
    boolean isLogin = (user != null && id.equals(user.getUserid()) &&
        password.equals(user.getPassword()));
    HttpSession session = request.getSession();
    session.setAttribute("isLogin", isLogin);
 
    if (!isLogin) {
        int result = dao.regUser(id, password);
        request.setAttribute("username", id);
        request.getRequestDispatcher("/user_reg_success.jsp").forward(request, response);
    } else {
        request.setAttribute("error", "同じIDとパスワードのユーザが既に登録されています。\n再入力してください。");
        request.getRequestDispatcher("/user_regist.jsp").forward(request, response);
    }
 
    }
}
ユーザ登録が成功した場合に呼ばれるJSP:user_reg_success.jspは、受け取ったユーザIDを使って、ユーザ登録成功のメッセージを表示し、戻るボタンで初期画面に戻れるようにしています。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ユーザ登録成功</title>
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/login.css">
</head>
<body>
<h1>ユーザ登録成功</h1>
<hr>
<%
    String username = (String)request.getAttribute("username");
    if (username != null) {
%>
    <p style="color:blue; font-size: larger;"><%= username %>さんの登録が完了しました。</p>
<%   } %>
<br>
<hr>
<form action="./login_main.jsp" method="post">
    <button type="submit"><pre><big>戻る</big></pre></button>
</form>
</body>
</html>

次はユーザの削除処理です。
まず削除するユーザの情報を入力するUI:user_delete.jspです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ログインフォーム</title>
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/login.css">
</head>
<body>
<h1>ユーザ削除</h1>
<form action="./UserDelServlet" method="post">
    <table>
        <tr>
            <th>ID</th>
            <th>パスワード</th>
            <th></th>
        </tr>
        <tr>
            <td><input type="text" name="id"  /></td>
            <td><input type="password" name="password" /></td>
            <td><input type="submit" value="削除"></td>
        </tr>
    </table>
</form>
<%
    String error = (String)request.getAttribute("error");
    if (error != null) {
%>
    <p style="color:red; font-size: larger;"><%= error %></p>
<%   } %>
<br>
<hr>
<form action="./login_main.jsp" method="post">
    <button type="submit"><pre><big>戻る</big></pre></button>
</form>
</body>
</html>

ユーザIDとパスワードを受取ったら、ユーザ削除処理のコントロールを行っているサーブレット:UserDelServletを呼びます。
一方、UserDelServletで入力情報のエラーを発見するとエラーメッセージをrequestオブジェクトの属性に乗せて本jspにフォーワードするので、後半でエラーメッセージがあればそれを表示しています。
また、戻るボタンで初期画面に戻るようになっています。

UserDelServletでは、DAOのfindUserで入力されたユーザ情報が既に登録済か確認し、登録されていればDAOのdelUserを使ってユーザを削除し、ユーザ削除成功としてユーザIDをオブジェクトの属性に乗せuser_del_success.jspにフォーワードし、登録されていなければエラーメッセージをrequestオブジェクトの属性に乗せuser_delete.jspにフォーワードします。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package com.example;
 
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
/**
 * Servlet implementation class UserDelServlet
 */
@WebServlet("/UserDelServlet")
public class UserDelServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
 
    /**
     * @see HttpServlet#HttpServlet()
     */
    public UserDelServlet() {
        super();
 
    }
 
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    request.setCharacterEncoding("UTF-8");
 
    String id = request.getParameter("id");
    String password = request.getParameter("password");
 
    UserDao dao = new UserDao();
    UserDto user = dao.findUser(id);
 
    boolean isLogin = (user != null && id.equals(user.getUserid()) &&      
        password.equals(user.getPassword()));
 
    if (isLogin) {
        int result = dao.delUser(id, password);
        request.setAttribute("username", id);
        request.getRequestDispatcher("/user_del_success.jsp").forward(request, response);
    } else {
        request.setAttribute("error", "該当するIDとパスワードのユーザは登録されていません。\n再入力してください。");
        request.getRequestDispatcher("/user_delete.jsp").forward(request, response);
    }
 
    }
}
ユーザ削除が成功した場合に呼ばれるJSP:user_del_success.jspは、受け取ったユーザIDを使って、ユーザ削除成功のメッセージを表示し、戻るボタンで初期画面に戻れるようにしています。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ユーザ削除成功</title>
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/login.css">
</head>
<body>
<h1>ユーザ削除成功</h1>
<hr>
<%
    String username = (String)request.getAttribute("username");
    if (username != null) {
%>
    <p style="color:blue; font-size: larger;"><%= username %>さんの登録を削除しました。</p>
<%   } %>
<br>
<hr>
<form action="./login_main.jsp" method="post">
    <button type="submit"><pre><big>戻る</big></pre></button>
</form>
</body>
</html>

最後に処理の中で度々呼ばれていたDAOとDTOを示します。
DAOはJDBCを使ってデータベースに対するConnection及びclose処理を行い、必要なデータベース操作のSQL文を発行し、結果をDTOに格納する各種のメソッドを提供しています。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package com.example;
 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
 
public class UserDao {
 
    private static Connection getConnection() {
        try {
            Class.forName("org.postgresql.Driver");
            return DriverManager.getConnection("jdbc:postgresql:login","postgres", "root");
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        }
    }
 
    private static void allClose(PreparedStatement statement, Connection connection) {
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
 
    }
 
    static Connection connection = null;
    static PreparedStatement statement = null;
 
    public UserDto findUser(String id) {
        UserDto user = new UserDto();
 
        try {
            connection = getConnection();
 
            statement = connection.prepareStatement("SELECT * FROM userinf WHERE userid = ?");
            statement.setString(1, id);
            ResultSet resultSet = statement.executeQuery();
 
            if (!resultSet.next()) { return null; }
 
            user.setUserid(resultSet.getString("userid"));
            user.setPassword(resultSet.getString("password"));
 
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            allClose(statement, connection);
        }
        return user;
 
    }
    public ArrayList<UserDto> getUserList() {
        ArrayList<UserDto> list = new ArrayList<UserDto>();
 
        try {
            connection = getConnection();
 
            statement = connection.prepareStatement("SELECT * FROM userinf");
            ResultSet resultSet = statement.executeQuery();
 
            while (resultSet.next()) {
                UserDto ud = new UserDto();
                ud.setNo(resultSet.getInt(1));
                ud.setUserid(resultSet.getString(2));
                ud.setPassword(resultSet.getString(3));
                list.add(ud);
            }
 
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            allClose(statement, connection);
        }
        return list;
 
    }
 
    public int regUser(String id, String password) {
        int result = 0;
 
        try {
            connection = getConnection();
 
            statement = connection.prepareStatement("INSERT INTO userinf (userid, password) VALUES (?, ?)");
            statement.setString(1, id);
            statement.setString(2, password);
            result = statement.executeUpdate();
 
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            allClose(statement, connection);
        }
        return result;
 
    }
 
    public int delUser(String id, String password) {
        int result = 0;
 
        try {
            connection = getConnection();
 
            statement = connection.prepareStatement("DELETE FROM userinf WHERE userid = ? AND password = ?");
            statement.setString(1, id);
            statement.setString(2, password);
            result = statement.executeUpdate();
 
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            allClose(statement, connection);
        }
        return result;
 
    }
 
}
そしてDTOはビジネスロジックが必要とするオブジェクト情報へのgetterとsetterを提供します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.example;
 
public class UserDto {
    private int no;
    private String userid;
    private String password;
 
    public int getNo() {
        return no;
    }
    public String getUserid() {
        return userid;
    }
    public String getPassword() {
        return password;
    }
 
    public void setNo(int no) {
        this.no = no;
    }
    public void setUserid(String userid) {
        this.userid = userid;
    }
    public void setPassword(String password) {
        this.password = password;
    }
 
}

以上のようにDAOを使うことでJSPやServletの数は増えますが、全体構造は簡潔になり保守性、拡張性が向上しログイン処理(書き下し版)とは異なる形になった事が分かるでしょう。

次のステップ:ログイン処理(DAOを使った汎用的で現実的な構造)
ではDAOを使ったより汎用的で、現実的な構造を考えます。

カテゴリー: JSP_Servlet タグ: , , , , , , , パーマリンク