1. ホーム
  2. java

[解決済み] Java Webアプリケーションに使用するアーキテクチャを説明してください。[クローズド]

2022-05-08 08:48:52

質問内容

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 .

この層は複数のクラスに分かれており、各クラスは特定のタイプのエンティティを扱い(例えば、ショッピングカートに関連するエンティティは、単一の永続化クラスで処理されるかもしれません)、以下のようになります。 使用 によって、たった1つの 管理者 .

さらに、このレイヤーには JPAエンティティ のようなものです。 Account , ShoppingCart などです。

事業内容

Webアプリケーションの機能に関連するすべてのロジックはこのレイヤーに配置されます。この機能は、クレジットカードを使用してオンラインで商品代金を支払おうとする顧客のために送金を開始することもできます。また、新しいユーザーを作成したり、ユーザーを削除したり、ウェブベースのゲームでの戦いの結果を計算したりすることもできます。

このレイヤーは複数のクラスに分割され、それぞれのクラスはアノテーションとして @Stateless になるように ステートレスセッションビーン (SLSB)を使用します。各SLSBは マネージャー というアノテーションが付けられたクラスがあり、例えば、マネージャーは AccountManager .

いつ AccountManager のインスタンスに適切な呼び出しを行い、CRUD 操作を実行する必要があります。 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のThe Java EE 5 Tutorialでは、次のように説明されています。 必須トランザクション属性 Enterprise JavaBeans (EJB)のためのものです。

クライアントが トランザクションを実行し、エンタープライズ ビーンのメソッドが実行されます。 は、クライアントのトランザクション内で使用されます。もし クライアントが トランザクションを開始し、コンテナは を実行する前に新しいトランザクションを メソッドを使用します。

Required属性は、暗黙のうちに トランザクション属性は、すべての で実行されるエンタプライズビーンのメソッドは コンテナ管理型トランザクション の区切りです。通常 Required属性は 他のトランザクションをオーバーライドする 属性があります。トランザクション 属性は宣言的であるため 後で簡単に変更することができます。

プレゼンテーション

プレゼンテーション層が担当するのは...プレゼンテーション!?ユーザーインターフェイスを担当し、HTMLページを構築し、GETやPOSTリクエストを通じてユーザーの入力を受け取ることによって、ユーザーに情報を表示します。現在、私たちは古い サーブレット 'の+Javaサーバーページ( JSP )の組み合わせになります。

このレイヤーは マネージャー は、ユーザーから要求された操作を実行したり、ウェブページに表示する情報を受け取ったりするために、ビジネスレイヤーの ビジネス層から受け取る情報は、あまり複雑ではない String 'sと int を、またある時は JPAエンティティ .

アーキテクチャの長所と短所

長所

  • この層には、特定の永続化の方法に関連するものすべてがあります。つまり、ビジネス層で何かを書き直すことなく、JPAから他のものに変更することができます。
  • プレゼンテーション層を他のものに置き換えるのは簡単だし、より良いものが見つかればそうする可能性もある。
  • EJBコンテナにトランザクションの境界を管理させるのはいいことだ。
  • サーブレットとJPAを使うのは簡単で(そもそも)、この技術は広く使われており、多くのサーバーに実装されている。
  • Java EEを使用することで、以下のような高可用性システムを容易に構築することができるとされています。 ロードバランシング フェイルオーバー . どちらも必要だと感じています。

短所

  • JPA を使用すると、よく使うクエリを名前付きクエリとして保存することができます。 @NamedQuery アノテーションを使用します。私たちのアーキテクチャのように、永続化に関連するものをできるだけ永続化クラスの中に入れてしまうと、クエリを見つける場所がJPAエンティティも含めて分散してしまうことになります。永続化操作を概観しにくくなるので、保守が大変になります。
  • 私たちは、JPAエンティティを永続化レイヤーの一部として持っています。しかし AccountShoppingCart ということですが、これらは本当にビジネス・オブジェクトなのでしょうか?これらのクラスに触れて、JPAが処理する方法を知っているエンティティに変換する必要があるため、この方法で行われます。
  • ビジネスオブジェクトでもあるJPAエンティティは、Data Transfer Objects ( DTO 's)、バリューオブジェクト(VO)とも呼ばれる。この結果 貧弱なドメインモデル ビジネス・オブジェクトは、アクセサー・メソッドを除いて、それ自身のロジックを持たないからです。すべてのロジックはビジネス・レイヤーのマネージャが行うので、より手続き的なプログラミング・スタイルになります。これは良いオブジェクト指向設計とは言えませんが、多分問題ないでしょう?(結局のところ、オブジェクト指向だけが結果を出してきたプログラミングパラダイムではないのです)。
  • EJBとJava EEを使用すると、少し複雑さが生じます。そして、純粋にTomcatだけを使うことはできません(EJBのマイクロコンテナを追加することは 純粋に Tomcat)。
  • サーブレット+JPAの利用には、いろいろと問題があります。これらの問題の詳細については、Googleを使用してください。
  • ビジネス層から抜けるとトランザクションが閉じてしまうので、必要なときにデータベースから読み込むように設定されているJPAエンティティから情報を読み込むことができません( fetch=FetchType.LAZY ) をプレゼンテーション層内部から削除してください。これは例外を引き起こします。この種のフィールドを含むエンティティを返す前に、関連するゲッターを呼び出すことを確認する必要があります。もう1つの方法は、Java Persistence Query Language (Java持続性クエリ言語) を使うことです。 JPQL を実行し FETCH JOIN . しかし、どちらも少々面倒な方法です。

解決方法は?

わかりました......(もっと)短いのをやります。

  • フロントエンド : タペストリー (古いプロジェクトは3、新しいプロジェクトは5)
  • ビジネス層。スプリング
  • DAO : Ibatis
  • データベース:オラクル

Spingのトランザクションサポートを利用しており、サービスレイヤーに入るとトランザクションが開始され、DAOの呼び出しに伝搬していきます。サービスレイヤーは最もビジネスモデルに関する知識を持ち、DAOは比較的単純なCRUD作業を行います。

パフォーマンス上の理由から、より複雑なクエリについては、バックエンドで処理されます。

Springを使う利点は、国や言語に依存したインスタンスをSpring Proxyクラスの後ろに置くことができることです。セッション内のユーザーに基づいて、呼び出しの際に正しい国や言語の実装が使用されます。

トランザクション管理はほぼ透過的で、実行時例外処理でロールバックします。例外処理はできるだけチェックしないものを使用しています。以前はチェックされた例外処理をしていましたが、Springの導入により、チェックされない例外処理、できるときだけ例外処理をすることの利点がわかりました。これにより、多くのお決まりの "catch/rethrow" や "throws" を回避することができるのです。

あなたの投稿より短くてすみません。あなたがこれを面白いと思ってくれればいいのですが...。