“サーブレットの例外とエラー処理チュートリアル”

今日はServletの例外とエラーハンドリングについて見ていきます。以前にJavaの例外処理について投稿しましたが、ウェブアプリケーションでは通常のJavaの例外処理以上のものが必要です。

サーブレット例外

もし注意してみると、doGet()とdoPost()メソッドはjavax.servlet.ServletExceptionとIOExceptionをスローします。アプリケーションからこれらの例外をスローしたときに何が起こるか見てみましょう。私はServletExceptionをスローするシンプルなサーブレットを書きます。

package com.scdev.servlet.exception;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/MyExceptionServlet")
public class MyExceptionServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		throw new ServletException("GET method is not supported.");
	}

}

ブラウザを使用してこのサーブレットをGETメソッドで呼び出すと、以下の画像のような応答が得られます。ブラウザはHTMLのみを理解するため、アプリケーションが例外を発生させると、サーブレットコンテナが例外を処理し、HTMLの応答を生成します。このロジックはサーブレットコンテナに固有です。私はTomcatを使用しており、このエラーページが表示されています。JBossやGlassfishなどの他のサーバーを使用すると、異なるエラーHTML応答が表示される可能性があります。この応答の問題は、ユーザーにとって価値がないことです。また、ユーザーには私たちのアプリケーションクラスやサーバーの詳細が表示され、ユーザーにとって理解できず、セキュリティ上の問題ともなります。

サーブレットエラー

URLが存在しない場合、404エラーを見たことがあると思います。サーブレットコンテナが404エラーにどのように応答するか見てみましょう。無効なURLに対してリクエストを送信すると、下の画像のような応答HTMLを受け取ります。再び、これは私たちのアプリケーションの代理としてサーバーによって生成される一般的なHTMLであり、ユーザーにはほとんど価値がありません。

サーブレットの例外とエラー処理

セルフレットAPIは、デプロイメント記述子で構成できるカスタムの例外およびエラーハンドラーサーブレットのサポートを提供します。これらのサーブレットの目的は、アプリケーションによって発生した例外やエラーを処理し、ユーザーに有用なHTML応答を送信することです。アプリケーションのホームページへのリンクや問題の内容をユーザーに知らせるための詳細を提供することができます。まず最初に、カスタムの例外およびエラーハンドラーサーブレットを作成する必要があります。アプリケーションには複数の例外およびエラーハンドラーサーブレットを持つことができますが、簡単さのために、単一のサーブレットを作成し、例外とエラーの両方に使用します。AppExceptionHandler.javaを作成します。

package com.scdev.servlet.exception;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/AppExceptionHandler")
public class AppExceptionHandler extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		processError(request, response);
	}

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		processError(request, response);
	}

	private void processError(HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		// Analyze the servlet exception
		Throwable throwable = (Throwable) request
				.getAttribute("javax.servlet.error.exception");
		Integer statusCode = (Integer) request
				.getAttribute("javax.servlet.error.status_code");
		String servletName = (String) request
				.getAttribute("javax.servlet.error.servlet_name");
		if (servletName == null) {
			servletName = "Unknown";
		}
		String requestUri = (String) request
				.getAttribute("javax.servlet.error.request_uri");
		if (requestUri == null) {
			requestUri = "Unknown";
		}
		
		// Set response content type
	      response.setContentType("text/html");
	 
	      PrintWriter out = response.getWriter();
	      out.write("<html><head><title>Exception/Error Details</title></head><body>");
	      if(statusCode != 500){
	    	  out.write("<h3>Error Details</h3>");
	    	  out.write("<strong>Status Code</strong>:"+statusCode+"<br>");
	    	  out.write("<strong>Requested URI</strong>:"+requestUri);
	      }else{
	    	  out.write("<h3>Exception Details</h3>");
	    	  out.write("<ul><li>Servlet Name:"+servletName+"</li>");
	    	  out.write("<li>Exception Name:"+throwable.getClass().getName()+"</li>");
	    	  out.write("<li>Requested URI:"+requestUri+"</li>");
	    	  out.write("<li>Exception Message:"+throwable.getMessage()+"</li>");
	    	  out.write("</ul>");
	      }
	      
	      out.write("<br><br>");
	      out.write("<a href=\"index.html\">Home Page</a>");
	      out.write("</body></html>");
	}
}

