JSP


POINT JSP が処理された結果は, HTML になる. ( RMB > ソースを表示 で対応 ) 使いどころ 顧客の情報を集めたい -> DB との連携
(.) サーバが実行できるプログラム (.) <%%> タグを用いることで、HTML の中にプログラムを埋め込むことができる (.) CGI とは異なり, ps 起動のオーバーヘッドがない -> 要は, Server( HTTPServer ) が他の ps を起動している. (.) Java の文法で記述でき、Java の利点を生かしたシステム構築ができる (.) ASP とは異なり, 各種環境で動作する.



環境設定





JSP Program の基本





Tutorial


// test.jsp <!-- 文字コードの指定とか --> <%@ page language="java" contentType="text/html; charset=Windows-31J" pageEncoding="Windows-31J" %> <%@ page language="java" contentType="text/html; charset=SJIS" pageEncoding="Windows-31J" %> out.println( request.getParameter( "param" ) ); // RET: B&B // Browser の URL 入力 [ http://localhost/app/test.jsp?param=B%26B ]
簡単な JSP Sample
<html> <head><title>Hello World!</title></head> <body> <h1>Hello World!</h1> <p> # Java の実行結果におきかわる <% // ここに Java Code をかく String hello = "Hello World!"; out.println(hello); %> </p> </body> </html>



暗黙オブジェクト


以下のオブジェクトは JSP 内で明示的に宣言しなくても利用できる。 request out


Javascript.との違い


POINT 違いをみるには, Browser でソースを表示をするとわかる jsp 側では HTML の記述のみが表示
// JavaScript Sample <html> <head><title>Hello World!</title></head> <body> <h1>Hello World!</h1> <p> <SCRIPT Language="JavaScript"> <!-- hello = "Hello World!"; document.write(hello); // --> </SCRIPT> </p> </body> </html>
[ Browser ] ---( リクエスト ) ---> [ Server ] [ Browser ] <---( JavaScript を含んだ HTML ) --- [ Server ] JavaScript に向いていること
Client で処理が完結すること. ( Game, Animation )
JSP に向いていること
(.) Server 側にある DB にアクセスすること (.) Server 側で処理をするので, Java の実行環境がなくても( 携帯 )実行が可能



Class.を利用する


DESC Java でつくった Class を JSP から使える 設定ファイル web.xml , context.xml の指定は不要 つくりかた
1. Java Class をつくる ( Java と同じ構文で OK ) 2. Compile して指定場所に配置する 3. JSP から class を import して利用する
JSP から利用できるクラスは次の条件が必要
// public 属性にする 1. VarMem 1. MethodMem // Public Class public class Test { public String func() { return "test class"; } }
ここに置く
/tom/app/WEB-INF/classes/testpkg/Test.java /tom/app/WEB-INF/classes/testpkg/Test.class /tom/app/testcalljava.jsp Package 名 : testpkg Class 名 : Test /TOMROOT/app/WEB-INF/classes/testpkg/Test.class $docBase/WEB-INF/classes/namePkg/original.class
* JSP からよびだします
// import 宣言をします <%@ page contentType="text/html; charset=sjis" import="testpkg.Test" %> <% Test t = new Test(); out.println( t.testfunc() ); %>
/* testcalljava.jsp */ # ( $docBase とは jsp のある dir と同階層にする必要がある ) # examples 相当 $TOMCAT/testdir/WEB-INF/classes/atmarkit/CopyrightHTML.class useclass.jsp POINT
WEB-INF/classes/ 以下にクラスを配置することで 新しく作成したクラスは Tomcat を再起動なしで読める もともと存在しなかった WEB-INF Directory を新しく 作成したときはパスが認識されないことがある そのときは Tomcat を再起動する WARNING class を再コンパイルしても反映されないかも 再起動すれば反映する



自作.Bean.の作成とその使用


