JSPで発生するエラー
JSPでエラーが発生すると、エラーページが表示される。Webサーバによって画面は異なるのだろうけど、Tomcatの場合はこんな画面になる。
これだと、Javaのエラースタックが表示されてしまう。Webアプリケーションの情報をデフォルトで公開してしまうわけなので、セキュリティとしてはあまりよろしくない。
これをなんとかするために、JSPではディレクティブというものが用意されている。これを使えば、エラー発生時に、指定したページに遷移してくれるため、遷移先のエラーページでエラー情報を表示しないようにすればいい。
使い方はJSPの先頭でerrorPage宣言をする。JSPヘッダ部の暗黙的インクルードで共通化してしまうのが手っ取り早い。
<%@ page errorPage="/error.jsp" %>
さらに、エラーページではisErrorPage属性をtrueに設定する。これで定義済みオブジェクト(exception)が使える。
<%@ page isErrorPage="true" %> <% out.println(exception.getMessage());%>
ケース:jsp:includeでエラーが発生
- include先でerrorPage属性を指定していたらそのページ
- include先でerrorPage属性を指定していなかったらincludeしているページのerrorPage属性のページ
ケース:c:importでエラーが発生
- import先でerrorPage属性を指定していても無効
- import元のerrorPage属性が絶対有効になる
ServletContextで発生するエラー
web.xmlのerror-pageタグを使えば、アプリケーション全体で発生するエラーを確実にキャッチできる。まずはエラーコードで指定。内部エラー以外にも404(ページがありません)などもキャッチしておきたいところ。
404 /error2.jsp
Exceptionのクラスで指定する場合はこんな感じ。ただし、これだと404エラーは拾われない。多分、40X系のステータスコードはサーバの問題ではないからだと思われる。
java.lang.Exception /error.jsp
500エラーでの設定と、Exceptionクラスの判定が両方とも書かれていた場合、クラス指定のほうが勝つ。よって恐らくクラス指定が先に判定されるのだろう。
注意:エラーページ(ここではerror2.jspが出力したファイル)のサイズが512バ
イト以上でないとうまく表示されず、IEのエラーページが表示されてしまう。これはIEのいけてない仕様なので、エラーページが軽かったら空白とかをだー
と書いて512バイト以上のサイズにすればいい。JSPのサイズじゃないので注意!
また、error.jspで運用用にログを出力する場合、「404 – Not Found」などの場合はログを出力しないようにしないといけない。404ごときでログをはいていると大変なことになる。
Exceptionクラスを指定しても、JSPでのエラーは拾ってくれない。JSPでのエラーはerrorPage属性が有効的
どっちを使うべきか?
ディレクティブのerrorPage属性だとJSPで発生した例外しか制御できないが、web.xmlのerror-pageタグだとアプリケーション全体として制御できる。なので、後者のほうが有効ではと考えた。
- errorPage属性をつけると、エラーページを表示してくれるが、include先でエラーが起こると、既に出力されているHTML部分が表示され、エラーページが埋め込まれた状態で表示される
- error-pageタグだとHTMLにはエラーページが表示されない(エラー情報をユーザに見せない)。ただ、何が起きたのかユーザには伝わらない
どちらにするかしら。動的インクルードより静的インクルードのほうがいい気がしてきた。