JSP/Servlet

JSPとサーブレットの結合

最後にWebアプリケーションの開発においてJSPとサーブレットで機能を分け、より効率的に記述する方法について学習しましょう。基本的にJSPで記述してもサーブレットで記述してもどちらでも同じ処理が行えます。では、この二つの違いはなんでしょう?

一般的に、JSPは表示に関する記述をサーブレットはファイルやデータベースの処理といったロジックを記述する事に用いられます。ここでは、サンプルを通して、その使い分けについて説明していくことにしましょう。

掲示板の作成

JSPとServletの連携としての掲示板

では、実際にJSPとサーブレットの連携の例として、カレンダーのプログラムを紹介します。起動時には、現在の年・月のカレンダーが表示されますが、任意の年・月を選んで、「送信」ボタンを押すと、指定した年・月のカレンダーが得られるものです。

Calender.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.*" %>
<!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>
<style type="text/css">
<!--
	*{padding:5px; margin:0px;}
	body{text-align:center;}
	table{width:800px; background:white; border:2px black solid; border-collapse:collapse;}
	th{border:1px black solid; background:#CCFFFF;}
	td{border:1px black solid; text-align:right; padding:5px 20px 5px 20px;}
	br{line-height:1em;}
-->
</style>
</head>
<body>
<b><%= request.getAttribute("year") %>年<%=request.getAttribute("month") %>月のカレンダー</b>
<br/>
<br/>
<%= request.getAttribute("calender") %>
<br/>
<b>カレンダーの変更</b>
<br/>
<div style="text-align:center;">
<form action="CalenderAccess" method="get">
<select id="year" name="year">
<%
	int year = Integer.parseInt(request.getAttribute("year").toString());
	int month = Integer.parseInt(request.getAttribute("month").toString());
	for(int i = year-10; i <= year+10; i++){
%>
<option value="<%=i %>"
<%
		if(i == year){
%>
selected
<%
		}
%>
><%=i %>年</option>
<%
	}
%>
</select>
 
<select id="moneth" name="month">
<%
	for(int i = 1; i <= 12; i++){
%>
<option value="<%=i %>"
<%
		if(i == month){
%>
selected
<%
		}
%>
><%=i %>月</option>
<%
	}
%>
</select>
<br/>
<br/>
<input type="submit" id="ok" name="ok" value="送信"/>
</form>
</div>

</body>
</html>
CalenderAccess.java
package day7;

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 java.util.*;

/**
 * Servlet implementation class CalenderAccess
 */
@WebServlet("/day7/CalenderAccess")
public class CalenderAccess extends HttpServlet {
	private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public CalenderAccess() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		prepData(request);
		RequestDispatcher dispatcher = request.getRequestDispatcher("Calender.jsp");
		//	フォワードによるページ遷移
        dispatcher.forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
	}
	//	送信用のデータの作成
	private void prepData(HttpServletRequest request){
		// 変数初期化
		int startday;
		int lastday;
		//	カレンダーの取得
		Calendar cal = Calendar.getInstance();
		//	年が設定されていれば、その値を取得。そうでなければ、今年の年号を入れる
		if(request.getParameter("year")==null){
			request.setAttribute("year", cal.get(Calendar.YEAR));	//	現在の年

		}else{
			request.setAttribute("year", request.getParameter("year"));	//	現在の年
		}
		if(request.getParameter("month")==null){
			request.setAttribute("month", cal.get(Calendar.MONTH)+1);	//	現在の月
		}else{
			request.setAttribute("month", request.getParameter("month"));	//	与えらられた月
		}
		int year = Integer.parseInt(request.getAttribute("year").toString());
		int month = Integer.parseInt(request.getAttribute("month").toString());
		// 月初めの曜日(日-> 1)
		cal.set(year, month - 1, 1);
		startday = cal.get(Calendar.DAY_OF_WEEK);
		// 月末の日付
		cal.add(Calendar.MONTH, 1);
		cal.add(Calendar.DATE, -1);
		lastday = cal.get(Calendar.DATE);
		//	カレンダーのデータを作成する
		int date = 1;
		int maxday = 6 * 7;
		StringBuilder sb = new StringBuilder();
		sb.append("<table>");
		sb.append("<tr>");
		sb.append("<th style=¥"color:red;¥">日</th>");
		sb.append("<th>月</th><th>火</th><th>水</th><th>木</th><th>金</th>");
		sb.append("<th style=¥"color:blue;¥">土</th>");
		sb.append("</tr>");
		sb.append("<tr>");
		for (int num = 1; num <= maxday; num++) {
			if(num < startday || num > lastday + startday - 1){
				sb.append("<td></td>");
			}else{
				sb.append("<td>"+date+"</td>");
				date++;
			}
			if(num % 7 == 0){
				sb.append("</tr>");
				if(num > startday + lastday - 1){
					break;
				}
				if(date < lastday){
					sb.append("<tr>");
				}else{
					//	最後だったら、ループから抜ける
					break;
				}
			}
		}
		sb.append("</table>");
		//	パラメータを設定
		request.setAttribute("calender", sb);
		return;
	}

}