DESC Bean とは JavaBeans の仕様にのとった命名, 設計規則 Java のクラス Rule を準備するだけで, 特定のクラスをBeanとして扱えます うまく使用することで、開発効率を向上させたり、 より信頼性の高いプログラミングができる Java 言語を用いて開発され 部品化されたプログラムを組みあわせてアプリケーションソフトを構築する手法 Java言語でBeanを作成するための技術仕様 プログラムを部品化すり 複数の開発者間での共有やコードの再利用が容易になり また出来合いのBeanやサードパーティから提供されるBean を組み合わせてアプリケーションソフトを開発すり 開発効率が飛躍的に向上します こんなルールあります
(.) プロパティの値を設定するメソッドとプロパティの値を取得するメソッドの名前に決まり事がある Accessor ( setとgetの後にプロパティ名を続けたメソッド )を準備するだけ
Bean を利用する場合は異なる tag ( BeanTag )を利用する. <jsp:useBean>  Bean の使用を宣言 # atmarkit.CopyrightHTMLBean クラスのBeanをcopyrightという名前で使用することを宣言しています。 # Program でいうと, atmarkit.CopyrightHTMLBean copyright = new atmarkit.CopyrightHTMLBean(); <jsp:useBean id="copyright" class="atmarkit.CopyrightHTMLBean" /> <jsp:setProperty>
 Bean のプロパティの値を設定する // copyrightという名前で宣言された Bean の year というプロパティに 2001 という値を設定 // 具体的には、copyright オブジェクトの setYear メソッドが実行されるので、 // 通常のプログラム: copyright.setYear("2001"); <jsp:setProperty name="copyright" property="year" value="2001" />
<jsp:getProperty>
 Bean のプロパティの値を取得 // copyright という名前で宣言された Bean の shortHTML というプロパティの値を取得 // copyright オブジェクトの getShortHTML メソッドが実行される // 通常のプログラムにおける、copyright.getShortHTML(); <jsp:getProperty name="copyright" property="shortHTML" /> 次のように考えれば OK. InstanceName + get + property <-> copyright.getShortHTML();
Bean のスコープ 今回は、1ページの表示で完結するJSPプログラムだったので 特に意識しませんでしたが Bean にはその有効範囲を指定できる scope 属性があります 種類は page : 現在の page DEF request session application <jsp:useBean> タグを次のように記述することでscopeを指定できます
<jsp:useBean id="id_name" class="class_name" scope="scope" /> Scope とは. 一度宣言された Bean にアクセスできる有効範囲を意味する.
scope 属性は EX scopeにsessionを指定した場合、同じセッションの範囲においては 違うページであっても同じidの値を指定することで、 同一のBeanにアクセスできる このようにすることで、セッション間の各ページで1つのBeanを共有できて 異なるページで同じ情報へアクセスできます   それぞれのscopeを指定したときのBeanの特徴は次のようになります scopeの指定によって、Beanをより有効に利用できるようになります。 scope アクセス可能な範囲 特徴 page 現在のページのみ デフォルトで使用されるスコープ もっとも有効な期間が短い request 現在のリクエストの範囲(インクルードされたページ、転送先のページを含む) レスポンスがユーザーに返されるまでの間だけ有効 EX: form で入力されたデータを保持させる session 現在のセッションの範囲 セッションと同じだけの有効期間を持つ EX: ログインしたユーザーの情報を保持させる application 現在のWebアプリケーション アプリケーションの有効期間と同じだけ永続的に使用できる EX: アクセスカウントなどアプリケーション間で共有する情報を保持させる


クッキー(cookie)を使う


