JSP (Java Server Pages) でWebサイトを作ってみる

Webサイトを作るところを初歩から始めてみようということで、JSPでWebサイトを作ってみました。

JSPはスクリプト風にJavaのコードを追加したWebページを作成するもので、Apache Tomcatなどのコンテナサービスに配置するとWebページを再現するJavaコードが自動的に作られてコンパイルされ、動的なWebサイトが作れるというものです。

とりあえず最初なので、データベースから値を取得して表示するだけのページを作ってみることにしました。

データとしては今季のサッカーJ1リーグの試合結果を使います。

まず、データベースを用意します。

ターミナルからMySQL上にstandingsデータベースを作成し、matchesテーブルを以下のように作成しました。

create database standings;
create table matches (
  match_no int auto_increment,

  section int not null,

  date date not null,

  home varchar(16) not null,

  away varchar(16) not null,

  goals_for int not null,

  goals_against int not null,

  primary key (match_no)

);

match_noはプライマリキーとしてとりあえず付けた番号、sectionは節、dateは試合開催日、homeはホームチーム名、awayはビジターチーム名、goals_forはホームチームの得点、goals_againstはビジターチームの得点のつもりです。

そして、ターミナルから以下のように試合結果を打ち込んでいきます。

insert into matches set
  date='2022-02-18',
  home='川崎F',

  away='FC東京',

  goals_for=1,

  goals_against=0;

テストということで、試合結果は第1節の9試合分を上のようにポチポチと手で打ち込みました。

さて、これを表示するWebページを作っていこうと思います。

WebコンテナはApache Tomcat 9を使います。最新のTomcat 10を使うのがよいのでしょうが、現時点ではEclipse用のtomcat toolsがTomcat 9までしか用意されていないので、Tomcat 9をインストールすることにしました。

今回はtomcat toolsは使用しないのですが…。

さて、TomcatでJSPによるWebアプリケーションを作成する場合、Tomcatのインストール先にあるwebappsディレクトリにWebアプリケーションディレクトリ (今回はstandingsという名前にしました) を作成し、そのディレクトリ内にWEB-INFディレクトリを作成します。

standingsディレクトリにあるHTMLファイルにはhttp://localhost:8080/standings/index.htmlのようにアクセスすることができます。

WEB-INFディレクトリにはWebアプリケーションが必要とするデータ類を保管します。今回はMySQLデータベースにアクセスするので、WEB-INFディレクトリにlibディレクトリ (アプリケーションの実行に必要なjarファイルを保存するディレクトリ) にmysql-connector-java-8.0.28.jarをコピーしました。

なお、jdbc関係のライブラリ (java.sqlパッケージ) はJavaランタイムのものが使用できるので、ここにコピーする必要はありません。

まず、index.htmlファイルを作ります。

<!DOCTYPE html>
<html>
  <head>

    <meta charset="UTF-8">

    <title>Standings List</title>

  </head>

  <body>

    <h1>戦績表</h1>

    <hr />

    <a href="matches.jsp">試合一覧</a>

  </body>

</html>

中身は見た通り試合一覧というリンクを表示するだけで、リンク先はmatches.jspというJSPファイルにしています。

次に試合一覧を表示するmatches.jspを作ります。

まず、試合結果をデータベースから取得して、一覧表示するプログラムを考えます。

import java.sql.*
import java.time.format.DateTimeFormatter


public class Standings {

  private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd");


  public static void main(String[] args) {

    Connection conn = null;

    PreparedStatement pstmt = null;


    try {

      Class.forName("com.mysql.cj.jdbc.Driver");

      conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/standings",

        "sampleUser", "SU_pass");

      pstmt = conn.prepareStatement("SELECT * FROM matches ORDER BY match_no");

      ResultSet rset = pstmt.executeQuery();

      while (rset.next()) {

        System.out.print(rset.getInt("section") + ", ");

        System.out.print(rset.getDate("date").toLocalDate().format(formatter) + ", ");

        System.out.print(rset.getString("home") + ", ");

        System.out.print(rset.getInt("goals_for") + " - " + rset.getInt("goals_against") + ", ");

        System.out.println(rset.getString("away"));

      }

    } catch (Exception ex) {

    } finally {

      try {

        if (pstmt != null)

          pstmt.close();

        if (conn != null)

          conn.close();

      } catch (SQLException se) {

      }

  }

}

CSV形式で結果を出力するプログラムを書くと上のような感じになるかと思います。

