今回からJavaでのWebアプリケーションを作成していきます。
前回の内容はこちら
プロジェクトの作成
まずはWebアプリケーション用の新規プロジェクトを準備しましょう。
【右クリック→新規→その他】
【Web→動的Webプロジェクトを選択→次へ】
プロジェクト名を入力し(CustomerManagement)【次へ】
デフォルトのまま【次へ】
web.xmlデプロイメントの記述子の生成にチェックし、【完了】
これで今回のWebアプリケーションのプロジェクトが作成されました。
プロジェクトをTomcatに設定する
TomcatはJavaでWebアプリケーションを動作させるために使用します。
JavaのWebアプリケーションはServletやJSPを使用して作成しますが、その実行環境を提供するのがTomcatです。Webコンテナとも呼ばれます。
一連の流れとしてはクライアントからのリクエストをWebコンテナで受け取り、Servletで値を処理し、その結果をJSPでクライアントにレスポンスします。
イメージ図
もっと詳しく知りたい方はこちら
ではTomcatに今回のプロジェクトを設定します。
【サーバー】と検索
以下のリンクをクリック
Tomcat v9.0サーバを選択し、【次へ】
プロジェクトを追加し、【完了】
これでプロジェクトをTomcat(Webコンテナ)に設定することができました。
Servletの作成
ではログイン画面をブラウザに表示させるためにServletを作成します。
【src(右クリック)→新規→その他】
「サーブレット」を選択し、【次へ】
Javaパッケージ:servlet / クラス名:LoginServlet
【完了】を選択
LoginServlet.javaにプログラムを記入していきます。
package servlet;
import java.io.IOException;
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;
/**
* Servlet implementation class LoginServlet
*/
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
//ログイン画面を表示させる
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
RequestDispatcher dispatcher =
request.getRequestDispatcher("WEB-INF/jsp/login.jsp");
dispatcher.forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
管理者ログイン画面を表示させるためにまずはブラウザからのURLリクエストをServletで受け取ります。doGetメソッドがその役割を担い、login.jspを表示させるようレスポンスを返します。
JSPの作成
ではログイン画面を作成していきます。
以下の構成でlogin.jspを作成します。
WebContent
画面を表示するJSPファイルは必ずWebContent内に作成してください。
└─WEB-INF
└─ jsp
└─ login.jsp
※ WebContent内に作成しなければならない理由を知りたい方はこちら
【WEB-INFを右クリック→新規→その他】を選択
「JSPファイル」を選択し、【次へ】
ファイル名に「jsp/login.jsp」を入力し、【完了】を選択
「login.jsp」は以下のようにして作成しています。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
<title>ログイン画面</title>
</head>
<body>
<div class="mx-auto" style="width: 300px;">
<h1 class="mb-3" style="text-align: center">管理者ログイン画面</h1>
<form action="/CustomerManagement/LoginServlet" method="post">
<div class="mb-3">
<label for="adminID" class="form-label">管理者ID</label>
<input type="text" class="form-control" id="adminID" name="admin_id">
</div>
<div class="mb-3">
<label for="pass" class="form-label">パスワード</label>
<input type="password" class="form-control" id="pass" name="password">
</div>
<button type="submit" class="btn btn-primary">ログイン</button>
</form>
</div>
</body>
</html>
管理者のIDとパスワードを入力するログイン画面となります。
8行目:BootStrapを使用するためのCDN
14行目:ログインボタンを押下後、処理をLoginServletのdoPostメソッドに渡す
17行目:入力された管理者IDの値をLoginServletのdoPostメソッドに渡す
21行目:入力されたパスワードの値をLoginServletのdoPostメソッドに渡す
では実際にTomcatを起動させて、以下のURLにアクセスしてみましょう。
http://localhost:8080/CustomerRepo/LoginServlet
するとログイン画面が表示されます。
管理者ID、パスワードを入力してログインボタンを押下しても現状はログイン機能を作成していないので何も処理は実行されません。
MySQLで管理者データの登録
では一旦Javaから離れてMySQLで管理者用のデータ(管理者ID , パスワード)を格納するテーブルを作成していきます。
今回はMySQLのバージョンは以下で実施しています。(どのバージョンでもOKです)
command $ mysql --version
mysql Ver 14.14 Distrib 5.7.36, for osx10.16 (x86_64) using EditLine wrapper
MySQLがインストールされていない方はこちら(Windows / Mac)
※ここではSQLの解説はしていません。詳しく学びたい方は以下から
MySQLサーバのステータス確認
$ mysql.server status
ERROR! MySQL is not running
MySQLサーバの起動
$ mysql.server start
Starting MySQL
.. SUCCESS!
MySQLにログインする
(ログイン情報を「ユーザ:root , パスワード:pass1234」で設定しています)
$ mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.36 Homebrew
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
データベースの作成
mysql> create database customer_management_db;
Query OK, 1 row affected (0.01 sec)
mysql>
作成したデータベースにアクセス
mysql> use customer_management_db;
Database changed
mysql>
管理者用のテーブルを作成
mysql> create table admin_tb (admin_id int(11) not null auto_increment,
-> name varchar(20) not null,
-> password varchar(20) not null,
-> primary key (admin_id)
-> );
Query OK, 0 rows affected (0.09 sec)
mysql>
テーブルの定義を確認
mysql> desc admin_tb;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| admin_id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| password | varchar(20) | NO | | NULL | |
+----------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
mysql>
管理者のデータを作成
mysql> insert into admin_tb(name , password) values("管理者1" , "11111111");
Query OK, 1 row affected (0.04 sec)
mysql>
作成した管理者のデータを確認
mysql> select * from admin_tb;
+---------+------------+----------+
| admin_id | name | password |
+---------+------------+----------+
| 1 | 管理者1 | 11111111 |
+---------+------------+----------+
1 row in set (0.01 sec)
mysql>
これで管理者のデータを登録することができました。後ほどログイン機能を作成しますが、ログイン画面で入力された管理者IDとパスワードがadmin_tbのadmin_idとpasswordに一致すればログインできるという実装になります。
JDBCのダウンロードと設定
ここではJDBC(Java Database Connectivity)のダウンロードと設定を行っていきます。
JDBCを簡単に説明しておくと、JavaのプログラムからデータベースにアクセスできるようにするJavaのAPIの一つになります。
今回はMySQLを使用していますので、MySQL用のJDBCをダウンロードする必要があります。
https://www.mysql.com/jp/products/connector/
JDBC Driver for MySQL (Connector/J)のダウンロードを選択
該当するOSを選択
※今回はMacでダウンロードを行っています。
zipファイルでダウンロードをします。
【No thanks,just start my download】をクリックするとダウンロードが始まります。
ダウンロード後、展開してデスクトップ上に配置しておきます。
ではプロジェクトにJDBCを設定していきます。
プロジェクトを選択し、「右クリック→ビルド・パス→ビルド・パスの構成」を選択
「ライブラリー → クラスパス → 外部JARの追加」を選択
先ほどデスクトップに配置した「mysql-connector-j-8.0.31」フォルダ内の「mysql-connector-j-8.0.31.jar」を選択し、「Open」を選択
クラスパスにJDBCが追加されていることを確認し、「適用して閉じる」を選択
「参照ライブラリー」に追加されていることを確認
これでプロジェクトにJavaからデータベースにアクセスするためのJDBCのダウンロードと設定が完了しました。
データベースへの接続情報を持たせるクラスを作成
JavaからJDBCを利用してデータベースにアクセスする際にも接続情報、ユーザ、パスワードが必要となります。
それらをログイン機能を実装するLoginServlet.java上に直接記載しても良いのですが、パスワードを変更するなどの際にはもう一度コンパイルする必要があり、非効率です。
コンパイルせずとも、パスワードを自由に変更できるようにPropertiesクラスを使用して、データベースの接続情報を管理するようにします。
まずはデータベースへの接続情報を持たせたファイル「DBconfig.properties」を作成します。
ファイル名を「DBconfig.properties」にし、【完了】
プロパティファイルは「キー = 値」という形式で、いずれもString型として設定されます。
キーを指定することで値が取得できます。
url=jdbc:mysql://localhost:3306/customer_management_db
user=root
password=pass1234
これでプロパティファイルの設定ができました。
ではプロパティファイル内のデータベース接続情報を取得するクラスを作成します。
パッケージ名:config / クラス名:DBconfig として、【完了】
package config;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class DBconfig {
// データベースの接続情報を取得するメソッド
public Map<String, String> getDBinfo() throws FileNotFoundException {
// プロパティファイルのフルパスを指定
String db_properties_file = "/Applications/Eclipse_2020-12.app/Contents/workspace/CustomerManagement/DBconfig.properties";
Properties db_info = new Properties();
FileInputStream db_file_stream = new FileInputStream(db_properties_file);
try {
// プロパティファイルを読み込む
db_info.load(db_file_stream);
} catch (IOException e) {
System.out.println("データベース設定ファイルが認識できませんでした");
e.printStackTrace();
}
//DBconfig.propertiesのキーから値を取得する
String db_url = db_info.getProperty("url");
String db_user = db_info.getProperty("user");
String db_pass = db_info.getProperty("password");
// 取得したデータベースの接続情報をMapに格納する
Map<String,String> getDBinfoForMap = new HashMap<>();
getDBinfoForMap.put("url", db_url);
getDBinfoForMap.put("user", db_user);
getDBinfoForMap.put("password", db_pass);
// DBconfigクラスの
// getDBinfoメソッドが呼び出された際に
// 『接続情報、ユーザ名、パスワード』の情報を返す
return getDBinfoForMap;
}
}
18行目:Propertiesクラスの使い方はこちら
19行目:ファイルをJVM(Java仮想マシン)に読み込むための入力ストリームクラスです。ファイル入出力について詳しくはこちら
これでプロパティファイルからデータベースの接続情報を取得するクラス・メソッドを作成できました。
ログイン機能の作成
ではログイン処理の実装をしていきます。
package servlet;
import java.io.IOException;
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 config.DBconfig;
/**
* Servlet implementation class LoginServlet
*/
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
//ログイン画面を表示させる
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
RequestDispatcher dispatcher =
request.getRequestDispatcher("WEB-INF/jsp/login.jsp");
dispatcher.forward(request, response);
}
// ログイン処理の実装
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 文字コードの設定
response.setContentType("text/html; charset=UTF-8");
request.setCharacterEncoding("UTF-8");
// ログイン画面で入力された値を取得
String user_id = request.getParameter("admin_id");
String password = request.getParameter("password");
}
}
36〜37行目:ログイン画面で入力された値をlogin.jspの「name=”admin_id” と name=”password”」から取得しています。
doPostメソッド内にログイン処理のプログラムを全て書いても良いのですが、冗長的なプログラムになってしまいます。
そこで、ログイン画面で入力された値がデータベースに存在するか(存在すればログイン成功とする)の確認を行うSQLの処理を別クラスで作成します。
パッケージ名:sql / クラス名:Login
またデータベースから取得した値(管理者ID、 ユーザ名、 パスワード)を格納するクラス(Admin.java)も作成しておきます。
パッケージ名:object / クラス名:Admin
package object;
public class Admin {
private int id;
private String name;
private String password;
private boolean login_flag;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isLogin_flag() {
return login_flag;
}
public void setLogin_flag(boolean login_flag) {
this.login_flag = login_flag;
}
}
データベースから取得した値を格納・取得するAdminオブジェクトを作成しました。
フィールドに設定してあるlogin_flagはログイン画面で入力した値とデータベースでの値が一致すればtrueを返すフラグです。
ではログイン画面で入力された値(管理者IDとパスワード)とデータベースに登録された値が一致するかの確認を行うSQLの実装をしていきます。
package sql;
import java.io.FileNotFoundException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import config.DBconfig;
import object.Admin;
public class Login {
public Admin check(String admin_id, String password) throws FileNotFoundException {
// データベースへの接続情報をプロパティファイルから取得
DBconfig db_info = new DBconfig();
String url = db_info.getDBinfo().get("url");
String user = db_info.getDBinfo().get("user");
String pass = db_info.getDBinfo().get("password");
// 実行SQL
String login_sql = "select * from admin_tb "
+ "where admin_id = ? and password = ?;";
// 管理者のオブジェクトを作成
Admin admin = new Admin();
// データベースへの接続
// try〜catch〜resources構文を使用
try(Connection conn = DriverManager.getConnection(url,user,pass)) {
PreparedStatement stmt = conn.prepareStatement(login_sql);
// 変数login_sqlの一番目の?に引数のuser_idをセット
stmt.setString(1, admin_id);
// 変数login_sqlの二番目の?に引数のpasswordをセット
stmt.setString(2, password);
// SQLを実行し、結果を取得
ResultSet rs = stmt.executeQuery();
// データベースから取得した値をAdminオブジェクトに格納
// 値がなければ、login_flag(false)のみ格納
if(rs.next()) {
admin.setId(rs.getInt("admin_id"));
admin.setName(rs.getString("name"));
admin.setPassword(rs.getString("password"));
admin.setLogin_flag(true);
} else {
admin.setLogin_flag(false);
}
} catch (SQLException e) {
System.out.println("データベースとの接続を閉じます");
e.printStackTrace();
}
// データベースから取得した値を返す
return admin;
}
}
checkメソッドの引数にログイン画面で入力された管理者IDとパスワードを持たせ、それをもとにデータベースにアクセスし、データを取得するSQLを作成しています。そのSQLから取得した値をAdminオブジェクトに格納してreturnで返しています。
try〜catch〜resourcesについてはこちら
作成したcheckメソッドをLoginServletのdoPostメソッドで使用できるようにし、ログイン機能を完成させます。
package servlet;
import java.io.IOException;
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 object.Admin;
import sql.Login;
/**
* Servlet implementation class LoginServlet
*/
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
//ログイン画面を表示させる
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
RequestDispatcher dispatcher =
request.getRequestDispatcher("WEB-INF/jsp/login.jsp");
dispatcher.forward(request, response);
}
// ログイン処理の実装
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 文字コードの設定
response.setContentType("text/html; charset=UTF-8");
request.setCharacterEncoding("UTF-8");
// ログイン画面で入力された値を取得
String user_id = request.getParameter("admin_id");
String password = request.getParameter("password");
// ログイン画面で入力された値をもとに
// データベースに登録された管理者の値を取得
// 入力された情報でデータベースから値が取得できない場合
// ログイン失敗
Login login = new Login();
Admin admin = login.check(user_id, password);
if(admin.isLogin_flag()) {
// ログイン成功 → 次の画面へ遷移
System.out.println("ログイン成功");
RequestDispatcher dispatcher =
request.getRequestDispatcher("WEB-INF/jsp/customer_list.jsp");
dispatcher.forward(request, response);
} else {
// ログイン失敗 → ログイン画面へ遷移
System.out.println("ログイン失敗");
RequestDispatcher dispatcher =
request.getRequestDispatcher("WEB-INF/jsp/login.jsp");
dispatcher.forward(request, response);
}
}
}
追記箇所:40〜59行目
admin.isLogin_flag()がtrueであればログイン後の画面(顧客一覧画面)へ、falseであればログイン画面を再度表示させます。
顧客一覧画面の作成
では最後にログイン成功時に遷移する画面(顧客一覧画面)を作成しておきます。
「JSPファイル」を選択し、【完了】
ファイル名:customer_list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>顧客一覧画面</title>
</head>
<body>
<h1>ログイン成功</h1>
</body>
</html>
ではTomcatを起動させ、ログイン画面に管理者情報を入力してみましょう。
管理者ID:1 / パスワード:11111111
上記を入力すると、以下の画面が表示されていると思います。
画面が遷移し「ログイン成功」と表示されていればOKです。
現在はまだログイン成功後の画面を作成しておりませんので、この状態となっておりますが、次回からはログイン時に管理者が登録した顧客の一覧を表示する顧客一覧画面を作成していきます。
今回はかなりボリュームがあったと思いますが、最後まで閲覧していただきありがとうございました。紹介したプログラム以外にもっといいコードの書き方があればぜひお知らせください。ここで他の方にも共有させていただきます。
次回の内容はこちら
コメント
DBconfig.javaの38行目のgetDBinfoForMap.put(“url”, db_pass);がgetDBinfoForMap.put(“password”, db_pass);の間違いだと思います。
田中太郎さん
閲覧していただき、ありがとうございます。
ご指摘の通り訂正しました。今後ともよろしくお願いします。