「フィルタ」の編集履歴(バックアップ)一覧はこちら
「フィルタ」(2009/03/10 (火) 22:56:56) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
*&bold(){<filter>要素と<filter-mapping>要素}
例として「/hello/」で始まるURLでサーブレットが呼ばれた場合に適用するフィルタを作成する場合
<web-app>
<filter>
<filter-name>
filtertest // ←フィルタ名
</filter-name>
<filter-class>
FilterTest // ←フィルタとして実行するサーブレットクラス名
</filter-class>
</filter>
<filter-mapping>
<filter-name>
filtertest // ←フィルタ名
</filter-name>
<url-pattern>
/hello/* // ←URLパターン
</url-pattern>
</filter-mapping>
</web-app>
フィルタを使う場合でも、もちろん<servlet>要素や<servlet-mapping>要素を記述する必要がある。
フィルタの記述する位置は<servlet>要素よりも前に記述する。
*&bold(){Filterインターフェース}
"init"メソッド、"destroy"メソッド、"doFilter"メソッドを実装する。
import java.io.*;
import javax.servlet.*;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
public class FilterTest implements Filter{
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain){
try{
/* フィルタで行う処理 */
}catch (ServletException se){
}catch (IOException e){
}
}
public void init(FilterConfig filterConfig){
}
public void destroy(){
}
}
次のサーブレットへ処理を移すには、FilterChainインターフェースで定義されている"doFilter"メソッドを使用する。
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain){
try{
/* フィルタで行う処理 */
chain.doFilter(request, response);
}catch (ServletException se){
}catch (IOException e){
}
}
FilterChainインターフェースの"doFilter"メソッドを呼び出さずに、他のサーブレットへフォワードやリダイレクトしてフィルタの流れを切る事も可能。
if (認証が行われている) then{
chain.doFilter(request, response);
}else{
((HttpServletResponse)response).sendRedirect("/Login");
}
|URL|http://localhost:8080/filter/helloworld|
|アプリケーション配置場所|c:\servlet-sample\filter\|
|web.xmlファイル|c:\servlet-sample\filter\WEB-INF\web.xml|
|コンテキストファイル|C:\Program Files\Apache Software Foundation\Tomcat 5.5\conf\Catalina\localhost\filter.xml|
※2009.03.01時点でのバージョンは5.1.7
以下の順でダウンロードする。
+ここにアクセス http://dev.mysql.com/downloads/
+Drivers and ConnectorsのMySQL Connector/J — for connecting to MySQL from Javaの「MySQL Connector/J 5.1」
+Source and Binaries (zip)の「Pick a mirror」
+New Usersの「Proceed」
+画面下部の「No thanks, just take me to the downloads!」
+好きなミラーサイトの「HTTP」
+適当な場所にダウンロード
-インストール
+ダウンロードしたファイルを解凍(mysql-connector-java-5.1.7.zip)
+解凍したフォルダ内のmysql-connector-java-5.1.7-bin.jarをTomcatをインストールしたフォルダ\common\lib\にコピーする。
*&bold(){JDBCドライバのロード}
MySQLの場合は次のように行う。
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
}catch (ClassNotFoundException e){
}catch (Exception e){
}
|URL|http://localhost:8080/database/databasetest|
|アプリケーション配置場所|c:\servlet-sample\database\|
|web.xmlファイル|c:\servlet-sample\database\WEB-INF\web.xml|
|コンテキストファイル|C:\Program Files\Apache Software Foundation\Tomcat 5.5\conf\Catalina\localhost\database.xml|
*&bold(){データベースへの接続と切断}
データベースへの接続を確立するには「DriverManager」クラスで用意されている"getConnection"メソッドを使う。
引数には接続するデータベースを表すURLと接続用のユーザー名とパスワードを指定する。
MySQLの場合、URLの形式は次のようになる。
jdbc:mysql://(サーバ名)/(データベース名)
例えばローカルホストにある「jdbctestdb」というデータベースに接続する場合は次のようになる。
jdbc:mysql://localhost/jdbctestdb
実際の使用例
Connection conn = null;
String url = "jdbc:mysql://localhost/jdbctestdb";
String user = "testuser";
String password = "testpass";
try{
conn = DriverManager.getConnection(url, user, password);
// データベースに対する処理
}catch (SQLException e){
}
-データベースの切断
いったん接続した後に切断する場合には、接続の際に取得したConnectionインターフェースのオブジェクトに対して、"close"メソッドを使う。
"close"メソッドは何か問題が発生した際に忘れずに行うためにも、次のように"finally"節を使って記述する。
Connection conn = null;
String url = "jdbc:mysql://localhost/jdbctestdb";
String user = "testuser";
String password = "testpass";
try{
conn = DriverManager.getConnection(url, user, password);
// データベースに対する処理
}catch (SQLException e){
// 例外処理
}finally{
try{
if (conn != null){
conn.close();
}
}catch (SQLException e){
// 例外処理
}
}
*&bold(){データベースの用意}
データベース名は「jdbctestdb」とする。
+MySQLへ接続する: mysql -u root -p
+パスワード応答
+データベースを作成する: create database jdbctestdb;
+テスト用データベースに接続する: use jdbctestdb
+テーブルを作成する: create table kabukatable(code int, company varchar(32), primary key(code) );
+ユーザの追加、権限設定: grant select,insert,update,delete on jdbctestdb.* to 'testuser'@'localhost' identified by 'testpass';
+データを追加する: 下記参照
+データを確認する: select * from kabukatable;
&u(){データを追加する}
※コマンドプロンプトからINSERTしようとした場合、「ERROR 1366 (HY000): Incorrect string value: '\x83r\x83b\x83N...' for column 'com
pany' at row 1」というエラーが発生し追加できない。これはどうやらMySQLインストール時に文字コードをutf-8にしたからの模様。正しい対処かどうかはわからないが、以下のSETコマンドを実行することでINSERTができるようになる。別セッションでSELECTしたりする場合は、毎回このSETを実行しないと文字化けする。
SET character_set_client = sjis;
SET character_set_connection = utf8;
SET character_set_results = sjis;
insert into kabukatable values
(3048,'ビックカメラ'),
(4689,'ヤフー'),
(4755,'RAKUTEN'),
(9984,'SoftBank');
*&bold(){データベース接続テスト}
|URL|http://localhost:8080/database/databasetest1|
*&bold(){データの取得(SELECT)}
-ステートメントを作成する
Connection」インターフェースで定義されている"createStatement"メソッドを使う。
conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
-問い合わせの実行
「Statement」インターフェースで用意されている"executeQuery"メソッドを使う。
conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
String sql = "SELECT * FROM kabukatable";
ResultSet rs = stmt.executeQuery(sql);
-結果の取得
カーソルを動かすには「ResultSet」インターフェースで定義されている"next"メソッドを使う。
conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
String sql = "SELECT * FROM kabukatable";
ResultSet rs = stmt.executeQuery(sql);
while(rs.next()){
/* 行からデータを取得 */
int code = rs.getInt("code");
String company = rs.getString("company");
}
データ型毎の値取得メソッド一覧(一部)
boolean getBoolean(String columnName)
byte getByte(String columnName)
Date getDate(String columnName)
double getDouble(String columnName)
int getInt(String columnName)
long getLong(String columnName)
Timestamp getTimestamp(String columnName)
-リソースの開放
使わなくなった「ResultSet」オブジェクトは"close"メソッドを使ってリソースを開放する。
また、「Statement」オブジェクトもに"close"メソッドを使ってリソースを開放する。
rs.close();
stmt.close();
|URL|http://localhost:8080/database/databasetest2|
*&bold(){データの更新(UPDATE)}
「Statement」インターフェースで用意されている"executeUpdate"メソッドを使う。
conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
String sql = "update kabukatable set company='楽天(株)' where code = 4755";
int num = stmt.executeUpdate(sql);
|URL|http://localhost:8080/database/databasetest3|
*&bold(){データの追加(INSERT)}
「Statement」インターフェースで用意されている"executeUpdate"メソッドを使う。
conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
String sql = "insert into kabukatable (code, company) values (2491, 'バリューコマース')";
int num = stmt.executeUpdate(sql);
*&bold(){データの削除(DELETE)}
「Statement」インターフェースで用意されている"executeUpdate"メソッドを使う。
conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
String sql = "delete from kabukatable where id = 4755";
int num = stmt.executeUpdate(sql);
*&bold(){prepareStatementの使用}
「Connection」インターフェースで定義されている"prepareStatement"メソッドを使う。
パラメータとして後から指定する部分には、実際の値を記述する替わりに「?」を記述したSQL文を作成し、そのSQLを元にプリペアドステートメントを作成する。
String sql = "insert into kabukatable (code, company) values (?, ?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
この例では実際に挿入する値を記述箇所に「?」を使っている。2箇所使っているので、後からパラメータを2つ指定する必要がある。
-パラメータへ値の設定
「PreparedStatement」インターフェースで用意されている「setInt」メソッドを使う。
パラメータの数だけメソッドを実行する。パラメータはSQL文中に記述された「?」を先頭から順番に1,2,3、・・・と順番に番号が割り当てられる。1番目のメソッドにはパラメータの番号を指定し、2番目の引数にパラメータに設定したい値を記述する。
String sql = "insert into kabukatable (code, company) values (?, ?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, 4755);
pstmt.setString(2, "楽天(株)");
パラメータに値を設定するには設定する値のデータ型毎に別々のメソッドが用意されてる。(一部)
|メソッド|説明|
|void setString(int parameterIndex, String x)|String 値に設定します。|
|void setInt(int parameterIndex, int x)|int 値に設定します。|
|void setLong(int parameterIndex, long x)|long 値に設定します。|
|void setByte(int parameterIndex, byte x)|バイト配列に設定します。|
|void setFloat(int parameterIndex, float x)|float 値に設定します。|
|void setDouble(int parameterIndex, double x)|double 値に設定します。|
|void setDate(int parameterIndex, Date x)|java.sql.Date 値に設定します。|
|void setTime(int parameterIndex, Time x)|java.sql.Time 値に設定します。|
|void setBoolean(int parameterIndex, boolean x)|boolean 値に設定します。|
|void setTimestamp(int parameterIndex, Timestamp x)|java.sql.Timestamp 値に設定します。|
-プリペアドステートメントの実行
「PreparedStatement」インターフェースにはSELECTなどのクエリーの結果を取得する場合に使う「executeQuery」メソッドと、INSERTやUPDATEなどの結果が返されない場合に使う「executeUpdate」メソッドがある。この使い方は「Statement」の場合と同じ。
conn = DriverManager.getConnection(url, user, password);
String sql = "insert into kabukatable (code, company) values (?, ?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, 4755);
pstmt.setString(2, "楽天(株)");
int num = pstmt.executeUpdate();
-パラメータのクリア
プリペアドステートメントを複数回続けて実行する場合、値が変更されないパラメータについては改めて設定する必要はない。
次の例では1番目のパラメータは変更が無く、2回目に実行する時には2番目のパラメータだけを設定する。
String sql = "insert into kabukatable (basho, company) values (?, ?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, "東証");
pstmt.setString(2, "ドコモ");
int num = pstmt.executeUpdate();
pstmt.setString(2, "KDDI");
num = pstmt.executeUpdate();
現在設定されているパラメータを全て一度クリアしたい場合には「PreparedStatement」インターフェースで用意されている「clearParameters」メソッドを使う。
|URL|http://localhost:8080/database/databasetest6|
*&bold(){<filter>要素と<filter-mapping>要素}
例として「/hello/」で始まるURLでサーブレットが呼ばれた場合に適用するフィルタを作成する場合
<web-app>
<filter>
<filter-name>
filtertest // ←フィルタ名
</filter-name>
<filter-class>
FilterTest // ←フィルタとして実行するサーブレットクラス名
</filter-class>
</filter>
<filter-mapping>
<filter-name>
filtertest // ←フィルタ名
</filter-name>
<url-pattern>
/hello/* // ←URLパターン
</url-pattern>
</filter-mapping>
</web-app>
フィルタを使う場合でも、もちろん<servlet>要素や<servlet-mapping>要素を記述する必要がある。
フィルタの記述する位置は<servlet>要素よりも前に記述する。
*&bold(){Filterインターフェース}
"init"メソッド、"destroy"メソッド、"doFilter"メソッドを実装する。
import java.io.*;
import javax.servlet.*;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
public class FilterTest implements Filter{
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain){
try{
/* フィルタで行う処理 */
}catch (ServletException se){
}catch (IOException e){
}
}
public void init(FilterConfig filterConfig){
}
public void destroy(){
}
}
次のサーブレットへ処理を移すには、FilterChainインターフェースで定義されている"doFilter"メソッドを使用する。
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain){
try{
/* フィルタで行う処理 */
chain.doFilter(request, response);
}catch (ServletException se){
}catch (IOException e){
}
}
FilterChainインターフェースの"doFilter"メソッドを呼び出さずに、他のサーブレットへフォワードやリダイレクトしてフィルタの流れを切る事も可能。
if (認証が行われている) then{
chain.doFilter(request, response);
}else{
((HttpServletResponse)response).sendRedirect("/Login");
}
|URL|http://localhost:8080/filter/helloworld|
|アプリケーション配置場所|c:\servlet-sample\filter\|
|web.xmlファイル|c:\servlet-sample\filter\WEB-INF\web.xml|
|コンテキストファイル|C:\Program Files\Apache Software Foundation\Tomcat 5.5\conf\Catalina\localhost\filter.xml|
*&bold(){フィルタを多重に設定する}
<filter>要素と<filter-mapping>要素を複数記述すればよい。
フィルタの実行順は、<filter-mapping>が定義されている順となる。
<web-app>
<filter>
<filter-name>filtertest</filter-name>
<filter-class>FilterTest</filter-class>
</filter>
<filter>
<filter-name>filtertest2</filter-name>
<filter-class>FilterTest2</filter-class>
</filter>
<filter-mapping>
<filter-name>filtertest</filter-name> // ←最初に実行されるフィルタ
<url-pattern>/hello/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>filtertest2</filter-name> // ←後に実行されるフィルタ
<url-pattern>/hello/*</url-pattern>
</filter-mapping>
</web-app>
*&bold(){<dispatcher>要素}
サーブレットから別のサーブレットへフォワードされた時にフィルタが呼び出されるように設定することも可能。
<filter-mapping>要素の子要素の1つに<dispatcher>要素があり、<dispatcher>要素にどのタイミングでフィルタが実行されるのかを指定する。
|値|フィルタのタイミング|
|REQUEST|URLがリクエストされた時|
|FORWARD|フォワードが行われた時|
|INCLUDE|インクルードが行われた時|
|ERROR|エラーページへ処理が移る時|
1つの<filter-mapping>要素内で<dispatcher>要素は0回から4回まで設定出来、4つの全てのタイミングを指定することも可能。
<web-app>
<filter>
<filter-name>filtertest</filter-name>
<filter-class>FilterTest</filter-class>
</filter>
<filter-mapping>
<filter-name>filtertest</filter-name>
<url-pattern>/hello/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
</web-app>