2007年10月21日日曜日

eclipse

eclipse
インストール
任意のフォルダにインストールできます。

設定
立ち上げるとワークスペースを設定する必要があります。
任意のフォルダでOKです。

通常 Installed JREs で JRE を JDK に設定します。

日本語の言語パックもダウンロードできます。

2007年10月17日水曜日

Tomcat

Tomcat は代表的なサーブレットエンジンです。
JSP や サーブレットのコンテナとして広く利用されています。

Tomcat のインストール
http://tomcat.apache.org/ よりダウンロード

クラスパスの設定
(例)
CATALINA_HOME → C:\Program Files\Apache Software Foundation\Tomcat5.5
CLASSPATH → .;%CATALINA_HOME%\common\lib\servlet-api.jar;%CATALINA_HOME%\common\lib\jsp-api.jar

Tomcat は Web サーバーとしても機能します。
Web サーバーとして大きなシェアを持っている Apache と組み合わせてTomcat をサーブレットコンテナ専用で使うのが現在の主流です。

tomcatPlugin

eclipse に tomcatPlugin を組み合わせると Web アプリケーションの開発が便利になります。
eclipsetotale.com より
eclipse のバージョンに対応した tomcatPlugin をダウンロードして eclipse の plugins フォルダに配置します。
eclipse を再起動すると完了です。

JSP/サーブレットプログラムの配置

基本的には Tomcat の webapps 以下にプロジェクトのルートを配置。


Tomcat
+ webapps
    + プロジェクトルート
        + WEB-INF
            + classes
                + パッケージ
                    + クラスファイル
            + web.xml
            + lib
            + tlds
            + tags
        + HTML ファイルや JSP ファイルなど

プロジェクトルート
    アプリケーションのルート

WEB-INF
    クライアントからアクセスできない。

web.xml
    アプリケーション配備記述子
    サーブレットなどの情報を定義する

lib フォルダ
    jar ファイルなどを配置する

tlds
    TLD ファイルを配置する

tags
    タグファイルを配置する


WEB-INF 以外はクライアントからアクセスできる。


コンテキストファイル
コンテキストファイルは通常 Tomcat の conf\Catalina\localhost 以下に配置します。
コンテキストファイルの例
<Context path="/sample"
reloadable="true"
docBase="・・・・・・・"
workDir="・・・・・・・" />

web.xml

web.xml
配備記述子

サーブレット 2.4 から
<?xml version="1.0" encoding="UTF-8" ?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">

配備記述子で定義する主な要素

context-param
welcom-file-list
filter
listener
servlet
session-config
mime-mapping
error-page
taglib
security-constraint
login-config

サーブレット

サーブレット

サーブレットの基本インターフェース・クラスは javax.servlet パッケージにあります。
Javadoc 参照下さい。

ライフサイクル
init メソッド → service メソッド → doXxxx メソッド → destroy メソッド

service メソッド
サーブレットへのリクエストは service メソッドを経由する。
service は javax.servlet.Servlet インターフェースの定義されている。

doXxxx メソッド
javax.servlet.http.HttpServlet クラスに定義されています。
サーブレットでリクエストに対応する以下のメソッドをオーバーライドします。

doGet     HTTP GET リクエスト
doPost     HTTP POST リクエスト
doPut     HTTP PUT リクエスト
doHead     HTTP HEAD リクエスト
doDelete     HTTP DELETE リクエスト
doOptions     HTTP OPTIONS リクエスト
doTrace     HTTP TRACE リクエスト

GET と POST

HTTP GETハイパーリンクから呼び出せる
パラメーターはクエリ情報として追加できる

HTTP POST
パラメータはボディに格納して送信される。

HTML ファイルからサーブレットへ送信

ハイパーリンク(GET)
<a href="/SCWCD/Sample2?message=Hi everyone">Sample2</a>
Hi everyone がサーブレットで表示される

form で送信(GET)
<form action="/SCWCD/Sample2">
<input type="text" name="message" size="30" maxlength="15" /><br />
<input type="submit" value="送信"/>
</form>
form の method 属性のデフォルトは get
入力したテキストがサーブレットで表示される

次のサンプルはサーブレットで doGet メソッドを定義していませんが、
service メソッドをオーバーライドして doPost を定義しています。
全てのリクエストは service を通るのでそこから doPost が呼び出されるので正常に動く。

Sample2.java
import java.io.*;

import javax.servlet.ServletException;
import javax.servlet.*;
import javax.servlet.http.*;

