Web ベース アプリケーションのデザイン パターン [closed] 質問する

Web ベース アプリケーションのデザイン パターン [closed] 質問する

私はシンプルな Web ベースのアプリケーションを設計しています。この Web ベースの分野は初心者です。サーブレット間で責任をどのように分散するか、新しいサーブレットを作成する基準など、設計パターンに関してアドバイスが必要です。

実際、私のホームページにはいくつかのエンティティがあり、それぞれに対応して、追加、編集、削除などのオプションがいくつかあります。以前は、エンティティ 1 の追加には Servlet1、エンティティ 1 の編集には Servlet2 というように、オプションごとに 1 つのサーブレットを使用していましたが、この方法では、多数のサーブレットが存在することになりました。

現在、設計を変更しています。質問は、サーブレットの役割をどのように選択するかということです。エンティティごとに 1 つのサーブレットを用意し、すべてのオプションを処理してリクエストをサービス レイヤーに転送する必要がありますか。それとも、ページ全体に 1 つのサーブレットを用意し、ページ全体のリクエストを処理してから、対応するサービス レイヤーに転送する必要がありますか。また、リクエスト オブジェクトをサービス レイヤーに転送するかどうかも教えてください。

ベストアンサー1

ある程度まともな Web アプリケーションは、さまざまなデザイン パターンの組み合わせで構成されています。ここでは最も重要なものだけを挙げます。


モデルビューコントローラパターン

使用したいコア(アーキテクチャ)デザインパターンはモデル-ビュー-コントローラパターンコントローラー、リクエストに基づいて特定のモデルビューを直接 (間接的に) 作成/使用するサーブレットによって表されます。モデルはJavabean クラスによって表されます。これは、アクション (動作) を含むビジネス モデルとデータ (情報) を含むデータ モデルにさらに分割できる場合がよくあります。ビューは、EL (式言語) によって(データ)モデルに直接アクセスできる JSP ファイルによって表されます。

さらに、アクションとイベントの処理方法に基づいたバリエーションがあります。一般的なものは次のとおりです。

  • リクエスト(アクション)ベースのMVC:これは実装が最も簡単です。(ビジネスモデルはオブジェクトと直接連携します。リクエストパラメータを(ほとんど)自分で収集、変換、検証する必要があります。HttpServletRequestビューはプレーンなHTML / CSS / JSで表現でき、リクエスト間で状態を維持しません。これは、他の方法の中でもHttpServletResponseスプリングMVCストラットそしてストライプ動作します。

  • コンポーネント ベースの MVC : これは実装が困難です。しかし、すべての「生の」サーブレット API が完全に抽象化された、よりシンプルなモデルとビューが得られます。リクエスト パラメータを自分で収集、変換、検証する必要はありません。コントローラーがこのタスクを実行し、収集、変換、検証されたリクエスト パラメータをモデルに設定します必要なのは、モデル プロパティと直接連携するアクション メソッドを定義することだけです。ビューは、JSP タグライブラリまたは XML 要素のフレーバーの「コンポーネント」によって表され、HTML/CSS/JS が生成されます。後続のリクエストのビューの状態はセッションで維持されます。これは、サーバー側の変換、検証、値変更イベントに特に役立ちます。これは、他の方法の中でも、JSFウィケットそして遊ぶ!動作します。

余談ですが、自作の MVC フレームワークを趣味として試してみるのは非常に良い学習方法であり、個人的/プライベートな目的に留める限りはお勧めします。しかし、プロになったら、独自のフレームワークを作り直すのではなく、既存のフレームワークを選択することを強くお勧めします。既存のよく開発されたフレームワークを学ぶ方が、堅牢なフレームワークを自分で開発して維持するよりも長期的には時間がかかりません。

以下の詳細な説明では、実装が簡単なため、リクエスト ベースの MVC に限定します。


フロントコントローラーパターンメディエーターパターン

まず、コントローラ部分はフロントコントローラーパターン(これは特殊な種類のメディエーターパターン) は、すべてのリクエストの集中エントリ ポイントを提供する単一のサーブレットのみで構成されます。パス情報やサーブレット パス、メソッド、および/または特定のパラメータなど、リクエストで利用可能な情報に基づいてモデルを作成する必要があります。ビジネス モデルはAction、以下で呼び出されます。HttpServlet例。

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
        Action action = ActionFactory.getAction(request);
        String view = action.execute(request, response);

        if (view.equals(request.getPathInfo().substring(1)) {
            request.getRequestDispatcher("/WEB-INF/" + view + ".jsp").forward(request, response);
        }
        else {
            response.sendRedirect(view); // We'd like to fire redirect in case of a view change as result of the action (PRG pattern).
        }
    }
    catch (Exception e) {
        throw new ServletException("Executing action failed.", e);
    }
}

