Java EE Web関連アノテーションの手引き

1. 概要

Java EEアノテーションを使用すると、アプリケーションコンポーネントがコンテナ内でどのように動作するかを指定できるため、開発者の作業が楽になります。 これらはXML記述子の最新の代替手段であり、基本的に、定型コードを回避することを可能にします。

この記事では、Java EE7のサーブレットAPI3.1で導入されたアノテーションに焦点を当てます。 それらの目的を調べ、その使用法を見ていきます。

2. Web注釈

サーブレットAPI3.1では、Servletクラスで使用できる新しいアノテーションタイプのセットが導入されました。

  • @WebServlet

  • @WebInitParam

  • @WebFilter

  • @WebListener

  • @ServletSecurity

  • @HttpConstraint

  • @HttpMethodConstraint

  • @MultipartConfig

これらについては、次のセクションで詳しく説明します。

3. @WebServlet

簡単に言えば、このアノテーションにより、Javaクラスをサーブレットとして宣言できます:

@WebServlet("/account")
public class AccountServlet extends javax.servlet.http.HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws IOException {
        // ...
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws IOException {
        // ...
    }
}

3.1. @WebServletアノテーションの属性の使用

@WebServletには、サーブレットをカスタマイズできる一連の属性があります。

  • name

  • 説明

  • urlPatterns

  • initParams

以下の例に示すようにこれらを使用できます。

@WebServlet(
  name = "BankAccountServlet",
  description = "Represents a Bank Account and it's transactions",
  urlPatterns = {"/account", "/bankAccount" },
  initParams = { @WebInitParam(name = "type", value = "savings")})
public class AccountServlet extends javax.servlet.http.HttpServlet {

    String accountType = null;

