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 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 */
$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 の使用を宣言
クラスのBeanをcopyrightという名前で使用することを宣言しています。
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.*" %>
<%= "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 はなくもて利用できる
<% out.print(nowTime); %>
<%@ page import="java.util.*"%>
Directive tag は <!-- --> とは無関係.
<%! %> 宣言
この宣言文を含むJSPページに固有の変数とメソッドを定義するのに使用します
User の入力をうける.
<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 . そして 実行.
[ 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
<jsp:include page="/home/username/jsp/include.jsp" flush="true" />
<jsp:include page="http://localhost/jsp/include.jsp" flush="true" />
OK
<jsp:include page="../include.jsp" flush="true" />
<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 をつかった 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() に渡せばすべて取得できる