データベース連携(JDBC)

(ブログ記事の一覧は「こちら」)

JavaのWebアプリで、DB(データベース)にアクセスする方法について確認していきましょう。

DBの作成、準備

Windowsの環境の場合、XAMMPを用いて、以下を構築してください。

DBを作成

db_sa2_sample

テーブルを生成

tbl_sa2_sample

テーブルの構造

名前 データ型 その他
id int primary
name varchar(128) -
hobby varchar(128) -

【参考】テーブル作成のSQL

CREATE TABLE `db_sa2_sample`.`tbl_sa2_sample` ( `id` INT NOT NULL AUTO_INCREMENT , `name` VARCHAR(128) NOT NULL , `hobby` VARCHAR(128) NOT NULL , PRIMARY KEY (`id`)) ENGINE = InnoDB CHARSET=utf8 COLLATE utf8_unicode_ci;

ダウンロード

以下のURLから、必要なjarファイルをダウンロードします。
https://downloads.mysql.com/archives/c-j/

バージョンは「5.1.xx」を選択してください。「mysql-connector-java-5.1.xx-bin.jar」を使用します。

プロジェクトの設定

「プロジェクト名」を右クリックして、「ビルド・パス」-「ビルド・パスの構成」を選択します。 (Eclipseの環境によっては、「プロジェクト名」を右クリックして、「プロパティ」を選択して、「Javaのビルド・パス」を選択します。)

Javaのビルド・パス」ウィンドウの「ライブラリー」タブが開きますので、右側の「外部JARの追加」ボタンをクリックして、ダウンロードしたjarファイルを追加します。

次に、左側のリストから「デプロイメント・アセンブリー」を選択します。右側の「追加」ボタンをクリックするとダイアログが開くので、「Javaビルド・パス・エントリー」が選択された状態で「次へ」ボタンをクリックして、表示されているjarファイルを選択して「完了」ボタンをクリックします。

プロジェクトの設定は以上です。

サンプルプログラム(データの登録)

セッションスコープ」のサンプルプログラムを利用して、入力フォームの値をDBに保存するサンプルを作成します。

画面の流れは、変更はありません。「確認画面」で「進む」を選択すると、「DBに保存」の処理を行い、「完了画面」に移ります。

「入力フォーム」 ⇒ 「確認画面」 ⇒ (「DBに保存」→「完了画面」)

対応するプログラムのファイルは以下のようになります。

[form.jsp]
 ⇒ (( [MainServlet.java] ↔ [UserInfo.java] )→ [confirm.jsp] )
 ⇒ (( [MainServlet.java] ↔ [DbManager.java] )→ [done.jsp] )

プロジェクト名、パッケージ名は、以下のようにしています。

プロジェクト名:SessionTest
パッケージ名:com.test.session

