Tomcat や Jetty などの Java ウェブアプリケーションでエラーが発生した時に表示されるエラーページを独自のものにカスタマイズする方法の紹介です。もちろんエラーが発生しないことが望ましいのですが、万が一エラーが発生してしまった場合に、標準のエラーメッセージが出てしまうと、どのアプリケーションサーバーを使っているのかが分かってしまいます。その結果、そのサーバーのセキュリティホールを狙われる可能性もないわけではありません。あとエラーページにユーモアを交えるような目的でも有用だと思います。

ではその手順の紹介です。 まずアプリケーションの web.xml の最後に以下の青字の情報を追加します:
  :
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

  <error-page>
    <error-code>404</error-code>
    <location>/error/404.html</location>
  </error-page>
  <error-page>
    <error-code>500</error-code>
    <location>/error/500.jsp</location>
  </error-page>
</web-app>

この例ではステータスコードが 404(ページが見つからないエラー)の時と、500(サーバー内部エラー)の時用のページをカスタマイズする前提で、その2つのページに関する情報を追加しています。他のエラー(認証など)についてもカスタマイズする場合は同様に追加してください。この例ではページが見つからない場合は /error/404.html に、Java コード等での内部エラー発生時には /error/500.jsp にそれぞれ飛ばすような指定をしています。もちろん静的な HTML ページでもいいのですが、今回は 500 エラーの時には JSP にして動的に作成してみます。

そしてこれらのページを作っていきます。/error/404.html は 404 エラー、つまり URL が間違っていることになるので、こんな感じの内容で:
<html>
<head>
<title>404</title>
</head>
<body>
<h1>見つからないよ~</h1>
</body>
</html>

一方、/error/500.jsp は 500 エラー、つまり Java の内部エラーなので、スタックトレースも表示するような内容にしてみます。試しにこんな感じにしました。また isErrorPage を true にしています:
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<%@ page import="javax.servlet.http.*" %>
<%@ page import="javax.servlet.*" %>
<% request.setCharacterEncoding("utf-8"); %>
<%@ page isErrorPage="true"%>

<html>
<head>
<title>500</title>
</head>
<body>
<h1>Internal な Server の Error だよ~</h1>

<% exception.printStackTrace(new java.io.PrintWriter(out)); %>


</body>
</html>

最後に、わざと 500 エラーを発生させるための JSP ページを作成します:
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<%@ page import="javax.servlet.http.*" %>
<%@ page import="javax.servlet.*" %>
<% request.setCharacterEncoding("utf-8"); %>

<%
String[] a = null;
for( int i = 0; i < a.length; i ++ ){ //. ここでぬるぽエラー
}
%>

<html>
<head>
<title>index</title>
</head>
<body>
<h1>Index</h1>

<% exception.printStackTrace(new java.io.PrintWriter(out)); %>


</body>
</html>

この状態で動かしてみます。まず存在しないページの URL を叩くとこんな感じのエラーになります:
2015012706


次に上記で作成したわざと NullPointer エラーがでるページにアクセスするとこんな感じに:
2015012707


できた!