デプロイメント記述子でどのように設定できるかを見てみましょう。それから実装方法と動作原理が理解できるでしょう。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  <display-name>ServletExceptionHandling</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
  
  <error-page>
  	<error-code>404</error-code>
  	<location>/AppExceptionHandler</location>
  </error-page>
  
  <error-page>
  <exception-type>javax.servlet.ServletException</exception-type>
  <location>/AppExceptionHandler</location>
  </error-page>
</web-app>

見ての通り、エラーページ要素を使用してアプリケーションの例外ハンドラーサーブレットを指定することは非常に簡単です。各エラーページ要素には、error-code要素またはexception-type要素のいずれかが必要です。例外ハンドラーサーブレットはlocation要素で定義します。上記の設定に基づいて、アプリケーションが404エラーやServletExceptionをスローする場合は、AppExceptionHandlerサーブレットで処理されます。このような例外やエラーシナリオが発生すると、サーブレットコンテナは例外ハンドラーサーブレットの対応するHTTPメソッドを呼び出し、リクエストとレスポンスオブジェクトを渡します。例外を処理するためにサーブレットコンテナがサーブレットを呼び出す前に、リクエストには例外に関する有用な情報を取得するためのいくつかの属性が設定されます。その中にはjavax.servlet.error.exception、javax.servlet.error.status_code、javax.servlet.error.servlet_name、javax.servlet.error.request_uriなどがあります。例外の場合、ステータスコードは常に「500 Internal Server Error」に対応しており、その他の種類のエラーには404、403などの異なるエラーコードが得られます。ステータスコードを使用して、私たちの実装ではユーザーに異なるタイプのHTMLレスポンスを表示します。また、アプリケーションのホームページへのハイパーリンクも提供します。そして、ServletExceptionをスローしているサーブレットにアクセスすると、下の画像のような応答を得ることができます。無効なURLにアクセスしようとすると、404応答を受け取ることができます。見た目も良く、ユーザーが何が起こったかを簡単に理解できるようになっており、正しい場所に移動する方法も提供しています。さらに、アプリケーションに関する機密情報をユーザーに送信しないようになっています。常にウェブアプリケーションに例外ハンドラーを用意するべきです。ランタイム例外とその他の例外を単一の例外ハンドラーで処理したい場合は、exception-typeとしてThrowableを指定することができます。

<error-page>
  <exception-type>java.lang.Throwable</exception-type>
  <location>/AppExceptionHandler</location>
</error-page>

もし複数のエラーページエントリがある場合、例えばThrowable用とIOException用の2つがあり、アプリケーションがFileNotFoundExceptionをスローする場合、それはIOExceptionのエラーハンドラによって処理されます。また、例外ハンドラとしてJSPページを使用することもできます。サーブレットマッピングではなく、JSPファイルの場所を指定するだけです。これにて、ウェブアプリケーションにおけるサーブレット例外のハンドリングは以上です。お楽しみいただければ幸いです。

「ダウンロードServlet例外処理のサンプルプロジェクトをダウンロードしてください。」

このシリーズの他の記事もぜひご覧ください。

    1. Javaのウェブアプリケーション

 

    1. Javaのサーブレットチュートリアル

 

    1. Javaにおけるセッション管理

 

    1. サーブレットフィルター

 

    1. サーブレットリスナー

 

    1. サーブレットにおけるクッキー

 

    サーブレットファイルのアップロードとダウンロードの例
コメントを残す 0

Your email address will not be published. Required fields are marked *