ウエブアプリケーション 2015
第12回 Servlet
2015/12/10
海谷 治彦
1
http://www0.info.kanagawa-u.ac.jp/~kaiya/wa/
dotcampus ショートコード 179067
目次
• 演習解答例
• 期末試験について
• JSP/Servletの対比 (ほぼ復習)
• Servletの記述
• Servletのコンパイル
• Servletの配置
• redirect と forward
• ウエブアプリに利用可能な通常Javaクラス
• 本日の演習
2
期末試験について
• やります.
• シラバスにそうかいちゃったんで.
• 本,紙類は持ち込み可能とします.
• PC, スマフォ,携帯電話,タブレット等はダメよ.
• 基本,知識を問う問題ではなく,理由を問う問題中
心になると思います.
3
セットアップしてほしい構成
4
Lenovo : クライアント Firefox等 : ウエブブラウザ CentOS 6.5 : サーバー apache 2.2 : ウエブサーバー PHP 5.3 : モジュール Tomcat6 : アプリケーションサーバー MySQL 5.1 : データベース HTTP JVM : モジュール復習
++
JSP and Servlet
• 共通点
• どちらもサーバーで実行される. • すなわち,クライアントに届いた時にはただのHTML • コレがJavaScriptとの大きな違い• JSP
• HTMLにJavaっぽいものを埋め込む. • 雰囲気はJavaScriptに似てるが,上記のようにサーバー内で実行される. • phpはコレに考え方が似ている. • オリジナルのクラス等を作成する場合は,Servletとの連携が必要.• Servlet
• Javaそのもの. • mainメソッドは書かないのが普通. • そもそも スーパークラスがフレームワーク的にできている. • Javaのprint機能でHTMLの行を表示しないと,クライアント側で解釈不能 になる. • どちらかといえば,JSPのサブルーチン的に使われるのが普通.5
復習
サンプル
6
<HTML> <HEAD> <TITLE> JSP loop </TITLE> </HEAD> <BODY> <ul> <% int i;for(i=0; i<10; i++){ %>
<li> number <%= i*3 %> <% } %> </ul> </BODY> </HTML> // Simple Servlet import java.io.*; import javax.servlet.*; import javax.servlet.http.*;
public class Another extends HttpServlet {
public void doGet(
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<head>"); out.println("<title>Another!</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>Another!</h1>"); out.println("</body>"); out.println("</html>"); } }
復習
Tomcat6の基本事項を
復習
(JSP)
• HTMLにJavaの断片を埋め込む感じ.
• 以下のフォルダの下の個々のフォルダがアプリケー
ションである,例えば,
/var/lib/tomcat6/webapps/アプリ/
• JSPファイルはアプリのフォルダに直接置けばよい.
• JSPに関しては特にコンパイル等はいらない.
• DBにアクセスするためには,
/var/lib/tomcat6/webapps/アプリ/META-INF/context.html
に設定を書かないといけない.
7
Tomcat6の基本事項 (Servlet)
• Javaプログラムそのもの. • 以下のフォルダの下の個々のフォルダがアプリケーションである. /var/lib/tomcat6/webapps/ • ServletはJavaそのものなので事前にコンパイルする必要がある. • クラスファイルは /var/lib/tomcat6/webapps/アプリ/WEB-INF/classes/ の下におく.パッケージに分けているなら,フォルダ階層も必要. • クラスファイルとページの対応表を以下のファイルにかかないといけない. /var/lib/tomcat6/webapps/アプリ/WEB-INF/web.xml • DBにアクセスするためには, /var/lib/tomcat6/webapps/アプリ/META-INF/context.html に設定を書かないといけない.8
Servletソースの構造
• アップしたサンプルを見ながら聞いてください.例
えば,WhereApi.java 等.
• javax.servlet.http.HttServletクラスのサブクラスとし
て構成する.
• 大抵,doGet もしくは doPostメソッドをオーバーライ
ドする.
• 独自にhtmlページを構成する場合,
• respnseの型を設定
• printlnで一行一行htmlを書く
という面倒をしないといけない.
• JSPにあった暗黙変数の取り方は次頁へ.
9
JSPの暗黙オブジェクト
• 以下のようなオブジェクト(インスタンス)が宣言なしで使える.
• 主にウエブとの情報共有に用いられる.
• 宣言部 (<%! %>)では使えないことを注意.
10
オブジェクト名 概要 application コンテナに関する情報等 config 設定ファイルへのアクセス exception ページ内で発生した例外情報を管理 out クライアントにデータを出力する手段.out.printlnはよくつかう. page JSPページそのもの. pageContext ページ単位で利用可能な情報. request httpリクエストへのアクセスを提供 response httpレスポンスを修正する場合に利用 session セッションの情報,次回以降.復習
Servletでの対応
• JSPでの暗黙オブジェクトは以下のようにSevletで
は取得できる.
11
JSP Servlet
application javax.servlet.ServletContext a=this.getServletContext(); config javax.servlet.ServletConfig c=this.getServletConfig(); exception 各メソッドによる APIを見ること
out java.io.PrintWriter out=response.getWriter();
page なし
pageContext なし
request doPost等の引数
response doPost等の引数
主なメソッド
• 基本的にはHTTPのメソッドの種類に対応.よく使
うものは,
• doGet ブラウザからGETメソッドでサーバーに接続
する際に呼び出される.
• doPost こちらはPOSTメソッドの場合.
• 引数の構成はほぼ同じ
• 軽くAPIを見直してみてください.
12
Javaのコンパイル (一般論,復習)
• Eclipse等を使っていると忘れ気味だが,javac というコマン
ドラインのコンパイラが存在する.
• servletでは非標準APIを使う必要があるので,自身でこの
準備を行う必要がある.
• 具体的には,本授業の環境では,以下のように,-cp オ
プションを付ける必要がある.
• 面倒だと思う人は shell scriptなり,alias なりにしてみること.
• サンプル中には,compile.sh というスクリプトが入っている. • CLASSPATH という環境変数を設定してもよい.13
javac -classpath /usr/share/tomcat6/lib/../servlet.jar なんとか.java
Javaのパッケージ (一般論)
• Javaでは同じ名前のクラスが衝突しないように,パッ
ケージという概念がある.
• これによって,例えば,
• org.acm.kaiya.Jindai クラスと,
• jp.ac.nii.kaiya.Jindai クラスは,
クラス名は同じでも,別のクラスとして扱える.
• パッケージ名は,上記のように,.で区切った英数文字
(
-は使えない
)の列で構成される.
• 上記のように,慣例として,ドメイン名を逆したした名前
をパッケージ名とすることが多い.
• kaiya.acm.org ならば org.acm.kaiya
• コンパイルは問題無いが,実行時点の配置には考慮
が必要.(後述)
14
サンプル
15
// ごく普通のクラス // パッケージの定義,本来は,org.acm.kaiya 等, // ドメイン逆の名前にすべきだが, //面倒だから単に一語のパッケージ名とした package kaiya;public class ImportTest2{ public int val=314;
// public ImportTest2(){} public String say(){
return "I was imported!"; }
public static String sayStatic(){
return "I am static and packaged. 2nd."; }
Servletのコンパイル
• javax.servletクラスは標準的なAPIではない.
• よって,前述の-cpオプション等でライブラリが入っ
ているフォルダもしくはjarファイルを指定しないと
いけない.
• 本演習の標準的な設定では,
/usr/share/tomcat6/lib/../servlet.jar
にSerlet関連のクラスが入っている.
• よって,以下のようにコンパイル
16
javac -classpath /usr/share/tomcat6/lib/../servlet.jar なんとか.java
Tomcat6の基本事項 (Servlet)
• Javaプログラムそのもの. • 以下のフォルダの下の個々のフォルダがアプリケーションである. /var/lib/tomcat6/webapps/ • ServletはJavaそのものなので事前にコンパイルする必要がある. • クラスファイルは /var/lib/tomcat6/webapps/アプリ/WEB-INF/classes/ の下におく.パッケージに分けているなら,フォルダ階層も必要. • クラスファイルとページの対応表を以下のファイルにかかないといけない. /var/lib/tomcat6/webapps/アプリ/WEB-INF/web.xml • DBにアクセスするためには, /var/lib/tomcat6/webapps/アプリ/META-INF/context.html に設定を書かないといけない.17
再掲載
Servletの配置
• コンパイルしたプログラムや設定ファイルを実行のために
サーバーの特定のフォルダにおくことを,
配置
もしくは
ディ
プロイ(deploy)
と呼ぶ.
• 単純なアプリと違い,ウエブアプリを含めた複雑なアプリは,
この,配置だけでわりと一苦労である.
• Servletやウエブアプリで使うJavaのclassファイルは,
/var/lib/tomcat6/webapps/アプリ/WEB-INF/classes/
• におけばよい.
• ただし,パッケージにした場合,パッケージに応じたフォル
ダ階層を構成しないといけない(次頁).
• アプリとclassファイルの対応表,web.xml については後述.
18
パッケージ対応の例
19
// サンプル acm.zip にはいってます package org.acm.kaiya; import java.io.*; import javax.servlet.*; import javax.servlet.http.*;public class Acmextends HttpServlet { public void doGet(
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException{ response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<html>"); // 中略 out.println("</html>"); } } 左記のようなパッケージに, クラスAcmを定義した場合, 以下のように, わりと深いフォルダ階層を 掘らないといけない. ・・・・・メンドい
web.xml
• クラスファイルをブラウザからアクセスするための対応表で
ある.
• 特に慣例は無い様だが,Strutsというフレームワークを使う
場合は .do とするようだ.
• 以下,例,青字は解説
20
<servlet> <servlet-name>id20141210</servlet-name> 名前は一意ならなんでもOK <servlet-class>org.acm.kaiya.Acm</servlet-class> パッケージを含めたクラス名 </servlet> <servlet-mapping> <servlet-name>id20141210</servlet-name> servletで定義した名前 <url-pattern>/welcome</url-pattern> URLの最後にコレがつく </servlet-mapping>Servletの実行
• アプリのURLに web.xml で定義したurl-patternを
くっつければ実行できる.
• 普通のHTMLやJSPが実際のフォルダ階層に合致
しているのに対して,servletはそうでは無いので注
意が必要.
Form等からの値処理
• From等から入力されたkey-valueをrequestから取り出
す典型的なインタラクション処理もJSP同様に記述可能.
• 例: svltform.zip を参照
22
import java.io.*; import javax.servlet.*; import javax.servlet.http.*;public class Register extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException{
String email = req.getParameter("email"); // 以下,略
} }
ServletからのDBアクセス
• JSPでのコードがほぼそのまま利用できる.
• サンプルソース Sql1.java
• アプリ /tomcat/tomcat01/sql1
• 別途,本日のサンプル中に dbclass.zip というのも
ある.
• これは,DB操作部分を独立したJavaクラスとして
ある.(後述)
23
redirect と forward
• ユーザーからの入力をトリガーとして,他のページ
に遷移することはformで実現できる.
• ユーザーからのトリガー無く他のページに処理を
移すための技術としてredirectとforwardがある.
• 例えば,Servletで何か計算をして,その結果をJSPで表
示したい場合等はとても便利.
• Servletで表示するのは面倒だし.• 無論,Servlet → Servlet, JSP → JSP もOK
• キーとなるポイントはページ間でどのようにデータ
を共有するかである.
• redirect セッション等を利用するしかない.
• forward リクエストの情報がそのまま引き継がれる.
の違いがある.
24
redirectのサンプル
• redict.zipを参照
25
// 略 Redirect.java
public class Redirect extends HttpServlet { public void doPost(HttpServletRequest req,
HttpServletResponse res)
throws IOException, ServletException{ String email = req.getParameter("email"); if(email==null) email="unknown"; HttpSession s=req.getSession(); s.setAttribute("email", email); res.sendRedirect("/tomcat/redirect/show.jsp"); } } <body> <%-- show.jsp --%> <% String email= (String)session.getAttribute("email"); %> <div> <table border> <tr> <th>email address</th><tr> <tr> <td> <%=email%> </td></tr> </table> </div> <a href="form.html">[again]</a> </body>
forwardのサンプル
• forward.zipを参照.
26
public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException{
// 折角なので,Servletで追加情報をつけた req.setAttribute("add", "ServletObjectID="+this); // 最初のJSPで入力されたemailについては何も対処してない 単に転送される this.getServletContext().getRequestDispatcher("/show.jsp").forward(req, res); } <% // 最初のJSPで入力された情報
String email = request.getParameter("email");
if(email==null) email="unknown"; // Servletで意図的に付け加えた情報
String add = (String)request.getAttribute("add");
%>
<div>
<table border>
<tr> <th>email address</th> <th>Object ID</th> <tr> <tr> <td><%=email%></td> <td><%=add%></td> </tr> </table>
</div> Forward.java から抜粋