これを分割してHTMLファイル中にスクリプトのように書いたものがJSPファイルになります。

まず、先頭にディレクティブを記述します。ディレクティブはJSPコンテナ (ここではTomcat) にJSPファイルの処理に必要な指示を記述したものです。

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.sql.*" %>
<%@ page import="java.time.format.DateTimeFormatter" %>

先頭の<%@から%>まではおまじないで、とりあえずこのまま書けばいいと思っています。

次の2個の<%@から%>まではJavaのインポート文をそのまま書いています。

なお、<%@直後のpageはディレクティブの有効範囲がこのページであることを示しています。

次に宣言部を記述します。宣言部は<%!から%>までで、関数やセッションを超えて使用される変数、定数などを記述します。宣言部に記述された変数はセッションを超えて維持されますが、TomcatなどのWebコンテナが起動・停止すると初期化されてしまうので、永続的なデータの記録には使用できません。

宣言部は関数と定数の宣言に使うのが適当なのではないかと考えています。

<%!
  DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd");
%>

ここでは試合開催日の表示に使用するフォーマッタを宣言することにしました。

ここからJSPの本体の記述になります。

まず、動的なコンテンツが登場するまでの部分を記述します。

<!DOCTYPE html>
<html>
  <head>

    <meta charset="UTF-8">

    <title>Match Results</title>

  </head>

  <body>

    <h1>試合一覧</h1>

    <table border="1">

      <tbody>

        <tr style="text-align: center;">

          <th>節</th>

          <th>日付</th>

          <th>ホーム</th>

          <th>得点</th>

          <th>アウェイ</th>

        </tr>

試合一覧はHTMLテーブル形式で表示することにしたので、テーブルの見出し行だけを記述し、テーブルの本体はJavaコードで生成するようにします。

<%
  Connection conn = null;
  PreparedStatement pstmt = null;

  try {

    Class.forName("com.mysql.cj.jdbc.Driver");

    conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/standings",

      "sampleUser", "SU_pass");

    pstmt = conn.prepareStatement("SELECT * FROM matches ORDER BY match_no");

    ResultSet rset = pstmt.executeQuery();

    while (rset.next()) {

%>

<%から%>までがJavaコード片で、データベースに接続して試合結果を取得し、結果があるかの確認までここで行っています。

この後、取得したデータをHTMLテーブルに埋め込んでいくのですが、そこではHTMLとJavaコードが混在するので、try節の途中で、さらにwhileループの途中という気持ち悪いところで途切れています。

<tr>
  <td style="text-align; end;"><%=rset.getInt("section") %></td>
  <td><%=rset.getDate("date").toLocalDate().format(formatter) %></td>

  <td style="text-align: end;"><%=rset.getString("home") %></td>

  <td><%=rset.getInt("goals_for") + "&nbsp;-&nbsp;" + rset.getInt("goals_against") %>

  <td><%=rset.getString("away") %></td>

</tr>

1行分のテーブルデータを作成するコードになります。

スクリプトの外側に記述されるので、Javaコードとは関係なく出力されそうな気がして多少気持ち悪いのですが、この部分もwhileループの中で処理されるようです。

また、<%=から%>の部分はテキスト出力の簡易表現で、<%=から%>の中に記述された式の値が文字列としてHTMLコードに埋め込まれます。

あとは残りの部分、whileループとtry節を閉じて終了処理を行うところと、HTMLの後始末になります。

<%
  }
} catch (Exception ex) {

} finally {

  try {

    if (pstmt != null)

      pstmt.close();

    if (conn != null)

      conn.close();

  } catch (SQLException se) {

  }

}

%>

      </tbody>

    </table>

  </body>

</html>

例外処理のやり方をきちんと確認していないので、とりあえず例外は何もしていません。

さて、JSPファイルができたらTomcatを起動するとJSPファイルに対応したJavaソースコードとコンパイル済みコードがTomcatのディレクトリの下、workディレクトリ配下に作られます。

少し階層が深いので、ディレクトリ階層は省略しますが、Javaソースコードが見られるので、JSPファイルがどのようにJavaコードになるかがよくわかります。

ざっくりいうと、Javaコードがそのまま出力され、HTMLコードはJavaコード中の該当する位置に出力命令として出力されているという感じです。

次はデータベースへの入力をやろうと思っています。JSPで作るか、Servletにするかは少し試してみてから考えます。


0コメント

  • 1000 / 1000