DESC 前回は JSP でセッションを扱う方法を説明しました。 JSP のセッションでは セッションの識別 ID がクッキーとして自動的にブラウザ側に格納された POINT
Cookie とは Server から渡される設定 file ( NAME = VAL で構成される ) なぜ Cookie ができたか ? Server で 情報を提供できるが, User の端末に情報を記述できなかった. というわけで設定 file を渡そうということになった. ) [ Browser ] <-> [ Server ] <--- 書き込みができない.
JSP から Cookie の値を取得できる API がある Cookie をどうやってわたすか ? クッキーがサポートされるブラウザへ Server が小さなデータ(name=valueの組み合わせ:クッキー)を レスポンスのヘッダ部分に記述することで保存させる -> Response にも Header がある.( ということは相互に HTTP 通信. ) -> Browser が Cookie を利用できるようにしなければならない.
shell> curl -I http://www.google.co.jp | grep "Set-Cookie" // RET Set-Cookie: PREF=ID=1a1244830643bcfa:FF=0:TM=1320792924:LM=1320792924:S=1bEhuL4795SjGXSc; expires=Thu, 07-Nov-2013 22:55:24 GMT; path=/; domain=.google.com
Cookie を Browser から渡すには Browser は次回そのクッキーを発行したサイトに訪れた際に 持っているクッキーをサーバに提出 サーバはその内容を確認して, 前回自分がブラウザとやりとりしたデータを復元できる クライアント側がクッキーを受け取った後は、 ブラウザを閉じたり、コンピュータの電源を切ってもクッキーの情報を再度利用できる クッキーには有効期限を設定できるので 特定の期間を過ぎたクッキーを無効にできる
[ Browser ] --------> [ Server ] <-------- RESPONSE name=key1 name=key2 REQUEST name=key1 name=key2 [ Browser ] --------> [ Server ] <--------
Cookie が利用されるケース
会員サイトのユーザーIDを保存して、次回の訪問でユーザーを認識する 最後に訪れた日時を保存して、ユーザーの訪問頻度を計る ユーザーがカスタマイズしたサイトの情報(ユーザーの好み)を保存、次回もその設定を適用する 掲示板へ投稿するときに入力した名前とメールアドレスを保存しておき次回の入力の手間を省く
ページにアクセスすると, アクセスした時刻が Cookie として渡される
<%@ page language="java" contentType="text/html; charset=Windows-31J" pageEncoding="Windows-31J" %> <%@ page import="java.net.*, java.util.Date" %> <% // 現在の時刻を取得 Date now = new Date(); // クッキーに格納する文字列を作成(URLエンコードをする) String value = URLEncoder.encode(now.toString()); // 名前が"accesstime"、値が現在時刻であるクッキーを作成 Cookie c = new Cookie("accesstime",value); // 有効期間を1週間に設定 c.setMaxAge(7 * 24 * 60 * 60); // クッキーを追加 ( Http Response Header に追加される ) response.addCookie( c ); %>
POINT Cookie を破棄する方法はないため 期間 0 の Cookie を再発行して上書きする
<%@ include file="util.jsp" %> <%@ page language="java" contentType="text/html; charset=Windows-31J" pageEncoding="Windows-31J" %> <%@ page import="java.net.*, java.util.Date" %> <% // クッキーを使用する(クッキーを破棄する) // クッキーを作成 Cookie c = new Cookie("accesstime",""); // クッキーの有効期間を0秒に設定 c.setMaxAge(0); // クッキーを発行 response.addCookie(c); %> <pre> クッキーの内容を削除しました <a href="cok.jsp">クッキーの内容を確認する</a> </pre>



別サイトへの転送(Redirect)


DESC forward アクションを用いて、アクセス先を転送できる 特定の処理の前 または処理の途中で条件に応じたアクセス先の振り分けに使う POINT forwardアクションの用途は 特定のJSPのページから別のページへアクセス先を転送できる 転送先のページには別の JSP 以外にも, HTML, CGI のページも指定できる  代表的な例 UserAgent ( クライアントのブラウザの種類 )によるページの振り分け
// 転送処理をしないと if で処理わけをします // 煩雑になります // if ( PC からのアクセス ) { // PC HTML 出力 } else { // 携帯 HTML 出力 } // 転送処理ができれば, 別ファイルを用意すれば良い if ( PC からのアクセス ) { // PC Page へ転送. pc.jsp } else { // 携帯 Page へ転送. keitai.jsp }
page Directive ( page に対する指示 )
<%@ page contentType="text/html; charset=Shift_JIS" %> <% // request から Browser 情報を取得する String s = request.getHeader("user-agent"); // そして Browser によって別ページへ誘導する // forward アクションは、転送先を ( ローカル URL ) しか指定できない。 if ( s.indexOf("Opera") >= 0 ) { response.sendRedirect("http://yahoo.co.jp"); } else { response.sendRedirect("http://google.co.jp"); } %>
転送元と転送先での変数の共有 転送処理を行うと便利なケースのもう1つの例としてエラー処理があります EX ユーザーから情報を入力してもらうような場合 必ずしもその入力が完全であるとは限りません 入力内容をチェックし、正しければそのまま処理を続け、 問題がある場合にはエラーページへ転送することで効率の良いプログラムができます  このような場合 転送先のエラーページでは、エラーの内容を表示するのが一般的 このためには エラーの情報が転送元のページからエラーページへ渡される必要がある  forward アクションによる転送では転送元と転送先で、 session オブジェクト、 request オブジェクトが共有される 従って これらのオブジェクトに変数を格納することで情報を持ちまわることができる 転送元と転送先がどちらも同じアプリケーションに属する場合は、 application オブジェクトも共有されるため、 このオブジェクトに変数を格納することもできます


