この講義でこれまで見てきたように、ServletとJSPはそれぞれ同じような処理ができます。では、この2つはどのように使い分ければよいのでしょうか。
ServletにしてもJSPにしても、HTMLとプログラムが混在していると、ソースファイルの見通しが悪く保守が大変になります。現在のWebアプリケーション開発では、HTMLの出力部分とプログラムとを分離するのが良いとされています。
JSPは、HTMLにJavaプログラムを埋め込んだようなスタイルです。スクリプトレットは書きにくく、アプリケーションのロジックがわかりにくくなるという欠点があります。また、Webページのデザイナが、スクリプトレットを書くのは大変です。JSPを使うときには、スクリプトレットをJavaBeansとタグライブラリに置き換えて、JSPはHTMLの出力に専念させるのが良いでしょう。
そして、ServletはJavaプログラムなので、HTMLの出力をさせずに、ロジックの処理に専念させるのが良いでしょう。Servletでの処理結果を、JSPで表示することができます。Servletでのプログラミングは、本質的には、HttpServletRequestとHttpServletResponseに働きかけるというものです。Servletは、RequestをResponseに変換するコンポーネントであると考えられます。
ソフトウェア開発には、「Model-View-Controller (MVC)」と呼ばれている方法論があります。この方法論では、アプリケーションを構成するコンポーネントが、「モデル(Model)」・「ビュー(View)」・「コントローラ(Controller)」と名づけられた、3つの部分に分けられています(図10.1[MVCモデル2])。
最近のJ2EEとその関連技術では、モデルにJavaBeansを使い、ビューにJSPを使い、コントローラにServletを使う開発手法が採用されています。このJ2EEの手法は、「MVCモデル2」と呼ばれています。
では、この「モデル・ビュー・コントローラ」について見てみましょう。
「モデル」は、アプリケーションのデータと、データの処理をするプログラムをまとめた部分です。この「データの処理をするプログラム」のことを「ビジネスロジック」と言います。
JavaBeans (あるいはそのコレクション)がモデルとして利用されます。
「ビュー」は、「モデル」の表示を担当する部分です。J2EEでは、JSPがよく利用されます。
「コントローラ」は、「モデル」と「ビュー」を制御する部分です。Servletが担当します。
MVCモデル2を用いたWebアプリケーションの処理の流れは、次のようになります。
まず、ServletがHTTPから要求を受け取ります。そして、データベースへのアクセスなどの必要な処理をします。
処理した結果はJavaBeansに格納します。ServletはJavaBeans (または、Beansをまとめたコレクション)をJSPに渡します。
JSPはタグライブラリを駆使して処理結果を出力します。このとき、JavaBeansのプロパティを出力することになります。
ここでは、サンプルを通して、MVCモデル2によるアプリケーションの基本的な構成について見てみましょう。このサンプルは、本の検索アプリケーションです。
このアプリケーションの処理は、まずユーザがWebブラウザに検索したい本の情報を入力し、その情報をもとにServletが処理をして、結果をJSPが表示する、という流れになります。それぞれの部分の役割は、次のようになります。
Servletがコントローラとなり、JSPがビューを担当します。また、モデルであるJavaBeansは、アプリケーションで処理するデータを保持して、ServletからJSPに渡されます。
今回のサンプルプログラムでは、コントローラがBookSearchServletであり、ビューがlist.jspで、モデルがBookData (と、それを複数集めたList)になります。
まず、モデルとなるJavaBeansを見てみましょう。BookDataは、1冊の本のデータを表すBeanです。java.util.Listで複数のBookDataをまとめます。
package jp.ac.wakhok.library;
import java.io.Serializable;
public class BookData implements Serializable {
private String ndc = "";
private String tyosya_hyouji = "";
private String id = "";
private String title = "";
private String author = "";
private String publisher = "";
public String getNdc() {
return ndc;
}
public void setNdc(String ndc) {
this.ndc = ndc;
}
public String getTyosya_hyouji() {
return tyosya_hyouji;
}
public void setTyosya_hyouji(String tyosya_hyouji) {
this.tyosya_hyouji = tyosya_hyouji;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getPublisher() {
return publisher;
}
public void setPublisher(String publisher) {
this.publisher = publisher;
}
}
次に、コントローラであるServletのソースを見てみましょう。
import java.util.List;
import java.util.ArrayList;
import java.io.*;
import java.sql.*;
import javax.sql.*;
import javax.servlet.*;
import javax.servlet.http.*;
import jp.ac.wakhok.library.*;
public class BookSearchServlet extends HttpServlet {
private String jspFile = "/list.jsp";
private ServletContext context;
public void init() throws ServletException {
context = getServletContext();
}
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
doIt(request, response);
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
doIt(request, response);
}
private void doIt(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("Shift_JIS");
String ndc = request.getParameter("ndc");
String tyosya_hyouji = request.getParameter("tyosya_hyouji");
String id = request.getParameter("id");
String title = request.getParameter("title");
String author = request.getParameter("author");
String publisher = request.getParameter("publisher");
List list =
search(ndc, tyosya_hyouji, id, title, author, publisher);
HttpSession session = request.getSession();
session.setAttribute("bookList", list);
context.getRequestDispatcher(jspFile)
.forward(request, response);
}
private List search(String ndc, String tyosya_hyouji,
String id, String title,
String author, String publisher) {
List list = new ArrayList();
try {
Class.forName("org.hsqldb.jdbcDriver");
String url = "jdbc:hsqldb:hsql://localhost";
Connection con = DriverManager.getConnection(url, "sa", "");
String selectStatement =
"select * " +
"from books where ndc like ? " +
"and tyosya_hyouji like ? " +
"and id like ? " +
"and title like ? " +
"and author like ? " +
"and publisher like ? ";
PreparedStatement prepStmt =
con.prepareStatement(selectStatement);
prepStmt.setString(1, appendPercent(ndc));
prepStmt.setString(2, appendPercent(tyosya_hyouji));
prepStmt.setString(3, appendPercent(id));
prepStmt.setString(4, appendPercent(title));
prepStmt.setString(5, appendPercent(author));
prepStmt.setString(6, appendPercent(publisher));
ResultSet rs = prepStmt.executeQuery();
while (rs.next()) {
BookData book = new BookData();
book.setNdc(rs.getString("ndc"));
book.setTyosya_hyouji(rs.getString("tyosya_hyouji"));
book.setId(rs.getString("id"));
book.setTitle(rs.getString("title"));
book.setAuthor(rs.getString("author"));
book.setPublisher(rs.getString("publisher"));
list.add(book);
}
rs.close();
prepStmt.close();
con.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
private String appendPercent(String from) {
StringBuffer to = new StringBuffer();
to.append("%");
to.append(from);
to.append("%");
return new String(to);
}
}
このServletでは、まずWebブラウザから入力されたデータを取り出し、JDBCを使って、そのデータを検索しています。1冊の本のデータはBookDataに格納されます。そして検索結果は、java.util.Listにまとめられています。
List list =
search(ndc, tyosya_hyouji, id, title, author, publisher);
次の部分で、HttpSession型のインスタンスsessionに、bookListという名前でBeanを登録します。
HttpSession session = request.getSession();
session.setAttribute("bookList", list);
Beanの内容の出力はlist.jspというJSPページに任せています。
context.getRequestDispatcher("/list.jsp");
.forward(request, response);
最後に、ビューであるJSPのソースを見てみましょう。
<%@ page contentType="text/html; charset=Shift_JIS" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>検索結果</title>
</head>
<body>
<h1>検索結果</h1>
<ul>
<c:forEach var="book" items="${sessionScope.bookList}" >
<li>
<c:out value="${book.title}" />
/
<c:out value="${book.author}" />
</li>
</c:forEach>
</ul>
</body>
</html>
このJSPでは、タグライブラリであるJSTLを使っています。まず、Listに含まれているBookDataをひとつずつ処理するためにc:forEachが使われています。また、BookDataのプロパティを出力するためにc:outが使われています。
まず、c:forEachについて見てみましょう。
<c:forEach var="book" items="${sessionScope.bookList}" >
.....
</c:forEach>
このタグのitems属性では、ServletでHttpSessionに登録された、bookListというコレクションを取り出しています。
このforEachというタグは、items属性で与えられたCollection, Iteratorなどに含まれているオブジェクトを繰り返し処理します。現在処理をしているオブジェクトは、bookという変数に入ります。この<c:forEach>タグでは、BookDataをひとつひとつ処理することになります。
BookDataのプロパティの出力には、c:outの中で式言語を使っています。
<c:out value="${book.title}" />
このサンプルアプリケーションを動かすには、Tomcatには次のようにファイルを配置します。
test --- input.html
|- list.jsp
|- WEB-INF/ ---- web.xml
|-- classes/
| |- BookSearchServlet.class
| |- jp/ac/wakhok/library/ --- BookData.class
|-- lib/
|- hsqldb.jar
|- jstl.jar
|- standard.jar