はじめに
今回はJSPで使った主な機能をサーブレットで実装する方法について説明します。また、JSPとサーブレットの連携についても考えてみます。JSPとサーブレット間でのデータのやり取り、さらにはWebアプリケーションにBeanを保管し、jSP~サーブレット~Bean間での値の受け渡しについても触れておきましょう。
対象読者
- Javaの基本(文法全般および基本的なクラスライブラリの使い方程度)をマスターしている人。
- サーバサイド(JSP、サーブレット)について基礎から勉強したい人。
- Eclipse WTPを使った開発に興味がある人。
JSP~サーブレット~JSPの流れを考える
JSPとサーブレットの特徴を考えたとき、誰もが思うのは「クライアントへの表示関係をJSPで行い、サーバ側で必要な処理をサーブレットで実装しよう」ということでしょう。すなわち、「データを送信するJSP→処理用サーブレット→結果表示JSP」というように、JSPとサーブレットの間でやり取りしながら処理を行っていくというやり方です。このようにすることで、GUIと内部処理を分離できるはずです。
そのためには、「JSPからサーブレットへの送信」「サーブレットからJSPに情報を渡す」「サーブレットから必要に応じてJSPページにリダイレクトする」といった処理が必要となります。実際に簡単なサンプルを作成して、これらの機能の使い方について整理していくことにしましょう。
ここでは「index.jsp」→「MyServlet」→「page.jsp」という流れで処理を受け渡すことにしましょう。まずは、「index.jsp」からです。一応、jspにしてありますが、基本的にはただのHTMLです。
<%@ page language="java" contentType="text/html; charset=Shift_JIS" pageEncoding="Shift_JIS"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"> <title>JSP SAMPLE</title> </head> <body> ※送信フォーム:<br> <form method="post" action="./myserv"> <input type="text" name="text1"><br> <input type="submit"> </form> </body> </html>
ここでは、myservに向けてフォームをPOST送信しています。このmyservがMyServletになります。まぁ、これ自体は特に説明の要はないでしょう。続いて、結果を表示する「page.jsp」のソースコードです。
<%@ page language="java" contentType="text/html; charset=Shift_JIS" pageEncoding="Shift_JIS"%> <% request.setCharacterEncoding("Shift_JIS"); String msg = (String)request.getAttribute("msg"); %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"> <title>PAGE</title> </head> <body> ※送信されたメッセージ:<br> <%=msg %> </body> </html>
ここでは、request.getAttribute
を使って"msg"という名前の値を取り出しています。これをそのまま<%=msg %>
としてページに表示をしています。
サーブレットの作成
サーブレットは、「index.jsp」から送信されたフォームの内容を受け取り、それを必要な形に処理し、「page.jsp」にその値を渡してリダイレクトする、という処理を行います。では、ソースコードを挙げておきましょう。
package jp.codezine; import java.io.IOException; import javax.servlet.*; import javax.servlet.http.*; public class MyServlet extends HttpServlet implements Servlet { private static final long serialVersionUID = 1L; public MyServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("Shift_JIS"); response.setContentType("text/html;charset=Shift_JIS"); String str = request.getParameter("text1"); str = this.getSanitizedString(str); str = "[JSP-to-SERVLET:\"" + str + "\"]"; request.setAttribute("msg", str); // リダイレクト ServletContext context = this.getServletContext(); RequestDispatcher dispatcher = context.getRequestDispatcher("/page.jsp"); dispatcher.forward(request, response); } // サニタイズ処理 public String getSanitizedString(String s){ String str = s; str = str.replace("<","<"); str = str.replace(">",">"); str = str.replace("\"","""); str = str.replace(" "," "); return str; } }
ここでは、doGetで特に処理をしていません。直接アクセスしたとしても、空白のページが表示されるだけです。doPostで必要な処理を行っています。setCharacterEncoding
とsetContentType
で下準備をした後、「index.jsp」から送られてきた値を取り出します。
String str = request.getParameter("text1");
この点は、JSPとまったく同じことが分かりますね。jspの暗黙オブジェクトも実質的にはdoPost
の引数で渡されるHttpServletRequest
と同じわけですから。続いて、この値をリクエストのアトリビュートとして設定します。
request.setAttribute("msg", str);
これも、JSPとまったく同じです。これで、「page.jsp」側はrequest.getAttribute
で値を取り出せるようになるわけです。JSP/サーブレット間の値のやり取りは、JSPどうしの場合とほとんど変わらずに行えることが分かるでしょう。
では、作業完了後に「page.jsp」に移動するリダイレクト処理はどうすればよいのでしょうか。これは、少々面倒なことを行う必要があります。JSPでは、pageContext
という暗黙オブジェクトのforward
を使えばよかったのですが、このpageContext
に相当するものはサーブレットに用意されていません。
pageContext
暗黙オブジェクトの正体は、javax.servlet.jspパッケージに用意されている「PageContext
」というクラスのインスタンスです。これはJSP用に用意されているものであるため、JSP以外(サーブレット含む)では利用できないのです。そこで、サーブレットでのやり方を別途覚えておく必要があります。
ServletContext context = this.getServletContext();
まず、etServletContext
というメソッドを使い、ServletContext
というクラスのインスタンスを取得します。これはサーブレットが利用されているWebアプリケーションに関する情報を管理するもので、各Webアプリケーションごとに1つのインスタンスが割り当てられています。
JSPにも、これに相当する暗黙オブジェクトはあります(「application」というものです)。ここから、リダイレクトのためのオブジェクトを取得して作業を行います。
RequestDispatcher dispatcher
= context.getRequestDispatcher("/page.jsp");
RequestDispatcher
は、文字通りリクエストの処理を転送するために必要な処理を持つクラスのインスタンスです。getRequestDispatcher
により、必要なRequestDispatcher
を取得します。このとき、引数には転送先のファイルのURLを指定します。これで、指定したURLに転送するためのRequestDispatcher
が得られるわけです。
dispatcher.forward(request, response);
取得したRequestDispatcherのforward
を呼び出して転送を行います。引数には、HttpServletRequest
とHttpServletResponse
を渡します。通常は、doGet
/doPost
の引数として渡されたものをそのまま渡せばよいでしょう。
このforward
が実行された時点でサーバはリダイレクトを行い、「page.jsp」にページ遷移します。従って、forward
の後に処理は書かないよう注意が必要です。
リダイレクトを行うとき、もう1つ覚えておきたいことがあります。それは、「サーブレットに送られたリクエスト・レスポンスがそのままリダイレクト先へも渡される」という点です。すなわち、サーブレットが受け取ったのと同じものが転送先に渡されるのです。ということは、サーブレットに送信した情報は、そのまま転送先でも利用できるということになります。
ここではサーブレットで「index.jsp」から送信されたフォームの内容を受け取り、アトリビュートに設定して送りましたが、「index.jsp」から送られた情報を直接「page.jsp」で利用することもできるわけです。
<% request.setCharacterEncoding("Shift_JIS"); String msg = (String)request.getParameter("text1"); %>
例えば、「page.jsp」の最初の<% %>
タグをこのようにすれば、「index.jsp」から送られたフォームのtext1の値をそのまま「page.jsp」で取り出すことができます。もちろん、forward
する際にdoGet
/doPost
の引数として渡されたHttpServletRequest
とHttpServletResponse
をそのまま渡すからこれが可能になる、という点は忘れないでおきましょう。
では、「リクエスト情報は不要だ。単純に他のページにジャンプしたい」というような場合にはどうすればいいのでしょうか。これは、response
にある「sendRedirect
」というメソッドを用います。
response.sendRedirect("http://google.com/");
例えば、このようにすることでGoogleのサイトへジャンプさせることができます。非常に単純です。