    public void init(ServletConfig config) throws ServletException {
        // ...
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws IOException {
        // ...
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws IOException {
        // ...
    }
}

name属性は、デフォルトで完全修飾クラス名であるデフォルトのサーブレット名をオーバーライドします。 サーブレットの機能の説明を提供する場合は、description属性を使用できます。

urlPatterns属性は、サーブレットを使用できるURLを指定するために使用されます(コード例に示すように、この属性に複数の値を指定できます)。

4. @WebInitParam

このアノテーションは、@WebServletアノテーションのinitParams属性およびサーブレットの初期化パラメータとともに使用されます。

この例では、サーブレット初期化パラメータtypeを「savings」の値に設定します。

@WebServlet(
  name = "BankAccountServlet",
  description = "Represents a Bank Account and it's transactions",
  urlPatterns = {"/account", "/bankAccount" },
  initParams = { @WebInitParam(name = "type", value = "savings")})
public class AccountServlet extends javax.servlet.http.HttpServlet {

    String accountType = null;

    public void init(ServletConfig config) throws ServletException {
        accountType = config.getInitParameter("type");
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws IOException {
        // ...
    }
}

5. @WebFilter

内部ロジックに触れずにサーブレットの要求と応答を変更したい場合は、WebFilterアノテーションを使用できます。 URLパターンを指定して、フィルターをサーブレットまたはサーブレットと静的コンテンツのグループに関連付けることができます。

以下の例では、@WebFilterアノテーションを使用して、不正アクセスをログインページにリダイレクトしています。

@WebFilter(
  urlPatterns = "/account/*",
  filterName = "LoggingFilter",
  description = "Filter all account transaction URLs")
public class LogInFilter implements javax.servlet.Filter {

    public void init(FilterConfig filterConfig) throws ServletException {
    }

    public void doFilter(
        ServletRequest request, ServletResponse response, FilterChain chain)
          throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;

        res.sendRedirect(req.getContextPath() + "/login.jsp");
        chain.doFilter(request, response);
    }

    public void destroy() {
    }

}

6. @WebListener

サーブレットとそのリクエストを初期化または変更する方法とタイミングについての知識や制御が必要な場合は、@WebListenerアノテーションを使用できます。

Webリスナーを作成するには、次のインターフェイスの1つ以上を拡張する必要があります。

  • ServletContextのライフサイクルに関するServletContextListener – forの通知

  • ServletContext属性が変更されたときのServletContextAttributeListener – for通知

  • リソースのリクエストが行われるたびにServletRequestListener – for通知

  • ServletRequestで属性が追加、削除、または変更されたときのServletRequestAttributeListener – for通知

  • 新しいセッションが作成および破棄されたときのHttpSessionListener – for通知

  • 新しい属性がセッションに追加またはセッションから削除されたときのHttpSessionAttributeListener – for通知

以下は、ServletContextListenerを使用してWebアプリケーションを構成する方法の例です。

@WebListener
public class BankAppServletContextListener
  implements ServletContextListener {

    public void contextInitialized(ServletContextEvent sce) {
        sce.getServletContext().setAttribute("ATTR_DEFAULT_LANGUAGE", "english");
    }

    public void contextDestroyed(ServletContextEvent sce) {
        // ...
    }
}

7. @ServletSecurity

ロール、アクセス制御、認証要件など、サーブレットのセキュリティモデルを指定する場合は、注釈@ServletSecurityを使用します。

この例では、@ServletSecurityアノテーションを使用してAccountServletへのアクセスを制限します。

@WebServlet(
  name = "BankAccountServlet",
  description = "Represents a Bank Account and it's transactions",
  urlPatterns = {"/account", "/bankAccount" },
  initParams = { @WebInitParam(name = "type", value = "savings")})
@ServletSecurity(
  value = @HttpConstraint(rolesAllowed = {"Member"}),
  httpMethodConstraints = {@HttpMethodConstraint(value = "POST", rolesAllowed = {"Admin"})})
public class AccountServlet extends javax.servlet.http.HttpServlet {

    String accountType = null;

    public void init(ServletConfig config) throws ServletException {
        // ...
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws IOException {
       // ...
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws IOException {
        double accountBalance = 1000d;

        String paramDepositAmt = request.getParameter("dep");
        double depositAmt = Double.parseDouble(paramDepositAmt);
        accountBalance = accountBalance + depositAmt;

        PrintWriter writer = response.getWriter();
        writer.println(" Balance of " + accountType + " account is: " + accountBalance
        + "");
        writer.flush();
    }
}

この場合、AccountServlet,を呼び出すと、ブラウザはユーザーが有効なユーザー名とパスワードを入力するためのログイン画面をポップアップします。

@HttpConstraintおよび@HttpMethodConstraintアノテーションを使用して、@ServletSecurityアノテーションの属性valueおよびhttpMethodConstraints,の値を指定できます。

@HttpConstraintアノテーションはすべてのHTTPメソッドに適用されます。 つまり、デフォルトのセキュリティ制約を指定します。

@HttpConstraintには3つの属性があります。

  • 許可されたroles

  • transportGuarantee

これらの属性のうち、最も一般的に使用される属性はrolesAllowedです。 上記のサンプルコードスニペットでは、ロールMemberに属するユーザーは、すべてのHTTPメソッドを呼び出すことができます。

@HttpMethodConstraintアノテーションを使用すると、特定のHTTPメソッドのセキュリティ制約を指定できます。

@HttpMethodConstraintには次の属性があります。

  • emptyRoleSemantic

  • 許可されたroles

  • transportGuarantee

上記のサンプルコードスニペットでは、doPostメソッドがAdminロールに属するユーザーに対してのみ制限され、デポジット機能をAdminユーザーのみが実行できるようにする方法を示しています。

8. @MultipartConfig

このアノテーションは、multipart/form-dataリクエストを処理するためにサーブレットにアノテーションを付ける必要がある場合に使用されます(通常、ファイルアップロードサーブレットに使用されます)。

これにより、HttpServletRequestgetParts()メソッドとgetPart(name)メソッドが公開され、個々のパーツだけでなくすべてのパーツにアクセスできます。

アップロードされたファイルは、Partオブジェクトのwrite(fileName)を呼び出すことでディスクに書き込むことができます。

次に、その使用法を示すサーブレットUploadCustomerDocumentsServletの例を見ていきます。

@WebServlet(urlPatterns = { "/uploadCustDocs" })
@MultipartConfig(
  fileSizeThreshold = 1024 * 1024 * 20,
  maxFileSize = 1024 * 1024 * 20,
  maxRequestSize = 1024 * 1024 * 25,
  location = "./custDocs")
public class UploadCustomerDocumentsServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
        for (Part part : request.getParts()) {
            part.write("myFile");
        }
    }

}

@MultipartConfigには4つの属性があります。

  • fileSizeThreshold –これはアップロードされたファイルを一時的に保存するときのサイズのしきい値です。 アップロードされたファイルのサイズがこのしきい値よりも大きい場合、ディスクに保存されます。 それ以外の場合、ファイルはメモリに保存されます(バイト単位のサイズ)

  • maxFileSize –これはアップロードされたファイルの最大サイズ(バイト単位のサイズ)です

  • maxRequestSize –これは、アップロードされたファイルと他のフォームデータ(バイト単位のサイズ)の両方を含む、リクエストの最大サイズです。

  • location –アップロードされたファイルが保存されるディレクトリです

9. 結論

この記事では、Servlet API 3.1で導入されたいくつかのJava EEアノテーションと、それらの目的と使用法について説明しました。

この記事に関連するソースコードはover on GitHubにあります。