ここでは、送信データを利用した検索について演習します。 完全に一致する場合と、部分的に一致すればいい場合とがあり、その 両者を実現する方法を学びます。 部分的な一致を調べる場合には、正規表現に関する 知識が必要になります。かいつまんで説明していますので、必要があれば インターネットで検索するなどして調べてみてください。
JSPでは日本語データのやり取りの際には、文字コードを意識しなければ いけません。Javaによる内部処理はUnicodeが使われており、 WebブラウザからのデータがUnicodeでない時には、自動的に判断 してくれるようになっていますが、文字化けが起こる場合もあります。 正しい動作を保証するためには文字コードを明示した方がよさそうです。
下記では、変数Nameに格納されたデータをShift_JISへ変換するまでの 処理を表しています。
上記のorgNameに格納されているデータに対して、 getBytesというメソッドにISO-8859-1を明記して、 ISO-8859-1という文字コードで バイト単位でデータを取り出しています。そして、その取り出したデータを Shift_JISに変換して、StringクラスのconvertedNameというインスタンスに 格納している、という流れを意味しています。これにより、 Shift_JISで作成されたJSPファイルからのデータも、文字化けせずに 済みます。
上記ではShift_JISへ変換してWebブラウザに出力するよう明記していますが、 下記のようにJISAutoDitectという方法で自動判別による 変換を指示することもできます。ですが、書籍やWebページを見てみると、 誤った判別の可能性もあり、上記のように文字コードを明記する方が無難との ことです。
追記事項:
日本語の文字化けに対して、Servlet API2.3から、 setCharacterEncoding()というメソッドが使えるようにな りました。したがって、一度だけ、
と記述するだけで、後はgetParameter()メソッドでデータを受け取っても 文字化けしなくなります。今後はこちらを使用していきます。
それでは下記の見本、address1.html、address1.jspを作ってみましょう。 見本では、名前とメールアドレ スを送信して処理するだけのHTML、JSPファイルです。 両者をSun ONEを使って自分自身で入力して作成し、送信される日本語デー タがどのように表示されるか、確認しましょう。
address1.html
<html> <head> <title>メールアドレスの検索</title> </head> <body> <form method="post" action="address1.jsp"> <p> 入力して下さい </p> <table border="1"> <tr> <th>名前</th> <td><input type="text" size="30" name="yourName" /></td> </tr> <tr> <th>メールアドレス</th> <td><input type="text" size="30" name="yourMail" /></td> </tr> </table> <br /> <input type="submit" value="送信" /> </form> </body> </html>
address1.jsp
<%@ page contentType="text/html;charset=Shift_JIS" %> <html> <head> <title>メールアドレスの検索結果</title> </head> <body> <% String orgName = request.getParameter("yourName"); String yourName = new String(orgName.getBytes("ISO-8859-1"), "Shift_JIS"); String orgMail = request.getParameter("yourMail"); String yourMail = new String(orgMail.getBytes("ISO-8859-1"), "Shift_JIS"); %> <p> 送信結果 </p> <table border="1"> <tr> <th></th> <th>文字コード変換前</th> <th>文字コード変換後</th> </tr> <tr> <th>名前</th> <td><%=orgName%></td> <td><%=yourName%></td> </tr> <tr> <th>メールアドレス</th> <td><%=orgMail%></td> <td><%=yourMail%></td> </tr> </table> </body> </html>
address1.jspでは単に文字コードを変換しただけでした。ここでは form要素を利用したクロスサイトスクリプティングという、 悪意を持った攻撃への対策として、特定の特殊記号(メタキャラクタ)を 別の表現に置換する エスケープ文字への変換を行います。
クロスサイトスクリプティングに関するWebページの例
メタキャラクタとその置換
メタキャラクタ | エスケープ文字 |
---|---|
< | < |
> | > |
& | & |
" | " |
上記のように、form要素から送られてきた「<」のような記号は、対応する エスケープ文字である「<」に置換する必要があります。
以下では、 address1.jspに、エスケープ文字への変換処理を追記したaddress2.jspを 示してありますが、 <%!〜%>の間で、変換処理のメソッドを宣言 しています。Sun ONE上で作成してください。address2.htmlは address1.htmlをコピーして作成してください。ただし、 「action="address1.jsp"」の箇所を 「action="address2.jsp"」のように 修正してください。
動作確認の際に、入力データにわざと「<」のような特殊記号を入力して 送信してみてください。出力結果では正しくエスケープ文字へ 変換されているか、Webブラウザの「ソースの表示」で確認しましょう。
address2.jsp
<%@ page contentType="text/html;charset=Shift_JIS" %> <%! private String escapeChar(String strInput){ StringBuffer strOutput=new StringBuffer(); for(int i=0;i<strInput.length();i++){ switch(strInput.charAt(i)){ case '<' : strOutput.append("<"); break; case '>' : strOutput.append(">"); break; case '&' : strOutput.append("&"); break; case '"' : strOutput.append("""); break; default : strOutput.append(strInput.charAt(i)); break; } } return strOutput.toString(); } %> <html> <head> <title>メールアドレスの検索結果</title> </head> <body> <% request.setCharacterEncoding("Shift_JIS"); String yourName = request.getParameter("yourName"); yourName = escapeChar(yourName); String yourMail = request.getParameter("yourMail"); yourMail = escapeChar(yourMail); %> <p> 送信結果 </p> <table border="1"> <tr> <th>名前</th> <td><%=yourName%></td> </tr> <tr> <th>メールアドレス</th> <td><%=yourMail%></td> </tr> </table> </body> </html>
それでは、送信されてきたデータが予め用意してあるデータに合致するかどうか 調べてみましょう。JSPスクリプト内に配列を用意し、メールアドレスを格納し ています。for文による繰り返し処理で、送信データと配列の各要素の 内容が等しいか調べています。文字列が等しいかどうかは equalsメソッドを利用しています。
address3.jsp
<%@ page contentType="text/html;charset=Shift_JIS" %> <%! private String escapeChar(String strInput){ StringBuffer strOutput=new StringBuffer(); for(int i=0;i<strInput.length();i++){ switch(strInput.charAt(i)){ case '<' : strOutput.append("<"); break; case '>' : strOutput.append(">"); break; case '&' : strOutput.append("&"); break; case '"' : strOutput.append("""); break; default : strOutput.append(strInput.charAt(i)); break; } } return strOutput.toString(); } %> <html> <head> <title>メールアドレスの検索結果</title> </head> <body> <% request.setCharacterEncoding("Shift_JIS"); String yourName = escapeChar(request.getParameter("yourName")); String yourMail = escapeChar(request.getParameter("yourMail")); String[] mailArray = {"yamada_jp@hotmail.com", "gogo@docomo.ne.jp", "e01200yy@edu.tuis.ac.jp", "g03010yy@rsch.tuis.ac.jp", "y_yamada@rsch.tuis.ac.jp"}; %> <p> 送信結果 </p> <% int flag = 0; if (yourName.equals("")) { out.println("名前を入力してください<br />"); flag = -1; } if (yourMail.equals("")) { out.println("メールアドレスを入力してください<br />"); flag = -1; } if (flag != -1) { %> <table border="1"> <tr> <th>名前</th> <td><%=yourName%></td> </tr> <tr> <th>メールアドレス</th> <td><%=yourMail%></td> </tr> </table> <% for (int i=0; i<mailArray.length; i++) { if (mailArray[i].equals(yourMail)) { out.println("<p>入力されたメールアドレスはありました</p>"); flag = 1; break; } } if (flag == 0) { out.println("<p>入力されたメールアドレスはありませんでした</p>"); } } %> </body> </html>
今度は、入力されたデータが特定の形式にしたがっているか判断し、その形式に 合わなければ、検索する前にエラー処理を行います。ここで 正規表現 (regular expression)という処理が必要になりま す。
正規表現そのものは、UNIXのコマンドでの処理やPerlでの処理でも利用 され、またWindowsの代表的なテキストエディタである秀丸でもある 程度の機能を利用できます。Perlでの正規表現は こちらのWebページ、 また秀丸での正規表現は こちらのWebページに記載されていますので、参考にしてください。
java.util.regexパッケージで使用できる主な正規表現
正規表現 | 意味 |
---|---|
. | 任意の1文字が存在すればマッチ |
* | 直前のものが0回以上繰り返すとマッチ |
+ | 直前のものが1回以上繰り返すとマッチ |
{m} | 直前のものがm回繰り返すとマッチ |
{m,} | 直前のものがm回以上繰り返すとマッチ |
[ ] 例:[あさと]んま |
または(1文字のみ対応可能) 「あんま」、「さんま」、「とんま」にマッチ |
( | ) 例:東京(情報|農業)大学 |
または(1文字以上に対応可能) 「東京情報大学」、「東京農業大学」にマッチ |
[0-9] | 0から9までの数字にマッチ |
[a-z] | aからzまでの英文字にマッチ |
^ | 文字列の先頭にあればマッチ |
$ | 文字列の終わりにあればマッチ |
[^ ] | 否定 |
下記の見本、address4-1.jspでは、入力されたメールアドレスに対して、 「.+@.+」 というパターン(正規表現)にあてはまるか判定しています。 この意味は以下の通りです。
正規表現 | .+ | @ | .+ |
---|---|---|---|
意味 | 任意の1字以上の文字列 | @マーク(ただの文字) | 任意の1字以上の文字列 |
したがって、「@の前には1字以上の文字列、後にも1字以上の文字列で 構成される文字列」という条件を指定していることになります。
address4-1.jsp
<%@ page contentType="text/html;charset=Shift_JIS" %> <%@ page import="java.util.regex.*" %> <%! private String escapeChar(String strInput){ StringBuffer strOutput=new StringBuffer(); for(int i=0;i<strInput.length();i++){ switch(strInput.charAt(i)){ case '<' : strOutput.append("<"); break; case '>' : strOutput.append(">"); break; case '&' : strOutput.append("&"); break; case '"' : strOutput.append("""); break; default : strOutput.append(strInput.charAt(i)); break; } } return strOutput.toString(); } %> <html> <head> <title>メールアドレスの検索結果</title> </head> <body> <% request.setCharacterEncoding("Shift_JIS"); String yourName = escapeChar(request.getParameter("yourName")); String yourMail = escapeChar(request.getParameter("yourMail")); String[] mailArray = {"yamada_jp@hotmail.com", "gogo@docomo.ne.jp", "e01200yy@edu.tuis.ac.jp", "g03010yy@rsch.tuis.ac.jp", "y_yamada@rsch.tuis.ac.jp"}; %> <p> 送信結果 </p> <% int flag = 0; if (yourName.equals("")) { out.println("名前を入力してください<br />"); flag = -1; } if (yourMail.equals("")) { out.println("メールアドレスを入力してください<br />"); flag = -1; } else { Pattern searchPattern = Pattern.compile(".+@.+"); Matcher searchMatcher = searchPattern.matcher(yourMail); if (!searchMatcher.find()) { out.println("正しいメールアドレスを入力してください<br />"); flag = -1; } } if (flag != -1) { %> <table border="1"> <tr> <th>名前</th> <td><%=yourName%></td> </tr> <tr> <th>メールアドレス</th> <td><%=yourMail%></td> </tr> </table> <% for (int i=0; i<mailArray.length; i++) { if (mailArray[i].equals(yourMail)) { out.println("<p>入力されたメールアドレスはありました</p>"); flag = 1; break; } } if (flag == 0) { out.println("<p>入力されたメールアドレスはありませんでした</p>"); } } %> </body> </html>
上記の処理の中でも、正規表現に関する部分について説明します。 まず、正規表現のパターンを記述するインスタンスが必要になります。 そのため、下記のように
Patternクラスのインスタンスを生成しています。正規表現のパターンは、 Patternクラスのcompile()メソッドを利用して、 ".+@.+"のように記述しています。
次に、パターンを含むかどうか調べたい対象を特定します。それが、
のように記述されています。Matcherクラスのインスタンスとして、 searchMatcherを生成しています。上記の処理では、yourMailに 格納されている文字列(メールアドレス)に対して正規表現があてはまるか どうかを調べようとしています。そして、
は、与えられた正規表現にあてはまらなければ、if文が実行されます。 与えられた正規表現にあてはまれば、searchMatcher.find()はtrueを返します。 「!」の記号で、否定を表すことも注意してください。
課題1:上記のaddress4-1.jspを参考にし、正規表現の 部分を修正して、@の直後には、 「.以外の1文字以上の文字列」、 「.」、 「.以外の1文字以上の文字列」 があるメールアドレス のみを通し、それ以外のメールアドレスに対してはエラーを表示させたい。 そのようなJSPファイルをaddress4-2.jspとして作成し、動作確認せよ。 ちなみにJSPでの正規表現では、 文字としてのピリオドは\\. で表現される。
要求されている正規表現:
正規表現 | .+ | @ | 自分で考えよう | \\. | 自分で考えよう |
---|---|---|---|---|---|
意味 | 任意の1字以上の文字列 | @マーク(ただの文字) | .以外の1字以上の文字列 | . | .以外の1字以上の文字列 |
エラー表示させたいメールアドレスの例:
課題1の解答(正規表現の部分だけ): 演習中の説明と若干違います
課題2:課題1の条件に加えて、正規表現の 部分を修正して、@が2つ以上あるメールアドレスに対しては エラーを表示させるJSPファイルをaddress4-3.jspとして作成し、動作確認せよ。
エラー表示させたいメールアドレスの例:
課題3: @が1つだけであり、末尾がtuis.ac.jpであるメールアドレス 以外にはエラーを表示させるJSPファイルをaddress4-4.jspとして作成し、 動作確認せよ。
条件を満たすメールアドレスの例:
エラー表示させるメールアドレスの例:
課題4:課題3の条件に加えて @の前は、「m, e, s, c, gのうちの1文字」+ 「5桁の数字」+「2桁の英文字」から構成されるメールアドレス 以外にはエラーを表示させるJSPファイルをaddress4-5.jspとして作成し、 動作確認せよ。
条件を満たすメールアドレスの例:
エラー表示させるメールアドレスの例:
上記の課題1〜4までの、正規表現の部分だけを記述したテキストファイルを作成 し、2004/01/19(月)の演習開始時に提出せよ。
提出課題の例
学籍番号:e01000ab 氏名:環境花子 解答: 課題1:.+@[^\\.]+\\.[^\\.]+ 課題2: 課題3: 課題4:
今度は入力されたメールアドレスの一部分を手がかりに、配列に格納された データに部分的に一致するかどうか調べていきます。下記のJSPファイルを address5.jspとして作成しましょう。
動作確認として様々な文字列、および正規表現を取り入れた文字列で 試してみましょう。例えば、 「yamada」と「^yamada」との違い、 「jp」と「jp$」との違いを確認 してみましょう。
address5.jsp
<%@ page contentType="text/html;charset=Shift_JIS" %> <%@ page import="java.util.regex.*" %> <%! private String escapeChar(String strInput){ StringBuffer strOutput=new StringBuffer(); for(int i=0;i<strInput.length();i++){ switch(strInput.charAt(i)){ case '<' : strOutput.append("<"); break; case '>' : strOutput.append(">"); break; case '&' : strOutput.append("&"); break; case '"' : strOutput.append("""); break; default : strOutput.append(strInput.charAt(i)); break; } } return strOutput.toString(); } %> <html> <head> <title>メールアドレスの検索結果</title> </head> <body> <% request.setCharacterEncoding("Shift_JIS"); String yourName = escapeChar(request.getParameter("yourName")); String yourMail = escapeChar(request.getParameter("yourMail")); String[] mailArray = {"yamada_jp@hotmail.com", "gogo@docomo.ne.jp", "e01200yy@edu.tuis.ac.jp", "g03010yy@rsch.tuis.ac.jp", "y_yamada@rsch.tuis.ac.jp"}; %> <p> 送信結果 </p> <% int flag = 0; if (yourName.equals("")) { out.println("名前を入力してください<br />"); flag = -1; } if (yourMail.equals("")) { out.println("検索したい文字列を入力してください<br />"); flag = -1; } if (flag != -1) { %> <table border="1"> <tr> <th>名前</th> <td><%=yourName%></td> </tr> <tr> <th>メールアドレス</th> <td><%=yourMail%></td> </tr> </table> <% Pattern searchPattern = Pattern.compile(yourMail); for (int i=0; i<mailArray.length; i++) { Matcher searchMatcher = searchPattern.matcher(mailArray[i]); if (searchMatcher.find()) { out.println("合致したメールアドレス:"+mailArray[i]+"<br />"); flag = 1; } } if (flag == 0) { out.println("合致したメールアドレスはありません。<br />"); } } %> </body> </html>