DB.へアクセスする


DESC 業務アプリケーションの世界では、 顧客情報や商品情報( Tool の統計情報. ) などを格納した DB とJSPの連携が必要になることが多い PostgreSQL のセットアップ JSP からデータベースへアクセスするためには、JDBC ドライバ が必要になります。 -> JavaDataBaseContainar テーブルの作成 PostgreSQLのセットアップが完了したら、 データを格納するためのテーブルを作成する テーブルの作成は、SQLの create table 文でする table をつくります
create table member ( member_id serial primary key not null, name varchar(32) not null, kana varchar(32) not null );
データベースアクセス用クラスの作成( java で実現する ) JDBC とは JDBC とは Java から DB にアクセスするための API


SYNTAX





Directive


SYNTAX <%@ %> DESC JSP Container に Page を処理する方法を指示
// import Directive <%@ page ... %> import "java.util.*"; <%@ page import="java.util.*" %> <%@ page import="java.lang.String" %> <%@ page import="java.io.*" %>
# 式 出力文を生成するのに使用 # Java Code を記述していることを忘れずに. <%= "foo" %> == <% out.println("foo"); %>
// 日本語をつかうときは, どの文字Code で出力するか指定します // Browser が文字化けしないならよいですが、 基本は指定します // JSP での出力結果を指定する // Default は ISO-8859-1 // JSP の処理結果であって 日本語<br> と記述した場合は Editor での文字 Code になる // 現時点では正しく動作しない. -> ないと正しく動作する. // EUC で出力 <%@ page contentType="text/html; charset=euc-jp" %> // SJIS で出力 <%@ page contentType="text/html; charset=Shift_JIS" %> // MIME Type を指定する // JSP で 特殊文字が文字化けする場合の対処方法 <%@ page contentType="text/html; charset=windows-31j" %>
String はなくもて利用できる # 適切な module を import しない ERROR になる. # スクリプトレット # 実際の処理の内容を指定のスクリプト言語( デフォルトでJava言語 )で記述 # [;] 必須. <% out.print(nowTime); %> # Package の使用を宣言 # Package を使用すると, namespace みたいなもの. # == import "java.util.*"; <%@ page import="java.util.*"%> # テキストの出力部分とロジック部分を混在させることも可能. # Demerit として, ロジックとHTML部分が混在し、メンテナンス性が低下 # -> String に出力結果を格納して, 最後に, <%= message %> とすべし. Directive tag は <!-- --> とは無関係. <%! %> 宣言 この宣言文を含むJSPページに固有の変数とメソッドを定義するのに使用します User の入力をうける. # これ経由でないと, 送信先で正しく開くことができない. # ie. 直接 /form.jsp を指定することはできない. <form action="form.jsp"> // 文字コードの変換を行う // EUC_JP として渡された Code // Java の内部 Code : Unicode name = new String( name.getBytes("8859_1"), "EUC_JP" ); birthday = new String(birthday.getBytes("8859_1"), "EUC_JP");


関数(Function)


SYNTAX <%! function(){} %> DESC JSP 内で利用する関数の定義
<%! // この Directive 内に関数を定義する // フォントカラーの指定を行ったHTML文を作成する public String getColoredHTML(String str, String color) { return "<font color=\"" + color + "\">" + str + "</font>"; } public int add( int x1, int x2 ) { return x1 + x2; } %> <% // 呼び出す out.print( add( 1, 2 ) ); %>



Include