【M】JavaBeans(UserInfo.java

セッションスコープ」のサンプルプログラムと同じです。

DBに接続、データを保存(DbManager.java

新規にクラスを作成します。(最初に作成した)DBに接続して、SQL(ここでではINSERT文)を実行します。

package com.test.session;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DbManager {
    
    public void InsertUserInfo(UserInfo userInfo) {
        final String DSN = "jdbc:mysql://localhost/db_sa2_sample?characterEncoding=utf8";
        final String USER = "root";
        final String PASSWORD = "";
        
        Connection conn = null;
        try {
            // JDBCドライバのロード
            Class.forName("com.mysql.jdbc.Driver");
            
            // DBに接続
            conn = DriverManager.getConnection(DSN, USER, PASSWORD);
            
            // SQL
            String sql = "INSERT INTO tbl_sa2_sample (name, hobby) values (?, ?)";
            PreparedStatement pStmt = conn.prepareStatement(sql);
            pStmt.setString(1, userInfo.getName());
            pStmt.setString(2, userInfo.getHobby());
            
            // 実行
            int num = pStmt.executeUpdate();
            
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            // DBを切断
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

jarファイルのバージョンによっては、プログラムも変わってきます。「mysql-connector-java-8.0.xx.jar」を使用した場合、該当の箇所について、それぞれ以下のように書き換えてください。

   final String DSN = "jdbc:mysql://localhost:3306/db_sa2_sample?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B9:00&rewriteBatchedStatements=true";
   // JDBCドライバのロード
    Class.forName("com.mysql.cj.jdbc.Driver");

【V】JSP(form.jsp

セッションスコープ」のサンプルプログラムと同じです。

【V】JSP(confirm.jsp

セッションスコープ」のサンプルプログラムと同じです。

【V】JSP(done.jsp

セッションスコープのサンプルプログラムを利用していますのでJSPファイルですが、データの読み込みは行っていないのでHTMLファイルでも構いません。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>完了画面</title>
</head>
<body>
    <p>登録が完了しました。</p>

    <a href="/SessionTest/MainServlet">戻る</a>
</body>
</html>

【C】サーブレット(MainServlet.java

doGetメソッドにて、パラメータが「action=done」の場合に、セッションスコープに保存された情報をDBに保存する処理を追加します。その後、不要となったセッションスコープ内のインスタンスを削除して、完了画面に移動します。

@WebServlet("/MainServlet")
public class MainServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    public MainServlet() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=UTF-8");

        // フォワード先
        String strForwardPath = null;
        
        String strAction = request.getParameter("action");

        if (strAction == null) {
            // フォワード先を設定(入力フォーム)
            strForwardPath = "/form.jsp";
            
        } else if (strAction.equals("done")) {
            // セッションスコープに保存された情報
            HttpSession session = request.getSession();
            UserInfo userInfo = (UserInfo) session.getAttribute("user_info");
            
            // DBに保存
            DbManager dbManager = new DbManager();
            dbManager.InsertUserInfo(userInfo);
            
            // 不要となったセッションスコープ内のインスタンスを削除
            session.removeAttribute("user_info");

            // 登録後のフォワード先を設定(完了画面)
            strForwardPath = "/done.jsp";
        }
        
        // 設定されたフォワード先にフォワード
        RequestDispatcher dispatcher = request.getRequestDispatcher(strForwardPath);
        dispatcher.forward(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=UTF-8");
        
        String strName = request.getParameter("name");
        String strHobby = request.getParameter("hobby");
        
        // UserInfoクラス(JavaBeans)
        UserInfo userInfo = new UserInfo();
        userInfo.setName(strName);
        userInfo.setHobby(strHobby);

        // セッションスコープに保存
        HttpSession session = request.getSession();
        session.setAttribute("user_info", userInfo);

        // フォワード(確認画面)
        RequestDispatcher dispatcher = request.getRequestDispatcher("/confirm.jsp");
        dispatcher.forward(request, response);
    }
}

実行

「MainServlet.java」を実行します。完了画面に進んだとき、入力した値がDBに保存されていることを確認してください。


サンプルプログラム(データの取得)

DBに接続、データの読み込み(DbManager.java

DbManager.java に以下のメソッドを追加します。

   public ArrayList<UserInfo> getUserInfo() {
        
        final String DSN = "jdbc:mysql://localhost/db_sa2_sample?characterEncoding=utf8";
        final String USER = "root";
        final String PASSWORD = "";
        
        ArrayList<UserInfo> arUserInfo = new ArrayList();
        
        Connection conn = null;
        try {
            // JDBC ドライバのロード
            Class.forName("com.mysql.jdbc.Driver");
            
            // データベースへ接続
            conn = DriverManager.getConnection(DSN, USER, PASSWORD);
            
            // SQL
            String sql = "SELECT * FROM tbl_sa2_sample";
            PreparedStatement pStmt = conn.prepareStatement(sql);
            // 実行
            ResultSet rs = pStmt.executeQuery();
            
            // 結果表に格納されたレコードの内容を表示
            while (rs.next()) {
                String name = rs.getString("name");
                String hobby = rs.getString("hobby");
                
                UserInfo userInfo = new UserInfo();
                userInfo.setName(name);
                userInfo.setHobby(hobby);
                
                arUserInfo.add(userInfo);
            }
            
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            // データベース切断
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        
        return arUserInfo;
    }   

【C】サーブレット(ShowDataServlet.java

新規にサーブレットクラスを作成します。

package com.test.session;

import java.io.IOException;
import java.io.PrintWriter;
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;

@WebServlet("/ShowDataServlet")
public class ShowDataServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    public ShowDataServlet() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 文字コードをセット(日本語の文字化けを避ける)
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=UTF-8");
        
        // UserInfoクラス(JavaBeans)
        DbManager dbManager = new DbManager();
        // DBの全データを取得
        ArrayList<UserInfo> arUserInfo = dbManager.getUserInfo();
        
        PrintWriter out = response.getWriter();
        for (int i = 0; i < arUserInfo.size(); i++) {
            UserInfo userInfo = arUserInfo.get(i);
            out.println(userInfo.getName() + " " + userInfo.getHobby() + "<br>");
        }
    }

}

実行

「ShowDataServlet.java」を実行します。

セッションスコープ

(ブログ記事の一覧は「こちら」)

セッションとは、サーバー側でデータを保持する仕組みのことです。

セッションスコープとは、クライアントからのリクエスト(request)とサーバーで作成したセッション(Session)の間でのスコープのことです。

セッションスコープは、クライアントが作成したセッションが破棄されるまで有効です。
セッションが破棄される例は、以下のものがあります。

  • 破棄するメソッド(removeAttribute)を呼び出した場合
  • 一定時間が経過した場合
  • ブラウザを閉じた場合


セッションスコープに保存
   // UserInfoクラス(JavaBeans)
    UserInfo userInfo = new UserInfo();
    userInfo.setName(strName);
    userInfo.setHobby(strHobby);

    // セッションスコープに保存
    HttpSession session = request.getSession();
    session.setAttribute("user_info", userInfo);
セッションスコープからインスタンスを取得
<%@ page import="com.test.session.UserInfo" %>
<%
    // セッションスコープからUserInfoクラスのインスタンスを取得
    UserInfo userInfo = (UserInfo) session.getAttribute("user_info");
%>

"user_info" は属性名です。保存と取得のときに文字列として一致していれば、属性名は自由に設定して問題ありません。

サンプルプログラム

MVCモデルで作成した、セッションスコープを利用したサンプルを作成します。

画面の流れは以下のようになります。

「入力フォーム」 ⇒ 「確認画面」 ⇒ 「完了画面」

対応するプログラムのファイルは以下のようになります。

[form.jsp]
 ⇒ (( [MainServlet.java] ↔ [UserInfo.java] )→ [confirm.jsp] )
 ⇒ ( [MainServlet.java] → [done.jsp] )

プロジェクト名、パッケージ名は、以下のようにしています。

プロジェクト名:SessionTest
パッケージ名:com.test.session

【M】JavaBeans(UserInfo.java

package com.test.session;

import java.io.Serializable;

public class UserInfo implements Serializable {

    private String name;
    private String hobby;

    public UserInfo() {}

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getHobby() {
        return this.hobby;
    }
 
    public void setHobby(String hobby) {
        this.hobby = hobby;
    }
}

【V】JSP(入力フォーム :form.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>
    <form action="/SessionTest/MainServlet" method="post">
        名前:<input type="text" name="name">
        趣味:<input type="text" name="hobby">
        <input type="submit" value="送信する">
    </form>
</body>
</html>

【V】JSP(確認画面:confirm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%@ page import="com.test.session.UserInfo" %>
<%
    // UserInfoクラス(JavaBeans)
    UserInfo userInfo = (UserInfo) session.getAttribute("user_info");
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>確認画面</title>
</head>
<body>
    <p>確認</p>

    <p>
    名前:<%= userInfo.getName() %>
    </p>
    <p>
    趣味:<%= userInfo.getHobby() %>
    </p>

    <a href="/SessionTest/MainServlet">戻る</a>
    <a href="/SessionTest/MainServlet?action=done">進む</a>
</body>
</html>

【V】JSP(完了画面:done.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%@ page import="com.test.session.UserInfo" %>
<%
    // UserInfoクラス(JavaBeans)
    UserInfo userInfo = (UserInfo) session.getAttribute("user_info");
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>完了画面</title>
</head>
<body>
    <p>完了</p>

    <p>
    名前:<%= userInfo.getName() %>
    </p>
    <p>
    趣味:<%= userInfo.getHobby() %>
    </p>

    <a href="/SessionTest/MainServlet">戻る</a>
</body>
</html>

【C】サーブレット(MainServlet.java

package com.test.session;

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 javax.servlet.http.HttpSession;

@WebServlet("/MainServlet")
public class MainServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    public MainServlet() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // フォワード先
        String strForwardPath = null;
        
        String strAction = request.getParameter("action");
        
        if (strAction == null) {
            // フォワード先を設定(入力フォーム)
            strForwardPath = "/form.jsp";
            
        } else if (strAction.equals("done")) {
            // フォワード先を設定(完了画面)
            strForwardPath = "/done.jsp";
        }
        
        // 設定されたフォワード先にフォワード
        RequestDispatcher dispatcher = request.getRequestDispatcher(strForwardPath);
        dispatcher.forward(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 文字コードをセット(日本語の文字化けを避ける)
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=UTF-8");

        // 入力フォームの値を取得       
        String strName = request.getParameter("name");
        String strHobby = request.getParameter("hobby");
        
        // UserInfoクラス(JavaBeans)
        UserInfo userInfo = new UserInfo();
        userInfo.setName(strName);
        userInfo.setHobby(strHobby);

        // セッションスコープに保存
        HttpSession session = request.getSession();
        session.setAttribute("user_info", userInfo);

        // フォワード(確認画面)
        RequestDispatcher dispatcher = request.getRequestDispatcher("/confirm.jsp");
        dispatcher.forward(request, response);
    }

}

課題

上記のサンプルについて、入力項目を「名前」「趣味」から、「特技」を加えたものに修正してください。

リクエストスコープ(サーブレット、JSP、JavaBeansの連携)

(ブログ記事の一覧は「こちら」)

サーブレット」「JSP」「JavaBeans」で学んだものを組み合わせて作成します。

ここで、MVC(Model View Controller)モデルという考え方について確認しておきましょう。

様々なアプリを作成するとき、ある程度の規模になる場合は、プログラム全体の設計を行うことが必要になりますが、ここで一般的によく使われるものとしてMVCモデルがあります。
今回のJavaによるWebアプリでは、それぞれ以下に該当します。

  • M(Model):JavaBeans
  • V(View):JSP(JavaServer Pages)
  • C(Controller):サーブレット 【 Controller(MVCのC)】

基本的な仕組みとして、「C(Controller)」から処理を開始して、「C」が「M(Model)」で定義しているデータ形式でデータを受け取り、「C」が「M」でのデータを「V(View)」に渡して表示する、という流れになります。

ウィキペディアWikipedia)のページも参考にしてください。

リクエスト(request)スコープ

スコープとは、データの有効な範囲のことです。
リクエストスコープとは、クライアントからのリクエスト(request)とサーバーからのレスポンス(Response)の間でのスコープのことです。

つまり、MVCモデルで作成したプログラム間でデータが保持されるので、便利な活用ができます。

以下は、UserInfoクラス(JavaBeans)を対象とした、リクエストスコープへの保存とインスタンスの取得のプログラム例です。

リクエストスコープに保存
   // UserInfoクラス(JavaBeans)
    UserInfo userInfo = new UserInfo();
    userInfo.setName(strName);
    userInfo.setHobby(strHobby);

    // リクエストスコープに保存
    request.setAttribute("user_info", userInfo);
リクエストスコープからインスタンスを取得
   // リクエストスコープからUserInfoクラスのインスタンスを取得
    UserInfo userInfo = (UserInfo) request.getAttribute("user_info");

"user_info" は属性名です。保存と取得のときに文字列として一致していれば、属性名は自由に設定して問題ありません。

サンプル1(MVC

フォワード」のページのサンプルに対して、MVCモデルに合わせた書き方に変更してみましょう。

「HTMLファイル」
    ⇒ ((「サーブレットクラス」 ↔ 「JavaBeans」)→ 「JSPファイル」)

フォワードのページのサンプルでは、MVCモデルの「VC」を使用した書き方になっていました。これにJavaBeansの仕様にあてはまるクラスを追加することで、MVCモデルを完成させましょう。

【M】JavaBeans(UserInfo.java

JavaBeansで作成したクラスを使用します。

【V】JSP(result.jsp)の修正

JavaBeansで定義したUserInfoクラスを呼び出し、各項目のデータを取得しています。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%@ page import="com.test.UserInfo" %>
<%
    // UserInfoクラス(JavaBeans)
    UserInfo userInfo = (UserInfo) request.getAttribute("user_info");
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<%
    // 文字コードをセット(日本語の文字化けを避ける)
    request.setCharacterEncoding("UTF-8");
    response.setContentType("text/html; charset=UTF-8");
%>

<p>
name:<%= userInfo.getName() %>
</p>
<p>
hobby:<%= userInfo.getHobby() %>
</p>

</body>
</html>

【C】サーブレット(MainServlet.java)の修正

doPostメソッドを修正します。

JavaBeansで定義したUserInfoクラスを呼び出し、各項目のデータをセットして、JSPフォワードしています。

   protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=UTF-8");

        String strName = request.getParameter("name");
        String strHobby = request.getParameter("hobby");

        // UserInfoクラス(JavaBeans)
        UserInfo userInfo = new UserInfo();
        userInfo.setName(strName);
        userInfo.setHobby(strHobby);

        request.setAttribute("user_info", userInfo);

        // フォワード
        RequestDispatcher dispatcher = request.getRequestDispatcher("/result.jsp");
        dispatcher.forward(request, response);
    }


サンプル2(メソッドの追加)

JavaBeansに新たなメソッドを追加して、そのメソッドを使用するサンプルを作成します。

【M】JavaBeans(UserInfo.java)への追加

新たなメソッドを追加します。下のプログラムを見てわかるように、「名前」「趣味」のデータを含む文章を返すメソッドを作成します。

package com.test;

import java.io.Serializable;

public class UserInfo implements Serializable {

    private String name;
    private String hobby;

    ... (省略)

    // 以下を追加
    public String getUserInfoSentence() {
        return "名前は" + this.name + "です。趣味は" + this.hobby + "です。";
    }
}

【V】JSP(result.jsp)の修正

上のJavaBeansで追加したメソッドを呼び出します。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%@ page import="com.test.UserInfo" %>
<%
    // UserInfoクラス(JavaBeans)
    UserInfo userInfo = (UserInfo) request.getAttribute("user_info");
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<%
    // 文字コードをセット(日本語の文字化けを避ける)
    request.setCharacterEncoding("UTF-8");
    response.setContentType("text/html; charset=UTF-8");
%>

<p>
<% if (userInfo != null) { %>
<%= userInfo.getUserInfoSentence() %>
<% } %>
</p>

</body>
</html>

【C】サーブレット(MainServlet.java

サーブレットについては、修正は不要です。

課題

上記のサンプルについて、入力項目を「名前」「趣味」から、「特技」を加えたものに修正してください。

JavaBeans【 Model(MVCのM)】

(ブログ記事の一覧は「こちら」)

サーブレットJSPで学んだサンプル(入力画面、結果画面の作成)では、「名前」「趣味」を入力して送信するプログラムを作成しました。

また、フォワードでは、プログラムの処理はサーブレットに記述して、その結果のHTMLの出力はJSPに記述する、という切り分けが有効であることを確認しました。

では、サンプルでの項目(「名前」「趣味」)についても切り分けてみることを考えてみます。つまり、データを処理する部分に注目して切り分ける方法について確認していきましょう。

JavaBeans

再利用が可能なルールで定義されたJavaのクラスのことをJavaBeansといいます。

JavaBeansの仕様

  • java.io.Serializableインタフェースを実装する
  • クラスをpublicで指定する
  • フィールド(メンバ変数)はprivateで指定する
  • publicで引数なしのコンストラクタを定義する
  • プロパティにアクセスするためのgetter / setterメソッドを用意する

サンプル

ここでは、JavaBeansの具体的な作成方法と例について確認します。
実際の使用方法は、次の「リクエストスコープ(サーブレット、JSP、JavaBeansの連携)」で説明します。

クラスファイルの作成

「プロジェクト名」を右クリックして、「新規」-「クラス」を選択します。

「名前」を入力して、「完了」ボタンをクリックします。 (「UserInfo」としています)

クラスファイルの編集

フィールドに「name(名前)」「hobby(趣味)」を追加して、それぞれのgetter / setterメソッドを追加します。

package com.test;

import java.io.Serializable;

public class UserInfo implements Serializable {

    private String name;
    private String hobby;

    public UserInfo() {}

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getHobby() {
        return this.hobby;
    }
 
    public void setHobby(String hobby) {
        this.hobby = hobby;
    }

}


これでデータ項目(「名前」「趣味」)だけを切り分けたクラスが作成できました。

フォワード(サーブレット、JSPの連携)

(ブログ記事の一覧は「こちら」)

これまで、サーブレットJSPについて学んできました。
プログラムの処理を書くにはサーブレットが向いていて、HTMLの出力を書くにはJSPが向いているといえます。

では、プログラムの処理をサーブレットに記述して、その結果のHTMLの出力をJSPに記述する、ということができれば、お互いのメリットを活かした実装ができるといえます。

それを実現する方法として「フォワード」と呼ばれるものがあります。フォワードを使用すると、処理を他のサーブレットJSPに転送することができます。

フォワードのサンプル

ここでは、サーブレットからJSPに転送するフォワードの例を確認していきましょう。

「HTMLファイル」 ⇒ (「サーブレットクラス」 → 「JSPファイル」)

サンプルでの具体的なファイル名は以下です。

「form.html」 ⇒ ( [MainServlet.java] → [result.jsp] )

サーブレットクラス(MainServlet.java

doPostメソッドに以下のコードを記述します。

@WebServlet("/MainServlet")
public class MainServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    (省略)

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        RequestDispatcher dispatcher = request.getRequestDispatcher("/result.jsp");
        dispatcher.forward(request, response);
    }

}

RequestDispatcher クラスを使用することで、指定したオブジェクトにフォワードさせることができます。コードの例では「result.jsp」にフォワードさせています。

HTMLファイル(form.html)

サーブレットの説明で作成したサンプルと同じものです。(サーブレットクラス「MainServlet」に対してPOSTリクエストで送信しています。)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

    <form action="/ServletAppTest/MainServlet" method="post">
        名前:<input type="text" name="name">
        趣味:<input type="text" name="hobby">
        <input type="submit" value="送信する">
    </form>

</body>
</html>

JSPファイル(result.jsp

JSPの説明で作成したサンプルと同じものです。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<%
    //文字コードをセット(日本語の文字化けを避ける)
    request.setCharacterEncoding("UTF-8");
    response.setContentType("text/html; charset=UTF-8");
%>

<p>
<%= request.getParameter("name") %>
</p>
<p>
<%= request.getParameter("hobby") %>
</p>

</body>
</html>

実行

「form.html」を右クリックして、「実行」-「サーバーで実行」を選択します。

テキストボックスに入力して送信ボタンを押すと、入力したテキストが出力される画面に移動することを確認してください。

課題

上記のサンプルについて、入力項目を「名前」「趣味」から、「特技」を加えたものに修正してください。

JSP(JavaServer Pages)【 View(MVCのV)】

(ブログ記事の一覧は「こちら」)

サーブレットは、サーバー上で動的なWebページを作成するJavaの技術についてでした。サーバー側の処理を書くのに向いていましたが、HTMLに出力するには(コード量が増えることから)あまり適していませんでした。
そこでJSP(JavaServer Pages)と呼ばれる技術が用意されています。JSPもサーバー上で動的なWebページを作成する技術ですが、JSPファイルはHTMLがベースになっています。

ここでは、JSPの基本と、サーブレットで作成したサンプル(入力画面、結果画面の作成)をJSPで作成する方法を確認していきましょう。

JSPファイルの作成、実行

JSPファイルの作成

「プロジェクト名」を右クリックして、「新規」-「JSPファイル」を選択します。

f:id:MJeeeey:20201125225008j:plain:w540

ファイル名を入力して、「完了」ボタンをクリックします。 (「result.jsp」としています)

f:id:MJeeeey:20201128231556j:plain:w480

以下のようになることを確認してください。

f:id:MJeeeey:20201128231739j:plain

JSPファイルの実行

JSPファイル(赤枠の部分)を右クリックして、「実行」-「サーバーで実行」を選択します。

f:id:MJeeeey:20201128232109j:plain:w540

簡単な修正

以下のように、bodyタグ内にJSPタグのプログラムを記述します。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

Served at: 
<%= request.getContextPath() %>

</body>
</html>

実行すると、サーブレットの初期状態と同じ結果が出力されます。

JSPの基本構文

JSPの基本構文について確認していきます。(タグの書式に注目)

pageディレクティブ(<%@ ... %>)

JSPの設定を行います。以下は、初期状態の先頭行に記述されています。

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
式(<%= ... %>)

変数や、メソッドの戻り値など、出力することができます。

<%= request.getContextPath() %>
スクリプトレット(<% ... %>)

Javaのコードを書くことができます。

<% 
int sum = 0;
for (int i = 0; i < 10; i++) {
    sum += i;
}
%>

サンプル(フォームからの呼び出し)

(「サーブレット」のときと同じ動作のものを作成します)

テキストボックスと送信ボタンを含む、入力フォームのHTMLを用意して、送信されたテキストデータをJSPファイルで受信して表示するWebアプリのサンプルを作成してみましょう。

HTMLファイルの作成

「プロジェクト名」を右クリックして、「新規」-「HTMLファイル」を選択します。

f:id:MJeeeey:20201123232008j:plain:w540

ダイアログが表示されたら、「form.html」として作成します。

以下のように、bodyタグ内にフォームを記述します。
(formタグのaction属性の値を、ご自身の環境に合わせるようにしてください。)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

    <form action="/ServletAppTest/result.jsp" method="post">
        名前:<input type="text" name="name">
        趣味:<input type="text" name="hobby">
        <input type="submit" value="送信する">
    </form>

</body>
</html>

JSPファイルの作成

「result.jsp」を作成して、以下のように追記します。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
    //文字コードをセット(日本語の文字化けを避ける)
    request.setCharacterEncoding("UTF-8");
    response.setContentType("text/html; charset=UTF-8");
%>

<p>
<%= request.getParameter("name") %>
</p>
<p>
<%= request.getParameter("hobby") %>
</p>

</body>
</html>

実行

「form.html」を右クリックして、「実行」-「サーバーで実行」を選択します。

テキストボックスに入力して送信ボタンを押すと、入力したテキストが出力される画面に移動することを確認してください。

課題

上記のサンプルについて、入力項目を「名前」「趣味」から、「特技」を加えたものに修正してください。

サーブレット【 Controller(MVCのC)】

(ブログ記事の一覧は「こちら」)

サーブレットは、サーバー上で動的なWebページを作成するJavaの技術です。

サーブレットを使用したWebアプリの基本的な作成方法について説明していきます。

自動生成されるサーブレットファイル

JavaによるWebアプリの開発環境の構築」で作成したプロジェクトに含まれているサーブレットファイル「MainServlet.java」は、以下のJavaプログラムになっています。

f:id:MJeeeey:20201119213703j:plain

生成されるメソッドは以下の通りです。

  • コンストラク
  • doGet
  • doPost

「doGet」はGETリクエストでの通信、「doPost」はPOSTリクエストでの通信で使用されます。

GET: URLに付加してリクエストを行う
POST: Bodyに含めてリクエストを行う

簡単な修正

「doGet」内のプログラムを以下のように修正してみましょう。(出力結果は同じです)

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        out.println("Served at: ");
        out.println(request.getContextPath());
    }

今後は、PrintWriterクラスのオブジェクトを明示した、上記の方法で説明します。


Webアプリなので、HTMLタグも追加して記述する方が良いです。以下のようになります。(出力結果は同じです)

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head>");
        out.println("<meta charset=\"UTF-8\">");
        out.println("<title>test</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("Served at: ");
        out.println(request.getContextPath());
        out.println("</body>");
        out.println("</html>");
    }

上記からわかるように、サーブレットでHTMLタグを追加すると記述量が多くなってしまいます。次に説明する「JSP」の方がすっきりとHTMLを記述することができます。

サンプル(入力画面、結果画面の作成)

テキストボックスと送信ボタンを含む「入力画面」のHTMLを用意して、送信されたテキストデータをサーブレットで受信して「結果画面」に表示するWebアプリのサンプルを作成してみましょう。

構成は以下のようになります。
入力画面「HTMLファイル」 ⇒ 結果画面「サーブレット

入力画面(HTMLファイル)の作成

「プロジェクト名」を右クリックして、「新規」-「HTMLファイル」を選択します。

f:id:MJeeeey:20201123232008j:plain:w540

ダイアログが表示されたら、「form.html」として作成します。以下のように追加されることを確認してください。

f:id:MJeeeey:20201123232420j:plain:w480

入力項目は「名前」と「趣味」を用意します。
以下のように、bodyタグ内にフォームを記述します。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

    <form action="/ServletAppTest/MainServlet" method="post">
        名前:<input type="text" name="name">
        趣味:<input type="text" name="hobby">
        <input type="submit" value="送信する">
    </form>

</body>
</html>

送信先はformタグのaction属性に「/{プロジェクトファイル名}/{サーブレットの@WebServlet}」とセットします。(上の例では「/ServletAppTest/MainServlet」)
また、method属性を「POST」として、POSTリクエストで送信しています。


結果画面の作成(サーブレットの編集)

「doPost」メソッドを以下のように記述します。

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 文字コードをセット(日本語の文字化けを避ける)
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=UTF-8");

        // パラメータを取得
        String strName = request.getParameter("name");
        String strHobby = request.getParameter("hobby");

        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head>");
        out.println("<meta charset=\"UTF-8\">");
        out.println("<title>ユーザー情報</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<p>" + strName + "</p>");
        out.println("<p>" + strHobby + "</p>");
        out.println("</body>");
        out.println("</html>");
    }

実行

「form.html」(HTMLファイル名)を右クリックして、「実行」-「サーバーで実行」を選択します。

f:id:MJeeeey:20201123233202j:plain:w540

テキストボックスに入力して送信ボタンを押すと、入力したテキストが出力される画面に移動することを確認してください。

課題

上記のサンプルについて、入力項目を「名前」「趣味」から、「特技」を加えたものに修正してください。