public class Sample2 extends HttpServlet {
    @Override
    public void service(ServletRequest req, ServletResponse res) {
        try {
            doPost((HttpServletRequest)req, (HttpServletResponse)res);
        } catch (ServletException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void doPost(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {

        PrintWriter out = res.getWriter();
        out.println("<html><body>");
        out.println(req.getParameter("message"));
        out.println("</body></html>");
    }
}

HttpServlet

サーブレットは javax.servlet.http.HttpServlet クラスを継承して
リクエストに対応した doXxxx メソッドをオーバーライドします。

<サンプル>
プロジェクトの構成

SCWCD
    + WEB-INF
        + src
            + sample
        + classes
             + sample
        web.xml


Sample1.java
import java.io.*;

import javax.servlet.ServletException;
import javax.servlet.http.*;

@SuppressWarnings("serial")
public class Sample1 extends HttpServlet {
    public void doGet(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {

        PrintWriter out = res.getWriter();
        out.println("<html><body>");
        out.println("Hello");
        out.println("</body></html>");
    }
}

web.xml
<?xml version="1.0" encoding="UTF-8" ?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">
    <description>SCWCD</description>
    <display-name>SCWCD</display-name>
    <distributable />

    <servlet>
        <servlet-name>Sample1</servlet-name>
        <servlet-class>sample.Sample1</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>Sample1</servlet-name>
        <url-pattern>/Sample1</url-pattern>
    </servlet-mapping>
</web-app>

http://localhost:8080/SCWCD/Sample1 へアクセス

<出力結果>
Hello

servlet タグ :    サーブレットに関する情報を定義
servlet-name :    サーブレットの名前
servlet-class :    サーブレットの完全修飾名(パッケージ.サーブレット名)
jsp ファイルを指定する場合は jsp-file タグを使用する

servlet-mapping タグ :    サーブレットと URI パターンをマッピングする
url-pattern :    サーブレットの URI パターンを定義する
http://ドメイン/プロジェクトルート/サーブレット名
でアクセスできるようになる。

distributable タグ
アプリケーションが分散環境で配備可能であることを定義する。

HttpServletRequest

HttpServletRequest インターフェースは ServletRequest インターフェースを継承しています。

リクエスト文字エンコーディング
javax.servlet.ServletRequest のメソッド
void setCharacterEncoding(String env)

パラメータの取得
javax.servlet.ServletRequest のメソッド
String getParameter(String name)
Map getParameterMap()
Enumeration getParameterNames()
String[] getParameterValues(String name)

ヘッダーの取得
String getHeader(String name)
Enumeration getHeaderNames()
Enumeration getHeaders(String name)

リクエスト属性
javax.servlet.ServletRequest のメソッド
Object getAttribute(String name)
Enumeration getAttributeNames()
void setAttribute(String name, Object o)

HttpServletResponse

HttpServletResponse インターフェースは ServletResponse インターフェースを継承しています。

出力用 PrintWriter オブジェクトの取得
javax.servlet.ServletResponse のメソッド
PrintWriter getWriter()

文字エンコーディング
javax.servlet.ServletResponse のメソッド
void setCharacterEncoding(String charset)
    getWriter より前に呼び出す
    レスポンスがコミットされる前に呼び出す。
void setContentType(String type)
    getWriter より前に呼び出す
    レスポンスがコミットされる前に呼び出す。

リダイレクト
void sendRedirect(String location)
/ で始まるコンテナルートを基準とするパスを location に設定するか、相対パスを設定する。
(例)/SCWCD/Sample1
(例)Sample1
sendRedirect メソッドは一旦レスポンスをクライアントに返してから location へリダイレクトする。
リクエスト属性を利用できない。
他のドメインにリダイレクトするには http://..... というように location を設定する。

URL 書き換え
String encodeUrl(String url)
String encodeRedirectURL(String url)
Cookie をサポートしてないブラウザのセッションを構成するには URL 書き換えが使われる。
sendRedirect メソッドへ送られる URL はこのメソッドを利用する。

<サンプル>
import java.io.*;

import javax.servlet.ServletException;
import javax.servlet.http.*;

public class Sample3 extends HttpServlet {
    public void doPost(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {
        if (req.getParameter("message").equals("")) {
            res.sendRedirect("/SCWCD/index.html");
        } else {
            PrintWriter out = res.getWriter();
            out.println("<html><body>");
            out.println(req.getParameter("message"));
            out.println("</body></html>");
        }
    }
}

index.html
...
<form action="/SCWCD/Sample3" method="post">
<input type="text" name="message" size="30" maxlength="15" /><br />
<input type="submit" value="送信"/>
</form>
...

<出力結果>
入力した文字が出力される。文字を入力しないとリダイレクトされる。

sendError / setStatus

HTTP ステータスコード一覧



HttpServletResponse インターフェースにはステータスコードが定数として定義されています。
(例)
404 : SC_NOT_FOUND
500 : SC_INTERNAL_SERVER_ERROR

sendError / setStatus メソッドを使用する際は定数の利用が推奨されます。


sendError(int sc)
sc で指定されたステータスコードを使用してクライアントにエラーレスポンスを返す

sendError(int sc, String msg)
メッセージをふかしてエラーレスポンスを返す

setStatus(int sc)
レスポンスに sc で指定したステータスコードをセットする。
SC_OK (200) や SC_MOVED_TEMPORARILY (302)をセットする。
エラーレスポンスの場合は sendError メソッドを使用すべき。

2007年10月16日火曜日

エラーページの設定

エラーが起こった場合に移動するページを web.xml で定義することが出来ます。

404 エラーが起こった場合(存在しないページをリクエストした場合)に error.html へリダイレクトする。
<error-page>
<error-code>404</error-code>
<location>/error.html</location>
</error-page>

error-code のほかに exception-type が使える。
<exception-type>java.io.IOException</exception-type>

ServletContext

javax.servlet.ServletContext オブジェクトは Web アプリケーション単位で作成される。
distributable タグを web.xml に定義した分散環境 Web アプリケーションでは、
それぞれの JVM につき一つの ServletContext オブジェクトが作成される。
分散環境ではグローバル情報をコンテキストオブジェクトの属性などに頼るべきではなくデータベースなどに頼るべき。

ServletContext オブジェクトは ServletConfig オブジェクトから取得する。

ServletConfig#getServletContext メソッドで取得できる。
<サンプル>
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
String formatParam =
this.getServletConfig().getServletContext()
.getInitParameter("dateformat");
SimpleDateFormat fmt = new SimpleDateFormat(formatParam);
PrintWriter out = res.getWriter();
out.println("<html><body>");
out.println(fmt.format(new Date()));
out.println("</body></html>");

}

JSP では暗黙オブジェクト application として利用できる。
<サンプル>
application.getInitParameter("dateformat");

ServletContextListener 実装クラスでは ServletContextEvent から取得できる
<サンプル>
public void contextInitialized(ServletContextEvent sce) {
ServletContext context = sce.getServletContext();
}

コンテキスト初期化パラメータの設定
コンテキスト初期化パラメータを web.xml に定義することが出来ます。
context-param タグは複数定義できます。

<context-param>
<param-name>dateformat</param-name>
<param-value>yyyy/MM/dd</param-value>
</context-param>

HttpSession

セッション追跡
HTTP にはセッションはありませんので HTTP だけではセッションを追跡でいない。

セッション追跡のメカニズム

クッキーの使用

URL 書き換え
    クッキーを無効にしているブラウザへの対応。

SSL(Secure Sockets Layer) セッション

Java では javax.servlet.http.HttpSession インターフェースを使ってセッションを構成します。

セッションオブジェクトの取得
    HttpServletRequest#getSession
        現在のセッションを返す。
        現在のセッションがなければ新たに作成する。
    HttpServletRequest#getSession(boolean create)
        現在のセッションを返す。
        現在のセッションがなくて create が true なら新たに作成する。
        false を指定すると新たにセッションを作成しない。

セッションと属性
    セッションにオブジェクトをセット
    HttpSession#setAttribute(String name, Object value)
    セッションからオブジェクトを所得
    HttpSession#getAttribute(String name)
    HttpSession#getAttributeNames() は String オブジェクトの Enumeration を返す

セッションタイムアウト
    HttpSession#setMaxInactiveInterval(int interval)
    タイムアウト値を秒で設定する。
    -(ネガティブ)を設定するとタイムアウトしない。
又は
    web.xml の設定。タイムアウト値を分で設定。
   <session-config>
        <session-timeout>
            20
        </session-timeout>
    </session-config>
-(ネガティブ)または 0 を設定するとタイムアウトしない。

セッションオブジェクトの削除
HttpSession#invalidate メソッドを呼び出します。関連付けられているオブジェクトも削除します。

セッションが作成、破棄されたときに通知を受ける
    javax.servlet.http.HttpSessionListener

HttpSession オブジェクトはスレッドセーフではない。
    HttpSession オブジェクトはスレッドセーフではありません。
    
参照 スレッドの同期化

RequestDispatcher

javax.servlet.RequestDispathcer インターフェースは
リクエストを別のリソースに転送できる。

RequestDispatcher オブジェクトの取得
ServletRequest#getRequestDispatcher(String path)
相対パスが使用できるが、/ で始まる path はコンテキストルートが基準
(例)/Sample1
(例) Sample1

ServletContext#getRequestDispatcher(String path)
/ で始まるコンテキストルートを基準とした path を使用。
(例)/Sample1

void forward(ServletRequest request, ServletResponse response)
リクエストを別のリソースへ転送する

void include(ServletRequest request, ServletResponse response)
別のリソースをインクルードする

forward メソッドはサーバー側で直接転送するところが HttpServletResponse#sendRedirect メソッドと異なる。
転送された後の URL バーは依然サーブレットの URL パターンが表示されている。

Cookie

javax.servlet.http.Cookie

クライアントがサーバーにアクセス

サーバーがレスポンスにクッキーを添付

クライアントがクッキーを保存

サーバーへ再度アクセス

クッキー情報からクライアントを特定

レスポンスにクッキーを添付する
HttpServletResponse#addCookie メソッド

Cookie cok = new Cookie(name, value);
cok.setMaxAge(60*60*24*180);
res.addCookie(cok);

Cookie オブジェクトの取得
HttpServletRequest#getCookies メソッド
クライアントがこのリクエストで送った全てのクッキーが配列に格納される。

Cookie のコンストラクタに渡す value は java.net.URLEncoder#encode(String s, String enc) メソッドで
エンコードします。
リクエスト先では java.net.URLDecoder#decode(String s, String enc) メソッドでデコードします。

<サンプル>
    Cookie cok = new Cookie("message", 
    URLEncoder.encode("あいうえお", "UTF-8"));

<サンプル>
    String str = null;
    Cookie[] cok = request.getCookies();
    if (cok != null) {
        for (int i = 0; i < cok.length; i++) {
            if (cok[i].getName().equals("message")) {
                str = URLDecoder.decode(cok[i].getValue(), "UTF-8");
                break;
            }
        }
    }

フィルタ

javax.servlet.Filter はリクエストをインターセプトして ServletRequest や ServletResponse に処理を行うことが出来る。
主なフィルタの使い方
・アプリケーションへのリクエストをインターセプトして文字エンコーディングを設定する。
・フィルタでセキュリティを一括管理する

web.xml への定義

フィルタは配備記述子 web.xml へ定義します。

(例)
<filter>
    <filter-name>MyFilter</filter-name>
    <filter-class>filter.MyFilter</filter-class>
    <init-param>
            <param-name>EncodeName</param-name>
            <param-value>Shift_JIS</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>MyFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

filter-name : フィルタクラスの名前
fiter-class : フィルタクラスの完全修飾名
init-param : 初期化パラメータ。FilterConfig オブジェクトから取得できる。
url-pattern : フィルタを適用する URL を指定する。 *(ワイルドカード) が使用できる。
dispatcher : REQUEST,FORWARD,INCLUDE,ERROR を指定。デフォルトは REQUEST



Filter インターフェースのメソッド
public void init(FilterConfig config)

public void doFilter(ServletRequest request, 
    ServletResponse response, FilterChain chain)

public void destroy()

<サンプル>
public class MyFilter1 {
    private FilterConfig config = null;
    public void init(FilterConfig config) throws ServletException {
        this.config = config;
    }
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
        throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest)req;
        String url = request.getRequestURI();

        /* データベース等でなんらかのカウントアップ処理 */
    
        /* 次のフィルターへ */
        chain.doFilter(req,res);
    }
    public void destroy() {}
}

    <filter>
        <filter-name>MyFilter1</filter-name>
        <filter-class>filter.MyFilter1</filter-class>
    </filter>
    
    <filter-mapping>
        <filter-name>MyFilter1</filter-name>
        <url-pattern>/MyFilter1</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>INCLUDE</dispatcher>
        <dispatcher>ERROR</dispatcher>
    </filter-mapping>

リスナー

JSP/サーブレット Web アプリケーションにおいてはイベントを感知するリスナーを使用できます。
リスナーは web.xml に listener タグで定義します。
HttpSessionBindingListener と HttpSessionActivationListener インターフェースを実装するリスナークラスは定義しなくても良い。

リスナーの定義
web.xml
<listener>
    <listener-class>sample.MyListener1</listener-class>
</listener>

ServletContextListener

ServletContextListener は ServletContextEvent をハンドルします。
ServletContextEvent はコンテキストの生成、削除を通知します。
下記のメソッドがあります。
contextInitialized(ServletContextEvent sce)
contextDestroyed(ServletContextEvent sce)

アプリケーション共通の情報をセットする出来ます。
各ページで共通の情報を利用できます。
分散環境では各 JVM に1つずつ SevletContext がつくられるのでグローバル情報を ServletContext 属性などにセットすべきではないといわれます。

<サンプル>
web.xml
    <listener>
        <display-name>Context Listener</display-name>
        <listener-class>listener.ListenerSample1</listener-class>
    </listener>
_________

ListenerSample1.java
public class ListenerSample1 implements ServletContextListener {
    public void contextInitialized(ServletContextEvent sce) {
        ServletContext context = sce.getServletContext();
        context.setAttribute("message", "Hello");
    }
    public void contextDestroyed(ServletContextEvent sce) {
        ServletContext context = sce.getServletContext();
        context.removeAttribute("message");
    }
}
_________

sample.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<body>
<c:out value="${applicationScope.message}" />
</body>
</html>

<出力結果>http://localhost:8080/SCWCD/sample.jsp
Hello

HttpSessionListener

HttpSessionListener は HttpSessionEvent をハンドルします。
HttpSessionEvent はセッションの生成、削除を通知します。
メソッドは2つあります。

<サンプル>
public class MySessionListener2 implements HttpSessionListener {
    public void sessionCreated(HttpSessionEvent hse) {
        ServletContext sc =
        hse.getSession().getServletContext();
        sc.log("Session created");
    }

     public void sessionDestroyed(HttpSessionEvent hse) {
        ServletContext sc =
        hse.getSession().getServletContext();
        sc.log("Session destroyed");
    }
}

ログは通常 %CATALINA_HOME%\log\localhost.XXXX-XX-XX.log ファイルの記録されます。

参照 リスナーの配備

HttpSessionActivationListener

HttpSessionActivationListener インターフェースを実装するクラスのオブジェクトがセッション属性としてバインドされている場合、セッションの「退避」、「回復」が行われるとバインドされているオブジェクトに HttpSessionEvent が通知されます。

<メソッド>
void sessionDidActivate(HttpSessionEvent se)
void sessionWillPassivate(HttpSessionEvent se)

オブジェクトは直列化するため Serialazable インターフェースを実装するべきでしょう。
JVM 間でのセッションの移動の際、セッションの「退避」「回復」が発生します。

HttpSessionActivationListener を実装するリスナークラスは
web.xml に定義する必要はありません。

<サンプル>
public class MyActivationListener implements
        HttpSessionActivationListener, Serializable {
    public void sessionDidActivate(HttpSessionEvent arg0) {
        .....
    }
    public void sessionWillPassivate(HttpSessionEvent arg0) {
        .....
    }
}

HttpSessionAttributeListener

HttpSessionAttributeListener は
セッション属性の変化を通知します。
メソッドは3つあります。

<サンプル>
public class MySessionListener implements
        HttpSessionAttributeListener {
    public void attributeAdded(HttpSessionBindingEvent sbe) {
        ServletContext sc=
            sbe.getSession().getServletContext();
        ......
    }
public void attributeRemoved(HttpSessionBindingEvent sbe) {
        ServletContext sc=
            sbe.getSession().getServletContext();
        .....
    }
    public void attributeReplaced(HttpSessionBindingEvent sbe) {
        ServletContext sc=
            sbe.getSession().getServletContext();
        .....
    }
}

HttpSessionBindingListener

セッション属性にセットされいる HttpSessionBindingListener インターフェースを実装するオブジェクトは、HttpSessionBindingEvent を受け取る。
メソッドは3つあります。

<サンプル>
public class MySessionListener2 implements HttpSessionBindingListener {
    public void valueBound(HttpSessionBindingEvent arg0) {
        // .....
    }
    public void valueUnbound(HttpSessionBindingEvent arg0) {
        // .....
    }
}

セキュリティ

認証(Authentication)
自身の身元を明らかにしシステムにアクセスする権利があることを証明するメカニズム。
JSP/Servlet アプリケーションでは BASIC 認証FORM ベース認証、DIGEST 認証、CLIENT-CERT 認証が使われます。

許可(Authorization)
保護されたシステムへのアクセスをアクセスする人の権限によって管理するメカニズム。

データ完全性(Data Integrity)
データ完全性とはクライアントからサーバーまでの通信経路でデータが修正されていないことをあらわします。

______

セキュリティ制約条件
JSP / Servlet アプリケーションではリソースを保護するためにセキュリティ制約条件を設定します。

web.xml の設定
アプリケーション配備記述子に security-constraint タグでセキュリティ制約条件を設定します。

<security-constraint>
    <web-resource-collection>
        <web-resource-name>
        <url-pattern>
        <http-method>
    <auth-constraint>
    <user-data-constraint>

url-pattern で定義した URL がセキュリティ制約条件の対象となります。
http-method は GET や POST などを指定します。省略した場合はすべての方式に対応します。

セキュリティロール
アクセス権のあるユーザーを設定します。
    <auth-constraint>
        <role-name>

ユーザーデータの制約条件
データ転送に関する定義。
    <user-data-constraint>
        <transport-guarantee>

  1. NONE    転送中の保障必要なし

  2. INTEGRAL    転送中にデータが修正された場合それを識別できる方法で転送する。

  3. CONFIDENTIAL    転送中にデータを読み取ることができない方式

BASIC 認証

BASIC 認証はユーザー名とパスワードをクリアテキストでサーバーに送信する認証方式。

BASIC 認証を行うには配備記述子 web.xml に security-constraint タグと login-config タグを定義します。
url-pattern に指定した URL にアクセスするとログイン認証が求められます。
url-pattern には * (ワイルドカード)が使用できます。
role-name には %CATALINA_HOME%\conf\tomcat-users.xml に設定してあるユーザー名を指定します。
新たにユーザーを登録する場合は tomcat-users.xml を編集する必要があります。

web.xml
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>SercretResourse</web-resource-name>
            <url-pattern>/secret/*</url-pattern>
        </web-resource-collection>

        <auth-constraint>
            <role-name>guest</role-name>
        </auth-constraint>
    </security-constraint>

    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>Secure Realm</realm-name>
    </login-config>


/secret 以下のリソースにアクセスすると認証が開始されます。
認証はリソースにアクセスするたびに求められるのが基本ですが、ほとんどのブラウザでは約3分間は認証をパスしてページ移動が出来るようです。これは HttpSession の力を借りているのではなくブラウザ側の機能です。

FORM ベース認証

FORM ベース認証は機能的には BASIC 認証と同じです。
html ファイルなどでログインフォームをカスタマイズできます。
配備記述子 web.xml の login-config タグに下記のように追加設定します。

web.xml
<login-config>
    <auth-method>FORM</auth-method>
    <form-login-config>
        <form-login-page>/login.html</form-login-page>
        <form-error-page>/error.html</form-error-page>
    </form-login-config>
</login-config>

login.html はログインフォーム。
error.html はログインが出来なかったときに転送されるページです。エラーメッセージなどを表示します。

login.html には下記のようなフォームを配置します。
<form method="post" action="j_security_check">
Name : <input type="text" name="j_username"><br />
Password : <input type="password" name="j_password"><br />
<input type="submit" value="ログインする"></td>
</form>

j_security_check
j_username
j_password
は変更できません。

____

BASIC 認証、FORM ベース認証のほかにパスワードを暗号化して送信する DIGEST 認証、SSL を使った CLIENT-CERT 認証があります。

スレッドセーフ

<スレッドセーフ>

リクエストオブジェクト
リクエスト属性

ローカル変数

シングルスレッドモデルにおけるインスタンス変数


以外は synchronized などを使って適切なプログラムを書く。

JSP (Java Server Pages)

拡張子 は .jsp です。JSP ファイルは .java ファイルに変換されて .class ファイルにコンパイルされます。


JSP ファイルの構成

ディレクティブ(指令)
<%@ 指令 属性....%>

宣言部
<%! .... %>

スクリプトレット
<% 
    ...
%>


<%=....%>

コメント
<%-- .... --%>

アクションタグ

式言語(EL)

ディレクティブ(指令)

使用できるディレクティブ要素
@include (外部ファイルのインクルード)
@page (ページに関する情報を定義)
@taglib (タグライブラリに関する情報を定義)

タグファイルで使用できるディレクティブ
@attribute
@tag
@variable

(例)
<%@ page contentType="text/html;charset=Shift_JIS" %>

ディレクティブ要素をまとめて記述する場合
<%@ page contentType="text/html;charset=Shift_JIS"
 import="java.io.*" %>


@page
autoFLush (デフォルト true)
buffer (デフォルト 8kb)
contentType (ex. text/html;charset=Shift_JIS)
errorPage (エラー時に表示するページを指定)
extends (スーパークラスを定義)
import    (パッケージのインポートを宣言)
info (ページ情報)
isELIgnored (式言語を無視するかどうか。デフォルト false)
isErrorPage (このページがエラーページかどうか。デフォルト false)
isThreadSafe (スレッドセーフ。デフォルト true)
language (Java)
pageEncoding (文字エンコーディング)
session (セッションを有効にするかどうか。デフォルト true)

@include
<%@ include file="header.jsp" %>
インクルードされてからコンパイルされる

アクションタグ
<jsp:include page="header.jsp" flush="true" />
別々にファイルがコンパイルされた後にインクルードされる。

<サンプル>
a.jsp
<html>
<body>
<%! int x; %>
<%@include file="b.jsp" %>
</body>
</html>

b.jsp
<%=x %>

<出力結果>
0

(注)jsp:include を使うと b.jsp の x が宣言されていないのでコンパイルできない。

宣言部

宣言部で変数の宣言などを行います。
宣言部の変数は .java ファイルではインスタンス変数またはクラス変数となります。

<サンプル>
<html>
<body>
<%! int x; %>
<% x = 100; %>
The number is <%=x%>
</body>
</html>

<出力結果>
The number is 100

宣言部には jspInit と jspDestroy メソッドを記述できます。
jspInit と jspDestroy メソッドは .java ファイルにそのまま変換されます。

<サンプル>
<html>
<body>
<%! 
int x; 
public void jspInit() {
    x = 100;
}
%>
The number is <%=x%>
</body>
</html>

<出力結果>
The number is 100

スクリプトレット

スクリプトレットは Java のプログラムを記述できます。
.java ファイルへ変換されると _jspService メソッドに記述されます。

<% x = 100; %>

public void _jspService(HttpServletRequest request, HttpServletResponse response)
    throws java.io.IOException, ServletException {
...
x = 100;
...
}

<%= .... %>

(例)
<%=request.getParameter("name")%>

単純な式を出力できます。
変数の宣言はできません。
サーブレットの out.print にあたります。

アクションタグ useBean

JSP では標準で使えるアクションタグがあります。
アクションタグを使うことで Java のコードを減らして可読性、保守性を高める。

jsp:useBean
JSP ページ内で JavaBean クラスのインスタンスを取得または生成する。

<構文>
<jsp:useBean id="obj" class="sample.SCWCDBean" scope="request />
obj という SCWCD のオブジェクトを JSP ページで利用できる。

<useBean の属性>
id            オブジェクト名
class        オブジェクトのクラス
type        オブジェクトの型(インターフェース使用可)
beanName    オブジェクトの名前
scope        スコープ(デフォルト page)

<scope について>
page            現在のページ
request            現在のページ + include 先 + forward 先
session            セッション領域
application        アプリケーション全域

<ルール>
・class 属性を使うとスコープにそのクラスのオブジェクトが見つかるとそれを利用し、見つからないと新しく作成する。
・type 属性を使うとスコープにそのクラスのオブジェクト、またはそのインターフェース型にキャストできるオブジェクトを見つけてその「型」で利用します。
見つからない場合はインスタンスを作成せず、InstantiationException が投げられる。
・type 属性と class 属性を同時に使うと オブジェクトが type 属性の型にキャストされる。
・beanName 属性は type 属性との組み合わせのみで使用できる。
・beanName 属性はオブジェクトを作成する際に class 属性の代わりとなるので class 属性と組合すことはできない。

<サンプル>
index.jsp
<%@ page contentType="text/html;charset=Shift_JIS"%>
<jsp:useBean id="obj" class="beans.SCWCDBean" scope="session" />
<html>
<body>
<a href="/SCWCD/usebeanSample.jsp">usebeanSample.jsp</a><br />
</body>
</html>
________

usebeanSample.jsp
<%@ page contentType="text/html;charset=Shift_JIS"%>
<jsp:useBean id="obj" type="beans.SJCPCertified" scope="session" />
<html>
<body>
SCJP 獲得 : <%=obj.status()%>
</body>
</html>
________

SJCPCertified.java
package beans;
public interface SJCPCertified {
    boolean SJCPCERTIFIED = true;
    boolean status();
}
________

SCWCDBean.java
package beans;
import java.io.Serializable;
@SuppressWarnings("serial")
public class SCWCDBean implements Serializable, SJCPCertified {
    public SCWCDBean() {}
    private String name;
    private int score;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getScore() {
        return score;
    }
    public void setScore(int score) {
        this.score = score;
    }
    public boolean status() {
        return SJCPCERTIFIED;
    }
}

<出力結果>
SCJP 獲得 : true

usebeanSample.jsp で SJCPCertified 型のオブジェクトが獲得されている。

setProperty / getProperty

jsp:getProperty
jsp:setProperty


これらは useBean タグと組み合わせて使用します。
Bean のプロパティの取得と設定を行います。
Bean にある setter / getter メソッドが利用されます。
setter / getter メソッドは setプロパティ名 / getプロパティ名 にします。

<サンプル>
SCWCDBean.java
package beans;
import java.io.Serializable;
@SuppressWarnings("serial")
public class SCWCDBean implements Serializable, SJCPCertified {
    public SCWCDBean() {}
    private String name;
    private int score;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getScore() {
        return score;
    }
    public void setScore(int score) {
        this.score = score;
    }
    public boolean status() {
        return SJCPCERTIFIED;
    }
}

<JSP ページからプロパティをセット>
jsp:setProperty の属性
name : useBean で id で指定したオブジェクト名になります。
propetry : Bean のプロパティ名
param : リクエストパラメータの名前。* を使用すると property 名と同名のパラメータがセットされる。
value : プロパティに値をセットする

<JSP ページからプロパティを取得>
jsp:getProperty の属性
name : useBean で id で指定したオブジェクト名になります。
property : Bean のプロパティ名

<サンプル>
index.jsp
<a href="property.jsp?name=MrScwcd&score=62">property</a><br />

property.jsp
<jsp:useBean id="obj" class="beans.SCWCDBean">
<jsp:setProperty name="obj" property="*" />
</jsp:useBean>
<html>
<body>
Name : <jsp:getProperty name="obj" property="name" /><br />
Score : <jsp:getProperty name="obj" property="score" />
</body>
</html>

<出力結果>
Name : MrScwcd
Score : 62 

XML ベース JSP で使うアクションタグ

JSP ファイルは完全な XML 形式で記述できます。

XML 宣言
<?xml version="1.0" encoding="Shift_JIS"?>
を記述します。

ルート
<jsp:root>
xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0" を指定します(JSP 2.0 の場合)。
jsp:root は必須です。

ディレクティブ(指令)
<jsp:directive.要素 属性 />

宣言部
<jsp:declaration></jsp:declaration>

スクリプトレット
<jsp:scriptlet></jsp:scriptlet>


<jsp:expression></jsp:expression>

テキスト
<jsp:text></jsp:text>

XML 予約文字の処理
XML 予約文字は CDATA セクションで囲みます。 

その他
<jsp:element>    要素の定義
<jsp:attribute>    属性の定義
<jsp:body>    属性に対するボディの定義
<jsp:output>    出力形式の定義
<jsp:forward>    転送
<jsp:include>    インクルード
<jsp:plugin>    アップレットなどの実行


<サンプル>
<?xml version="1.0" encoding="Shift_JIS"?>
<jsp:root
    xmlns:jsp="http://java.sun.com/JSP/Page"
    version="2.0">
<jsp:directive.page 
    contentType="text/html; charset=Shift_JIS" />
<jsp:text><&#33;[CDATA[
    <html>
    <body>
]]></jsp:text>
<jsp:declaration>int x;</jsp:declaration>
<jsp:scriptlet>x = 100;</jsp:scriptlet>
<jsp:text>The number is </jsp:text>
<jsp:expression>x</jsp:expression>
<jsp:text><&#33;[CDATA[
    </body>
    </html>
]]></jsp:text> 
</jsp:root>

<出力結果>
The number is 100

その他のアクションタグ

その他のアクションタグ

タグファイルで使用するアクションタグ

jsp:doBody
jsp:invoke

暗黙オブジェクト

JSP では宣言しなくても使用できるオブジェクトがあります。
これにより記述がシンプルになります。



<主な暗黙オブジェクト>
pageContext (javax.servlet.ServletContext)
    アプリケーション共通の情報を管理
config (javax.servlet.ServletConfig)
    初期化パラメータへアクセスできる
exception (java.lang.Throwable)
    @page ディレクティブで isErrorPage が true の場合のみ使用可能
out (javax.servlet.jsp.JspWriter)
    出力手段
page (java.lang.Object)
application (javax.servlet.ServletContext)
request (javax.servlet.http.ServletRequest)
response (javax.servlet.http.ServletResponse)
session (javax.servlet.http.HttpSession)

<サンプル>
下記はコンパイルエラーになります。

<%@ page session="false" %>
<% session.setAttribute("test", "test"); %>

式言語(EL)

式言語は英語では Expression Language といいます。
比較的簡易な記述で式を出力できるメリットがあります。
${ } の形式で記述する。

式言語では下記の暗黙オブジェクトが利用できます。
pageContext
                 pageContext を参照できます。
pageScope
                 page スコープ属性の Map を返します。
requestScope
                 request スコープ属性の Map を返します。
sessionScope
                 session スコープ属性の Map を返します。
applicationScope
                 applicaton スコープ属性の Map を返します。
param
                requestパラメータの Map を返します。
paramValues
                requestパラメータの Map を返します。
                value は String 型配列。
header                 request ヘッダーの Map を返します。
headerValues
                request ヘッダーの Map を返します。
                value は String 型配列
cookie
                Cookie の Map。
                同じ名前が共有されている場合
                HttpServletRequest#getCookies の配列の
                最初の要素をvalue として格納する。
initParam
            アプリケーション初期化パラメータの Map を返します。

Map へのアクセス方法
(例)
${requestScope.key}             request.getAttribute("key")
${requestScope['key']}             request.getAttribute("key")

式言語の演算子

式言語ではエイリアス(別名)を持つ演算子を使用できる
(例)/ は div

下記は式言語で使用できる演算子とその優先順位です。

[] . 
() (優先順位の変更)  
- (単項) not ! empty  
* / div % mod  
+ - (2 項)  
< > <= >= lt gt le ge 
== != eq ne  
&& and  
|| or  
? :  

<サンプル>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%! int x = 5; String s = "5"; %>
<% int a = 5; %>
<c:set var="v" value="5" />
${5 + 5}<br />
${'5' + 5}<br />
${x + 5}<br />
${s + 5}<br />
${v + 5}<br />

<出力結果>
10
10
5
5
10

式言語から静的メソッドの呼び出し

JSP 2.0 以降では式言語から静的メソッドを呼び出せます。
しかし、複雑な処理を行うにはサーブレットの使用が断然推奨されます。
式言語から呼び出す静的メソッドはあくまでシンプルな機能が推奨されます。

<静的メソッドの配備>
package scwcd;

public class ScwcdFunction {
    public static String message(String name) {
        return "You are SCWCD, " + name + "!";
    }



<TLD ファイルの配置>
WEB-INF/tlds 以下に scwcdTaglib.tld ファイルを配置する
scwcdTaglib.tld
<taglib>
<short-name>certified</short-name>
<function>
    <name>message</name>
    <function-class>
        scwcd.ScwcdFunction
    </function-class>
    <function-signature>
        java.lang.String message(java.lang.String)
    </function-signature>
</function>


<このメソッドの呼び出し方>

<%@ taglib prefix="certified" uri="/WEB-INF/tlds/scwcdTaglib.tld" %>
${certified:message("Takashi")}

<出力結果>
You are SCWCD, Takashi!

taglib uri を相対 URI にするには web.xml で下記のように設定してその URI を使います。
web.xml
<taglib>
    <taglib-uri>/scwcdTaglib</taglib-uri>
    <taglib-location>/WEB-INF/tlds/scwcdTaglib.tld</taglib-location>
</taglib>

これで
<%@ taglib prefix="certified" uri="/scwcdTaglib" %>
とすることができます。

JSTL

JSP Standard Tag Library は JSP の汎用的な機能を実装するタグライブラリです。
式言語やアクションタグと組み合わせて使うとより一層 JSP を簡易に記述できます。

JSTL には下記の5つのタグライブラリがあります。

Core
Database
l18n
Xml
Function

<JSTL の設定 - Windows XP 編>
jar ファイルの入手
現時点の最新バージョンは 1.1.2 
http://jakarta.apache.org/site/downloads/downloads_taglibs-standard.cgi
zip ファイルを解凍すると lib フォルダに jstl.jar と standard.jar がある。

jar ファイルの配置
jar ファイルは WEB-INF/lib フォルダに配置します。

<JSP から JSTL を使用する>
@taglib ディレクティブを宣言する。

Core         
<@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
l18n         
<@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
Database     
<@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
XML         
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %> 
Function     
<@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> 

以上で JSTL は使用できるようになります。

JSTL Core

JSTL Core タグライブラリで使用できる主なタグ
<c:set var="obj" value="value" />
    変数の設定
<c:remove var"obj" scope="page" />
    変数の削除
<c:out value="${obj}" />
    変数の出力
<c:import var="page1" url="/header.jsp" charEncoding="UTF-8" />
    外部ファイルのインポート
<c:redirect url="/index.jsp" />
    リダイレクト。
    / で始まる url はコンテキストルート基準。
    属性 context でコンテキストを変更する。
    <c:redirect context="/sjcp" url="/index.html" />
<c:url>
    URL エンコード
<c:catch var="message">...</c:catch>
    例外のキャッチ
<c:forEach var="name" items="${paramValues.names}">
<c:forEach var="i" begin="0" end="5" step="1">
    繰り返し処理
<c:choose>
    分岐処理
<c:when test=${i == 5}>
    条件
<c:otherwise>
    条件
<c:forTokens item="Hello! World" delimms="!">....</c:forTokens>
    文字列分割
<c:if test="${a == b}" var="result" />
    条件
<c:param name="takashi" value="male" />
    パラメータ

<サンプル>
test.jsp
<html>
<body>
<%@ taglib prefix="c"    uri="http://java.sun.com/jsp/jstl/core" %>
<c:if test="${empty paramValues.name[0]}">
    <c:redirect url="/index.jsp" />
</c:if>
<c:forEach var="item" items="${paramValues.name}">
    <c:out value="${item}" /><br />
</c:forEach>
</body>
</html>

index.jsp
<a href="/SCWCD/redirect.jsp?name=Guest&name=Taro&name=Jiro">redirect.jps</a><br />

<出力結果> index.jsp からリンクをクリック
Guest
Taro
Jiro

カスタムタグ


  1. TLD ファイルの定義
    タグライブラリに関する情報をタグライブラリディスクリプタ(TLD ファイル)に定義します。
    通常 WEB-INF/tlds 以下に配置します。


  2. タグハンドラクラスの作成
    タグの動作内容を定義します。
    TLD ファイルで tag-class タグでマッピングします。


  3. taglib ディレクティブ
    JSP ファイルでタグを使用する際、tablib 指令で TLD の URI を指定します。
    TLD ファイルの場所を直接指定するか、相対 URI または jar ファイルを指定します。
    (例)
    直接指定
    <%@ taglib prefix="sample" uri="/WEB-INF/tlds/myTaglib.tld" %>

  4. web.xml の定義(相対 URI の定義)
    web.xml で相対 URI を定義すると taglib ディレクティブで相対 URI を使用できます。
    (例)
    相対URI
    <%@ taglib prefix="sample" uri="/myTaglib.tld" %>

    web.xml
        <jsp-config>
            <taglib>
                <taglib-uri>/myTaglib</taglib-uri>
                <taglib-location>/WEB-INF/tlds/myTaglib.tld</taglib-location>
            </taglib>
        </jsp-config>

    taglib-location に jar ファイルの場所を指定することもできます。

  5. TLD ファイルを収めた jar ファイル
    taglib ディレクティブで jar ファイルを指定する場合、jar ファイルの META-INF ディレクトリ内に TLD ファイルを配置する必要があります。

TLD (タグライブラリディスクリプタ)

TLD ファイルの例

<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/jee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
    version="2.0">
    <tlib-version>2.0</tlib-version>
    <short-name>certified</short-name>
    <tag>
        <name>sample</name>
        <tag-class>scwcd.SampleTag</tag-class>
        <body-content>empty</body-content>
    </tag>
</taglib>

____

TLD ファイルの要素
___________________________________________

tlib-version    バージョンを指定
short-name    タグの略称
tag    
    name    タグの名前
    tag-class    タグハンドラクラスの完全修飾名
    body-content    タグのボディに関する定義
                    empty    ボディなし
                            タグでボディを記述するとコンパイルエラー
                    JSP        JSP コードをボディに記述可能
                    tagdependent    タグハンドラクラスに依存
                    scriptless    JSP スクリプトレットの記述不可
    attribute        
        name    属性名
        required    必須属性かどうか(デフォルト false)
        trexprvalue    Runtime Expression Value(JSP の式)
                    を使用できるかどうか(デフォルト false)
        type        データ型
        fragment    属性がフラグメントかどうか(デフォルト false)
    dynamic-attributes 動的属性を有効にするかどうか
                        (デフォルト false)
tag-file    タグファイルの情報を定義
function    関数の定義
___________________________________________

タグハンドラクラス

タグハンドラクラスを作成するためには主に下記のインターフェースかクラスを利用します。

Tag インターフェース
BodyTag インターフェース
IterationTag インターフェース
TagSupport クラス
BodyTagSupport クラス

これらのインターフェースには int 値を返すメソッドがあり、タグのフローを示します。

_________

TLD ファイルでの定義

タグハンドラクラスは TLD ファイルで tag 要素以下に tag-class で完全修飾名を指定します。

Tag インターフェース

public interface Tag extends JspTag
static int EVAL_BODY_INCLUDE
    ボディの評価をストリームに含める
static int EVAL_PAGE
    ページの評価を続ける
static int SKIP_BODY
    ボディの評価をスキップする
static int SKIP_PAGE
    残りのページの評価をスキップする

______


ライフサイクル
setPageContext(PageContext pc)

setParent(Tag t)

属性のセット

doStartTag()
    EVAL_BODY_INCLUDE / SKIP_BODY

doEndTag()
    EVAL_PAGE / SKIP_PAGE

release()
______

<サンプル>
package scwcd;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.Tag;

public class TagSample implements Tag {
    private PageContext pc;
    private Tag t;
    public int doEndTag() throws JspException {
        return SKIP_PAGE;
    }
    public int doStartTag() throws JspException {
        JspWriter out = pc.getOut();
        try {
            out.println("Hello! World");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return SKIP_BODY;
    }
    public Tag getParent() {
        return t;
    }
    public void release() {}
    public void setPageContext(PageContext pc) {
        this.pc = pc;
    }
    public void setParent(Tag t) {
        this.t = t;
    }
}
____

scwcdTaglib.tld
<taglib>
    <short-name>certified</short-name>
    <tag>
        <name>tagsample</name>
        <tag-class>scwcd.TagSample</tag-class>
        <body-content>emply</body-content>
    </tag>
</taglib>
_____

web.xml
    <jsp-config>
        <taglib>
            <taglib-uri>/scwcdTaglib</taglib-uri>
            <taglib-location>/WEB-INF/tlds/scwcdTaglib.tld</taglib-location>
        </taglib>
    </jsp-config>
_____

tagsample.jsp
<%@ page contentType="text/html;charset=Shift_JIS"%>
<%@ taglib prefix="certified" uri="/scwcdTaglib"%>
<html>
<body>
<certified:tagsample />
</body>
</html>

<出力結果>
Hello! World

BodyTag インターフェース

public interface BodyTag extends IterationTag

static int EVAL_BODY_BUFFERED
新しいバッファを作成しボディを評価する。
____

BodyTag インターフェースはボディコンテントを操作する手段を提供します。
doStartTag は
EVAL_BODY_BUFFERED
EVAL_BODY_INCLUDE
SKIP_BODY

のいずれかを返します。

EVAL_BODY_INCLUDE が返された場合 IterationTag の場合と同じ動作となります。
____

ライフサイクル
setPageContext

setParent

属性のセット

doStartTag → EVAL_BODY_INCLUDE / SKIP_BODY

EVAL_BODY_BUFFERED

doInitBody

BODY

doAfterBody → EVAL_BODY_AGAIN
↓ 
SKIP_BODY

doEndTag

release

IterationTag インターフェース

public interface IterationTagextends Tag

static int EVAL_BODY_AGAIN
ボディの再評価を要求する定数。

_____

IterationTag インターフェースは Tag インターフェースを継承し、
doAfterBody メソッドを追加しています。

_____

ライフサイクル

setPageContext

setParent

属性のセット

doStartTag → SKIP_BODY → doEndTag

EVAL_BODY_INCLUDE

doAfterBody → EVAL_BODY_AGAIN

SKIP_BODY

doEndTag

TagSupport クラス

public class TagSupport
    implements IterationTag, Serializable

protected String id
    id 属性の値を格納します。
protected PageContext pageContext
_______

TagSupport クラスは IterationTag インターフェースを実装してさらに便利なメソッドを付け加えてタグハンドラクラスを作成しやすくしています。


  1. TagSupport クラスにはあらかじめ id プロパティ(変数)が定義されています。

  2. getId メソッドで id キーの値を取得できる。

  3. public Object getValue(String key) で各プロパティ値を取得できる。

  4. public Enumeration<String> getValues メソッドですべてのキーを取得できます。

  5. public static final Tag findAncestorWithClass(Tag from,
            Class klass) メソッド
    指定されたクラスに最も近いタグを返す。 Tag インターフェースの getParent メソッドを呼び出す。
    from 検索を始めるタグ
    klass 検索するタグ


________

<サンプル>
scwcdTaglib.tld
    <tag>
        <name>tagsupportsample</name>
        <tag-class>scwcd.TagSupportSample</tag-class>
        <body-content>emply</body-content>
        <dynamic-attributes>true</dynamic-attributes>
    </tag>
________

web.xml
    <jsp-config>
        <taglib>
            <taglib-uri>/scwcdTaglib</taglib-uri>
            <taglib-location>/WEB-INF/tlds/scwcdTaglib.tld</taglib-location>
        </taglib>
    </jsp-config>
________

TagSupportSample.java
package scwcd;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.DynamicAttributes;
import javax.servlet.jsp.tagext.TagSupport;

public class TagSupportSample extends TagSupport 
        implements DynamicAttributes {
    public void setDynamicAttribute(
            String uri, String key, Object value) 
                throws JspException {
        setValue(key, value);
    }
    public int doStartTag() throws JspException {
        JspWriter out = pageContext.getOut();
        Enumeration<String> keys = getValues();
        while (keys.hasMoreElements()) {
            try {
                String key = keys.nextElement();
                out.println("キー : " + key + 
                        " 値 : " + getValue(key) + 
                        "<br />");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return SKIP_BODY;
    }
}
________

tagsupportsample.jsp
<%@ page contentType="text/html;charset=Shift_JIS"%>
<%@ taglib prefix="certified" uri="/scwcdTaglib"%>
<html>
<body>
<certified:tagsupportsample name="Takashi" age="unknown" />
</body>
</html>
________

<出力結果>
キー : age 値 : unknown
キー : name 値 : Takashi

BodyTagSupport クラス

public class BodyTagSupport
    extends TagSupport
    implements BodyTag

protected BodyContent bodyContent
現在のボディコンテント

BodyTagSupport クラスは BodyTag インターフェースを実装して、新たに便利なメソッドを付け加えています。通常、タグハンドラクラスを作成する場合 BodyTagSupport クラスを継承すると便利だと思います。

タグファイル

タグファイルは JSP の構文で記述できるカスタムタグです。
タグファイルは /WEB-INF/tags 以下に .tag 拡張子で配置します。
JSP ページの taglib ディレクトリの tagdir 属性を /WEB-INF/tags と指定します。

<サンプル>
morning.tag
<%@ tag pageEncoding="Shift_JIS" %>
<p>おはよう。</p>

sample.jsp
<%@ page contentType="text/html;charset=Shift_JIS"%>
<%@ prefix="tags" taglib tagdir="/WEB-INF/tags"%>
<tags:morning/>


<出力結果>
おはよう。
_________

TLD ファイルとタグファイルを jar ファイル化する場合、
タグファイルを /META-INF/tags 以下においた状態で jar ファイル化します。
TLD ファイルに
<tag-file>
<name>morning</name>
<path>/META-INF/tags/morning.tag</path>
</tag-file>
のように定義します。

J2EE デザインパターン

クライアント層
HTML、アップレット

プレゼンテーション層
JSP、サーブレット、JavaBeans

ビジネス層
Enterprise Java Beans

インテグレーション層
DataAccessObject

リソース層
リレーショナルデータベース

プレゼンテーション層

Front Controller

コントロール機能の集約
多様なリクエストを Controller が集約管理してビジネスロジックをコントロールする

セキュリティーの管理能力の向上
入り口を一つにすることでセキュリティ管理のリソースを減らすだけでなく、多様なリクエストのセキュリティを効率よく管理できる。

再利用性が高まる

________

Intercepting Filter

多様なリクエストを Controller で集約的管理。 Controller はフィルタを伴い、各フィルタは緩い結び付きでつながっている。

フィルタ間の緩い結びつきにより再利用性が高まる。
同時に情報の共有には向かない。

________

MVC モデル

多様なクライアントスタイルに対応。
拡張性に優れている。

ビジネス層

Business Delegate



  1. プレゼンテーション層とビジネス層の結びつきを緩くし、コントロールを Business Delegate 一箇所で行い操作性を向上さす。

  2. Business Exceptions を翻訳してエラーの本質をクライアントから隠す。

  3. エラーリバリーと同期化処理を実装する。

  4. シンプルなインターフェースをクライアントに提供する。

  5. クライアントにキャッシュサービスを提供する。

  6. 層が増える。時としてデメリットとなる。
  7. リモート性を隠す。



Session Facade



  1. ビジネス層をコントロールする層を提供する。

  2. 一様のインターフェースを提供する。

  3. ビジネスオブジェクトとクライアントの結びつきを減らし保守性を向上さす。

  4. セキュリティを集中制御。

  5. リモートインターフェースのクライアントへの露出をほとんど無くす。



Service Locator



  1. 複雑さを抽象化してクライアントにシンプルなインターフェースを提供する。

  2. ビジネスコンポーネントの追加を容易にする。

  3. ネットワークパフォーマンスの向上。

  4. キャッシュによりクライアントパフォーマンスを向上さす。/li>


Transfer Object



  1. Entity Bean とリモートインターフェースを単純化する。

  2. リモート呼び出しのデータ量の向上。

  3. ネットワークトラフィックの減少。

  4. 同期化処理が複雑化する