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>
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テーブルここで、下に出ている「年」と「月」を変更し、「送信」ボタンを押すと、画面が切り替わり、指定した年・月のカレンダーに切り替わります。(図7-2.)
図7-2.LEFT OUTER JOINによる結合GET送信であることから、URLの末尾に、「?year=2016&month=10…」といった具合にyeare(年)およびmonth(月)のパラメータが送付されていることが分かります。
アクセスの仕組み
ではこのプログラムの仕組みを見てみましょう。まず、大まかなアクセスの仕組みを図にすると以下の通りになります。(図7-3.)
図7-3.RIGHT OUTER JOINによる結合初回のアクセスでは、現在の「年」と「月」をもとにして、カレンダーを作成し、「年」・「月」およびカレンダーのデータとして、Calender.jspに送信し、それが画面に出力されます。
次に、「送信」ボタンが押されると、画面上で選択された「年」と「月」が送られて、それを元にカレンダーが表示されます。
パラメータの取得
では、CalenderAccess.javaの中の、doGet()メソッドで、初回アクセスと、「送信」ボタンが押されたときのアクセスは、どのようにして区別しているのでしょうか。
結論から先に言うと、prepDataメソッドの中の「GET送信時のパラメータの有無」で区別しています。送信時にパラメータが設定されていると、requestのgetParamaterメソッドでデータを取得できます。したがって、その値が取れないということは、初回アクセスということになります。(図7-4.)
図7-4.LEFT OUTER JOINの内容アトリビュート
次は、得られた「年」および「月」をもとに、カレンダーを作ります。カレンダーはテーブル(table)を用いて作ります。このサンプルでは、65行目から105行目までの間でその処理を行っています。
これらが完成すると、次は「年」「月」「カレンダー」のデータをCalender.jspに送信する必要があります。そのために必要になるのが、requestオブジェクトのsetAttribute()および、getAttribute()メソッドです。
これらは、requestオブジェクトの属性として、送信するデータを設定・取得ができるというものです。使い方は以下のようになります。
requestオブジェクトの属性の値の設定設定する値は、オブジェクトになります。そのため、設定側と取得側できちんと型を合わせておく必要があるので、注意が必要です。なお、CalenderAccess.javaの54行目から66行の間でこれら一連の処理が行われています。
フォワード
属性の設定が終わったら、次は属性の値を持ったままでページ遷移を行う必要があります。そのためには、フォワードと呼ばれる処理を行う必要があります。このサンプルでは、CalenderAccess.javaの34行目から36行の間で行われています。
フォワードの処理// フォワードによるページ遷移
dispatcher.forward(request, response);
getRequestDispatcherメソッドは、引数にURLを指定し、そのURLに対するRequestDispatcherオブジェクトを生成します。URLはコンテキストルートから/(スラッシュ)を含めて絶対パスで指定するか、呼び出すプログラムからの相対パスで指定します。
生成されたオブジェクトの、forwardメソッドを利用すれば、指定されたページに遷移できます。フォワードには引数として、request並びにresponseを必要とします。これにより、requestの属性が、遷移先のページで取得できます。(図7-5.)
図7-5.RIGHT OUTER JOINの内容以上がこのプログラムの大まかな仕組みです。カレンダーを生成する仕組みなど、細かい点に関する説明は省略します。興味がある方は是非とも解析してみてください。
以上で基本編の開設は終わりです。しかし、より実用的なWebアプリを作成するためには、これだけの知識では不十分です。更に学習を進めるためには、応用編をご覧ください。