Front Controller パターン

このセクションでは、 「パターンテンプレート」 で定義されている形式の Front Controller デザインパターンについて説明します。

問題

デザインが不適切な多くの Web アプリケーションでは、クライアントはビューに直接アクセスします。その結果、Web アプリケーションにおけるアクセス制御または他の管理機能を実装することが困難になります。該当するターゲットリソースにリクエストを転送するアプリケーションの場合、しばしばフロントエンドを実装する必要があります。

ビューには、次のようなシステムサービスを提供するロジックが含まれている場合があります。

したがって、アプリケーションのコードが分散または重複して、保守が困難になります。ビジネスロジックとプレゼンテーションロジックの分離が困難であるということも問題となります。これについては、 「View Helper パターン」 で説明しています。

次の図に、別個のコンポーネントとして理想的に実装されるビジネスロジックが含まれている各コンポーネントを示します。

これは、クライアントが、ビジネスロジックとプレゼンテーションロジックがすべて含まれている複数のページに対するリクエストを行っているイメージを示しています。

解決策

Front Controller パターンは、同じコンポーネントにおいて、プレゼンテーションロジックからビジネスロジックを強制的に分離します。このパターンでは、すべてのリクエストの最初のアクセスポイントとしてコントローラを使用します。コントローラは、リクエストにおける次の側面を処理します。

システムサービスの仕事をコントローラに肩代わりさせることによって、Front Controller パターンは、プレゼンテーションおよびモデルの処理をターゲットリソースに渡します。

アプリケーションでは、サービスの個々のセットを呼び出すことによって複数のコントローラを使用できます。

次の図に、さまざまなプレゼンテーション層のコンポーネントにリクエストを転送するコントローラを示します。

これは、クライアントが複数のページへのリクエストを行っているイメージを示しています。各リクエストはコントローラによって阻止されます。阻止されたリクエストは、プレゼンテーションロジックだけが含まれている該当ページに送られます。

ビジネスロジックの実装を支援する追加コードがコントローラに含まれている場合、パターンは、Service to Worker パターンと類似したものになります。詳細については、 「Service to Worker パターン」 を参照してください。

戦略

Front Controller パターンを実装する場合は、JSP にリクエストを送信するフィルタまたはサーブレットのチェーンとして実装する方法をお勧めします。コントローラ内で論理リソースマッピングを使用するか、設定ファイル内でリソースマッピングを定義してください。

パターンを実行するには、JSP を /WEB-INF ディレクトリに配置してください。クライアントはそのディレクトリ内のリソースを直接リクエストできないため、サーブレットまたは他の Web コンポーネントがコントローラとして機能し、リクエストをこの JSP に送信する必要があります。

Front Controller サーブレットのサンプル

次は、コントローラ実装のサンプルコードです。サーブレットの doGet および doPost メソッドはいずれも processRequest メソッドを呼び出します。processRequest で、このコントローラは、リクエストパラメータを抽出し、その値を転送先として使用します。

public class Controller extends HttpServlet {
 protected void processRequest(HttpServletRequest req, 
HttpServletResponse res throws ServletException, 
java.io.IOException {
  page = req.getParameter("page");
  RequestDispatcher dispatcher = 
getServletContext().getRequestDispatcher(page);
  dispatcher.forward(req, res);
 }
  protected void doGet(HttpServletRequest req, HttpServletResponse 
res) 
  throws ServletException, java.io.IOException {
  processRequest(req, res);
 }
 protected void doPost(HttpServletRequest req, HttpServletResponse 
res) throws ServletException, java.io.IOException {
  processRequest(req, res);
 }
}