実行は、JSPであるCalender.jspではなく、サーブレットであるCalenderAccess.javaにしてください。

そのため、URLは、http://localhost:8080/jsp/day7/CalenderAccessとなります。結果、以下のようなカレンダーが出力されます。(図7-1.)

図7-1.purchase_historyテーブル
purchase_historyテーブル

ここで、下に出ている「年」と「月」を変更し、「送信」ボタンを押すと、画面が切り替わり、指定した年・月のカレンダーに切り替わります。(図7-2.)

図7-2.LEFT OUTER JOINによる結合
LEFT OUTER JOINによる結合

GET送信であることから、URLの末尾に、「?year=2016&month=10…」といった具合にyeare(年)およびmonth(月)のパラメータが送付されていることが分かります。

アクセスの仕組み

ではこのプログラムの仕組みを見てみましょう。まず、大まかなアクセスの仕組みを図にすると以下の通りになります。(図7-3.)

図7-3.RIGHT OUTER JOINによる結合
RIGHT OUTER JOINによる結合

初回のアクセスでは、現在の「年」と「月」をもとにして、カレンダーを作成し、「年」・「月」およびカレンダーのデータとして、Calender.jspに送信し、それが画面に出力されます。

次に、「送信」ボタンが押されると、画面上で選択された「年」と「月」が送られて、それを元にカレンダーが表示されます。

パラメータの取得

では、CalenderAccess.javaの中の、doGet()メソッドで、初回アクセスと、「送信」ボタンが押されたときのアクセスは、どのようにして区別しているのでしょうか。

結論から先に言うと、prepDataメソッドの中の「GET送信時のパラメータの有無」で区別しています。送信時にパラメータが設定されていると、requestのgetParamaterメソッドでデータを取得できます。したがって、その値が取れないということは、初回アクセスということになります。(図7-4.)

図7-4.LEFT OUTER JOINの内容
LEFT OUTER JOINの内容

アトリビュート

次は、得られた「年」および「月」をもとに、カレンダーを作ります。カレンダーはテーブル(table)を用いて作ります。このサンプルでは、65行目から105行目までの間でその処理を行っています。

これらが完成すると、次は「年」「月」「カレンダー」のデータをCalender.jspに送信する必要があります。そのために必要になるのが、requestオブジェクトのsetAttribute()および、getAttribute()メソッドです。

これらは、requestオブジェクトの属性として、送信するデータを設定・取得ができるというものです。使い方は以下のようになります。

requestオブジェクトの属性の値の設定
request.setAttribute("属性名",値);
requestオブジェクトの属性の値の取得
request.getAttribute("属性名");

設定する値は、オブジェクトになります。そのため、設定側と取得側できちんと型を合わせておく必要があるので、注意が必要です。なお、CalenderAccess.javaの54行目から66行の間でこれら一連の処理が行われています。

フォワード

属性の設定が終わったら、次は属性の値を持ったままでページ遷移を行う必要があります。そのためには、フォワードと呼ばれる処理を行う必要があります。このサンプルでは、CalenderAccess.javaの34行目から36行の間で行われています。

フォワードの処理
RequestDispatcher dispatcher = request.getRequestDispatcher("Calender.jsp");
// フォワードによるページ遷移
dispatcher.forward(request, response);

getRequestDispatcherメソッドは、引数にURLを指定し、そのURLに対するRequestDispatcherオブジェクトを生成します。URLはコンテキストルートから/(スラッシュ)を含めて絶対パスで指定するか、呼び出すプログラムからの相対パスで指定します。

生成されたオブジェクトの、forwardメソッドを利用すれば、指定されたページに遷移できます。フォワードには引数として、request並びにresponseを必要とします。これにより、requestの属性が、遷移先のページで取得できます。(図7-5.)

図7-5.RIGHT OUTER JOINの内容
RIGHT OUTER JOINの内容

以上がこのプログラムの大まかな仕組みです。カレンダーを生成する仕組みなど、細かい点に関する説明は省略します。興味がある方は是非とも解析してみてください。

以上で基本編の開設は終わりです。しかし、より実用的なWebアプリを作成するためには、これだけの知識では不十分です。更に学習を進めるためには、応用編をご覧ください。