アクションを実行すると、ビューを見つけるための識別子が返されます。最も簡単な方法は、それを JSP のファイル名として使用することです。このサーブレットを、またはなどの特定url-patternのにマップします。web.xml/pages/**.do*.html

例えばプレフィックスパターンの場合、/pages/*次のようなURLを呼び出すことができます。http://example.com/pages/registerhttp://example.com/pages/ログイン、などを提供し/WEB-INF/register.jsp、適切なGETおよびPOSTアクションを提供します。その後、、、などの/WEB-INF/login.jsp部分はregisterloginrequest.getPathInfo()上記の例のように。

*.do、などのサフィックスパターンを使用している場合は*.html、次のようなURLを呼び出すことができます。http://example.com/register.dohttp://example.com/login.doなどがあり、この回答のコード例(および)を変更して、および部分をActionFactory抽出する必要があります。registerloginrequest.getServletPath()その代わり。


戦略パターン

Action戦略パターン抽象メソッドに渡された引数に基づいて作業を行う抽象/インターフェース型として定義する必要があります(これがコマンドパターン、抽象/インターフェース型は、実装の作成中に渡された引数に基づいて作業を行う必要があります。

public interface Action {
    public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception;
}

Exceptionのようなカスタム例外を使用して、 をより具体的にすることもできますActionException。 これは単なる基本的なキックオフの例であり、残りはすべてあなた次第です。

LoginActionこれは、(名前の通り) ユーザーをログインさせるの例です。 自体は、データ モデルUserです。ビューはの存在を認識します。User

public class LoginAction implements Action {

    public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        User user = userDAO.find(username, password);

        if (user != null) {
            request.getSession().setAttribute("user", user); // Login user.
            return "home"; // Redirect to home page.
        }
        else {
            request.setAttribute("error", "Unknown username/password. Please retry."); // Store error message in request scope.
            return "login"; // Go back to redisplay login form with error.
        }
    }

}

ファクトリーメソッドパターン

ActionFactoryファクトリーメソッドパターン基本的に、抽象/インターフェース型の具体的な実装を返す作成メソッドを提供する必要があります。この場合、リクエストによって提供された情報に基づいてインターフェースの実装を返す必要がありますAction。たとえば、方法そしてパス情報(pathinfo は、リクエスト URL 内のコンテキストとサーブレット パスの後の部分で、クエリ文字列は除きます)。

public static Action getAction(HttpServletRequest request) {
    return actions.get(request.getMethod() + request.getPathInfo());
}

今度actionsは、すべての既知のアクションを保持する静的/アプリケーション全体のマップが必要ですMap<String, Action>。このマップをどのように埋めるかはあなた次第です。ハードコーディング:

actions.put("POST/register", new RegisterAction());
actions.put("POST/login", new LoginAction());
actions.put("GET/logout", new LogoutAction());
// ...

または、クラスパス内のプロパティ/XML 構成ファイルに基づいて構成可能: (疑似)

for (Entry entry : configuration) {
    actions.put(entry.getKey(), Class.forName(entry.getValue()).newInstance());
}

または、クラスパス内の特定のインターフェースやアノテーションを実装するクラスをスキャンして動的に検索する: (疑似)

for (ClassFile classFile : classpath) {
    if (classFile.isInstanceOf(Action.class)) {
       actions.put(classFile.getAnnotation("mapping"), classFile.newInstance());
    }
}

マッピングがない場合には、 「何もしない」を作成することを忘れないでくださいAction。たとえば、request.getPathInfo().substring(1)then を直接返すようにします。


その他のパタ​​ーン

ここまでが重要なパターンでした。

さらに一歩進むには、ファサードパターンContextリクエストとレスポンスオブジェクトをラップし、リクエストとレスポンスオブジェクトに委譲する便利なメソッドをいくつか提供するクラスを作成し、代わりにメソッドに引数として渡します。これにより、生のサーブレットAPIを隠すための抽象レイヤーが追加されます。基本的に、すべての実装で宣言がゼロAction#execute()になります。JSFの用語では、これが import javax.servlet.*ActionFacesContextそしてExternalContextクラスが何をしているか。具体的な例はこの答え

そして、状態パターンリクエストパラメータの収集、変換、検証、モデル値の更新、アクションの実行といったタスクを分割するために、追加の抽象化レイヤーを追加したい場合。JSFの用語では、これはLifeCycleやっている。

そして、複合パターンモデルに添付でき、その動作がリクエストベースのライフサイクルの状態に依存するコンポーネントベースのビューを作成したい場合。JSFの用語では、これはUIComponent代表する。

この方法で、コンポーネント ベースのフレームワークに向けて少しずつ進化することができます。


参照:

おすすめ記事