ラベル 基本メモ の投稿を表示しています。 すべての投稿を表示
ラベル 基本メモ の投稿を表示しています。 すべての投稿を表示

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 ファイルの記録されます。

参照 リスナーの配備