SYNTAX // 静的 include <%@ include file="include.jsp"%> DESC * JSP でも Include できます 1. Code 量を減らすため. 2. Maintenance 効率をあげるため JSP でのプログラムの再利用方法
(.) インクルードディレクティブを使用した静的インクルード (.) インクルードアクションを使用した動的インクルード (.) オリジナルクラスの作成 (.) オリジナル Bean の作成
flush 属性 インクルードされるページを読み込む前にページの 出力バッファをフラッシュするかどうかを制御 現バージョンのJSPでは、必ず true に設定することになっているので、 インクルードアクションを使用する場合は、flush="true" を必ず記述するようにします # <jsp:include page="include.jsp" flush="true" /> インクルードディレクティブ jsp code を埋め込んでから, CMP . そして 実行. # Servlet の本質は Program を走らせて, Redirect することかも. [ sinc.jsp ] ---> ( include( 埋め込み ) ) ---> [ Compile ] ---> ( class file == Servlet )


IncludeAction


DESC 実行時に 組み込んで, 結果を埋め込む. 要は Action を組み込む どういうときに利用するか ? 1. 特定のフォーマットで Copyright を表示するプログラムを再利用する [ ainc.jsp ] ---> [ Compile ] ---> ( include( 埋め込み ) ) ( class file servlet ) 2 回 Compile されている. 1. include.jsp の Compile 結果を include ファイルパスの指定方法 Include する際の, path は JSP file からの相対. 絶対のどちらも可能. 同一の Context にある必要がある. BAD # context.xml での appBase が基準. <jsp:include page="/home/username/jsp/include.jsp" flush="true" /> # url の指定もできない. <jsp:include page="http://localhost/jsp/include.jsp" flush="true" /> # Relative OK # Relative <jsp:include page="../include.jsp" flush="true" /> # absolue <jsp:include page="../include.jsp" flush="true" /> Java コードの比較 JSPプログラムがサーバ側でJavaコードに翻訳されるときにはどのような 処理がなされるのでしょう。 本連載の第4回で“Hello, World!” の文字列を表示するJSPプログラムがJavaコードに翻訳された結果を見たように、 今回も5-1.jsp、5-2.jspがJavaコードに翻訳された結果を見てみましょう Javaコードは非常に長いので、実際にHTMLを出力する部分だけに注目してみます。


基本事項


# servlet を拡張したもの.
// Servlet をつかった hello world Sample // 見てのとおり メンドイです import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class HelloWorld 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><title>Hello World!</title></head>"); out.println("<body>"); out.println("<h1>Hello World!</h1>"); out.println("<p>"); out.println("Hello World!"); out.println("</p>"); out.println("</body>"); out.println("</html>"); } }



Server側のJSPの処理


1. Request をうける. ( Socket 通信かな ? ) 2. jsp を Compile する. foo.jsp ---> foo.java ---> CMP ( $tomcat/work/ に生成 ) 3. [ Browser ] ---> [ Server ] -(Compile)->
Context Path に jsp というパスを追加して、 その中に hello.jsp という名前でファイルを保存した場合 localhost_8080%2Fjsp/_0002fhello_0002ejsphello_jsp_0.java という名前で、このソースコードが存在する 自分の環境では, $tomcat/work/Catalina/localhost/my/org/apache/jsp/test_jsp.java -> Java Code が生成されている. 文字列も Java で記述するのか 変換される内容
HTML 文字 <-> out.write( "html" ); 1. ImplicitObject [ out ] JspWriter out = out = pageContext.getOut(); 1. JSP ページによって生成されるクラスは HttpJspBase クラスを継承する -> JSP は 動的に Servelet を生成する仕組み. ( ie. Servelet に集約する. ) HTML 文の出力は HttpJspBase::_jspService() メソッドでされている HTML 文の出力 JSP ページで記述した処理は try{ }catch(Exception ex){} 構文の中でする



HTTPHeaderの情報


DESC HTTPHeader とは Client と Server が Data をやりとりする際の付加される情報 荷物でいうところの 宛名、差出人 クライアントが利用しているブラウザソフトの名称やクッキー情報 ホスト名などが含まれる
// Client がだれか調べて, 携帯用のコンテンツに出力もできます String user_agent = request.getHeader("user-agent"); // 接続元の IP をえる out.print( request.getRemoteHost() ); // Header の項目をすべて取得する out.print( request.getHeaderNames() ); // getHeader() に渡せばすべて取得できる