Java ベースの Web アプリケーション アーキテクチャを共有しましょう。
Java を使用して実装される Web アプリケーションには、さまざまなアーキテクチャがあります。この質問に対する回答は、さまざまな Web アプリケーション設計とその長所と短所のライブラリとして役立つ可能性があります。回答は主観的なものになることは承知していますが、できるだけ客観的になり、リストする長所と短所の理由を説明するように努めましょう。
アーキテクチャを説明する際は、お好みの詳細レベルを使用してください。回答に価値を持たせるには、少なくとも、説明するアーキテクチャで使用されている主要なテクノロジーとアイデアを説明する必要があります。最後に、いつあなたのアーキテクチャを使用すべきでしょうか?
始めますよ...
アーキテクチャの概要
当社では、Java EE、Java Persistence API、Servlet、Java Server Pages などの Sun のオープン標準に基づく 3 層アーキテクチャを使用しています。
- 持続性
- 仕事
- プレゼンテーション
レイヤー間の可能な通信フローは次のように表されます。
Persistence <-> Business <-> Presentation
たとえば、プレゼンテーション層は永続化操作を呼び出したり実行したりすることはなく、常にビジネス層を通じて実行されます。このアーキテクチャは、高可用性 Web アプリケーションの要求を満たすことを目的としています。
持続性
作成、読み取り、更新、削除を実行します(CRUD) 永続化操作。このケースでは (Java 永続性 API) JPAであり、現在使用している休止状態永続性プロバイダとして使用しそのEntityManager。
この層は複数のクラスに分かれており、各クラスは特定の種類のエンティティを扱います(例えば、ショッピングカートに関連するエンティティは単一の永続クラスで処理される可能性があります)。使用済みたった一人によってマネージャー。
さらにこのレイヤーにはJPAエンティティなどのAccount
ようなものです。ShoppingCart
仕事
Web アプリケーションの機能に結び付けられたすべてのロジックは、このレイヤーにあります。この機能は、クレジットカードを使用してオンラインで商品の支払いを希望する顧客のために送金を開始することなどです。また、新しいユーザーの作成、ユーザーの削除、Web ベースのゲームでの戦闘の結果の計算などにも使用できます。
このレイヤーは複数のクラスに分かれており、それぞれのクラスには注釈が付けられ@Stateless
、ステートレスセッションBean(SLSB)。各SLSBはマネージャーたとえば、マネージャーは、前述のように注釈が付けられた と呼ばれるクラスになりますAccountManager
。
が CRUD 操作を実行する必要がある場合、AccountManager
は永続化レイヤーのクラスである のインスタンスを適切に呼び出しますAccountManagerPersistence
。 の 2 つのメソッドの大まかな概要は次AccountManager
のようになります。
...
public void makeExpiredAccountsInactive() {
AccountManagerPersistence amp = new AccountManagerPersistence(...)
// Calls persistence layer
List<Account> expiredAccounts = amp.getAllExpiredAccounts();
for(Account account : expiredAccounts) {
this.makeAccountInactive(account)
}
}
public void makeAccountInactive(Account account) {
AccountManagerPersistence amp = new AccountManagerPersistence(...)
account.deactivate();
amp.storeUpdatedAccount(account); // Calls persistence layer
}
を使用しておりますコンテナ マネージャー トランザクションそのため、トランザクションの境界を自分で設定する必要はありません。基本的に、SLSB メソッドに入るときにトランザクションを開始し、メソッドを終了する直前にコミット (またはロールバック) します。これは、設定よりも規約を優先する例ですが、デフォルトの Required 以外のものはまだ必要ありません。
SunのJava EE 5チュートリアルでは、必須のトランザクション属性Enterprise JavaBeans (EJB) の場合:
クライアントがトランザクション内で実行されていて、エンタープライズ Bean のメソッドを呼び出す場合、メソッドはクライアントのトランザクション内で実行されます。クライアントがトランザクションに関連付けられていない場合、コンテナはメソッドを実行する前に新しいトランザクションを開始します。
Required 属性は、コンテナ管理トランザクション境界で実行されるすべてのエンタープライズ Bean メソッドの暗黙的なトランザクション属性です。通常、別のトランザクション属性をオーバーライドする必要がある場合を除き、Required 属性は設定しません。トランザクション属性は宣言型であるため、後で簡単に変更できます。
プレゼンテーション
プレゼンテーション層は、プレゼンテーションを担当しています。ユーザーインターフェイスを担当し、HTMLページを構築し、GETおよびPOSTリクエストを通じてユーザー入力を受け取ることでユーザーに情報を表示します。現在は古いサーブレットの + Java Server Pages (JSP) の組み合わせ。
レイヤーはメソッドを呼び出しますマネージャービジネス層は、ユーザーから要求された操作を実行し、Webページに表示する情報を受け取ります。ビジネス層から受け取る情報は、String
'sやint
egersなどのそれほど複雑ではない型である場合もあれば、JPAエンティティ。
アーキテクチャの長所と短所
長所
- このレイヤーに永続化を行う特定の方法に関連するものがすべて揃っているということは、ビジネス レイヤーで何も書き直すことなく、JPA の使用から他のものに切り替えることができることを意味します。
- プレゼンテーション レイヤーを他のレイヤーに置き換えるのは簡単です。また、より優れたレイヤーが見つかった場合は、そうする可能性もあります。
- EJB コンテナにトランザクション境界を管理させるのは良いことです。
- Servlet + JPA の使用は (そもそも) 簡単で、そのテクノロジは広く使用され、多くのサーバーで実装されています。
- Java EEを使用すると、高可用性システムを簡単に作成できるようになります。負荷分散そしてフェイルオーバーどちらも必要だと私たちは感じています。
短所
- JPA を使用すると、JPA エンティティ クラスのアノテーションを使用して、頻繁に使用されるクエリを名前付きクエリとして保存できます
@NamedQuery
。私たちのアーキテクチャのように、永続性クラスに永続性に関連するものをできるだけ多く含めると、クエリを見つける場所が広がり、JPA エンティティも含まれるようになります。永続性操作の概要を把握することが難しくなり、保守が難しくなります。 - 永続化レイヤーの一部として JPA エンティティがあります。しかし、
Account
とShoppingCart
は実際にはビジネス オブジェクトではないのでしょうか? これらのクラスにアクセスして、JPA が処理できるエンティティに変換する必要があるため、このように実行されます。 - JPAエンティティはビジネスオブジェクトでもあり、データ転送オブジェクト(個人情報's(値オブジェクト(VO)とも呼ばれる)です。これにより、貧血領域モデルビジネス オブジェクトには、アクセサ メソッド以外の独自のロジックはありません。すべてのロジックはビジネス レイヤーでマネージャによって実行されるため、より手続き型のプログラミング スタイルになります。これは優れたオブジェクト指向設計ではありませんが、おそらく問題ではないでしょうか。(結局のところ、オブジェクト指向は、成果を上げている唯一のプログラミング パラダイムではありません。)
- EJBとJava EEを使用すると、少し複雑になります。また、Tomcatのみを使用することはできません(EJBマイクロコンテナを追加するのは純粋にトムキャット)。
- Servlet + JPA の使用には多くの問題があります。これらの問題の詳細については、Google を使用してください。
- ビジネス層から出るときにトランザクションが閉じられるため、
fetch=FetchType.LAZY
プレゼンテーション層内から必要なときにデータベースからロードするように構成されている JPA エンティティから情報をロードすることはできません ( を使用)。例外が発生します。これらの種類のフィールドを含むエンティティを返す前に、関連するゲッターを呼び出す必要があります。別のオプションは、Java Persistence Query Language (JPQL) を実行して を実行しますFETCH JOIN
。ただし、これらのオプションはどちらも少し面倒です。
ベストアンサー1
わかりました。(もっと短い)ものをやります:
- フロントエンド :タペストリー(古いプロジェクトの場合は 3、新しいプロジェクトの場合は 5)
- ビジネスレイヤー: Spring
- DAO: Ibatis
- データベース: Oracle
私たちは Sping トランザクション サポートを使用し、サービス レイヤーに入るとトランザクションを開始し、DAO 呼び出しまで伝播します。サービス レイヤーには最も多くのビジネス モデル知識があり、DAO は比較的単純な CRUD 作業を実行します。
パフォーマンス上の理由から、より複雑なクエリの一部は、バックエンドでより複雑なクエリによって処理されます。
この場合、Spring を使用する利点は、Spring Proxy クラスの背後にある国/言語依存のインスタンスを使用できることです。セッション内のユーザーに基づいて、呼び出し時に適切な国/言語の実装が使用されます。
トランザクション管理はほぼ透過的で、実行時例外でロールバックします。可能な限り、非チェック例外を使用します。以前はチェック例外を使用していましたが、Spring の導入により、非チェック例外の利点がわかりました。非チェック例外は可能な場合にのみ例外を処理します。これにより、多くの定型的な「catch/rethrow」または「throws」を回避できます。
あなたの投稿より短くて申し訳ありませんが、これが興味深いと思っていただければ幸いです...