9

私の理解によると、サーブレットコンテナは、サーブレットの限定されたインスタンスと各サーブレットインスタンスの複数のスレッドを作成し、それらのスレッドとインスタンスを再利用します。

スレッドには複数のインスタンスがあるため、それらは「スレッドセーフ」ではありません(ただし、スレッドセーフでコーディングすることは難しくないことを理解しています)。

一方、EJBコンテナはEJBのスレッドを作成せず、EJBオブジェクトのみを再利用します(プールを使用)。EJBインスタンスには複数のスレッドがないため、スレッドの安全性に問題はありません。

私の質問:なぜ異なる振る舞いをするのですか?EJBをサーブレット(スレッドセーフではない)として機能させるのは良い考えではありませんか?

私は何かが欠けていると確信しており、その欠けている部分を理解したいと思います。

4

3 に答える 3

9

おそらく、同じ目標を念頭に置いて設計されていないためです。

サーブレットAPIは、HTTPプロトコルに非常に近い単純なAPIであり、その上にアプリケーションまたはフレームワークを構築できます。HTTPプロトコルは完全にステートレスなので、ステートレスのAPIも構築するのは理にかなっていると思います。サーブレットAPIの上に構築されたいくつかのフレームワーク(たとえば、ストライプ)は、リクエストごとに1つのアクションインスタンスを使用しますが、これは同時に使用されません。

EJBは、トランザクションビジネスロジックを可能な限り単純に実装するように設計された、はるかに複雑で高レベルのフレームワークです。それはより重い重量であり、ステートフルなコンポーネントを持っています。これらは明らかにスレッドセーフである必要があります。したがって、ステートレスBeanをスレッドセーフにするのも自然なことだったと思います。

たとえば、Spring Beanはデフォルトでシングルトンであるため、サーブレットと同じルールに従う必要があることに注意してください。したがって、複数の設計でほぼ同じ機能を提供できます。

スレッドは、パフォーマンスの最適化とは何の関係もありません。3つのリクエストを同時に処理する必要がある場合は、リクエストがサーブレットに送信されるか、EJBに送信されるかに関係なく、3つのスレッドが必要です。

于 2012-06-26T22:13:44.217 に答える
9

もちろん、あなたの質問に対する最短の答えは、EJBがサーブレットのように機能できるようにすることをお勧めします。EJB3.1では、まさにそれを実行できるコンポーネントを追加しました。@Singleton

Beanは、次の@Singletonいずれかの方法でサーブレットのようにマルチスレッド化できます。

  • 使用する@ConcurrencyManagement(BEAN)
  • 並行性が必要なメソッドやスレッドセーフではないメソッド@ConcurrencyManagement(CONTAINER)と一緒に使用します。@Lock(READ)@Lock(WRITE)

サーブレットがEJBにはなかった何年にもわたって持っていたもう一つのことは、サーブレットが<load-on-startup>熱心にロードされ、アプリケーションの開始時に機能することを可能にすることでした。

サーブレットと一致させるために、任意のEJBに追加できるアノテーションを<load-on-start>追加し、アプリケーションの起動時にEJBを起動させます。これらのBeanには、アプリケーションの起動時に呼び出されるメソッドと、アプリケーションのシャットダウン時に呼び出されるメソッドがあります。@Startup@Singleton@PostConstruct@PreDestroy

番号()を使用して、 startで注釈が<load-on-startup>1</load-on-startup>付けられたBeanの順序を指定するのではなく、Beanに注釈を付け、注釈付きBeanの前に開始する必要があるBeanのリストを指定できます。@Startup@DependsOn

そして、サーブレットとEJBを整列させるためにEJB 3.1で行った、あまり知られていない、理解されていない側面は、もちろん、EJBを.warファイル内にパッケージ化できるようにすることでした(これはあまり知られていない部分ではありません)。java:comp/envサーブレットアプローチに一致するように。

java:comp/envEJB 3.1より前は、2つのEJBで名前空間を共有する方法はありませんでした( java:comp/envEJB仕様ではBeanスコープです)。対照的に、サーブレットには、個々のサーブレットが独自のプライベートjava:comp/env名前空間を持つ方法がありませんでした(java:comp/envサーブレット仕様ではモジュールスコープです)。したがって、EJB 3.1では、戦争にパックされたEJBは、Webアプリケーション内の他のすべてのサーブレットおよびEJBと同じモジュールスコープの名前空間を持ちます。これは、 EJBがEARにパックされたときに取得するjava:comp/envBeanスコープの名前空間とはかなり対照的です。java:comp/env戦争の外。私たちはそれについて何週間も議論しました。

お友達にクイズをするのにちょっとしたビールタイムはささいなことです。

于 2012-06-27T01:30:23.767 に答える
3

最良の答えは、javax.servlet.SingleThreadedModelインターフェースのJavadocから直接取得することです。

非推奨。JavaサーブレットAPI2.4以降、直接の置き換えはありません。

public interface SingleThreadModel

サーブレットが一度に1つのリクエストのみを処理するようにします。このインターフェースにはメソッドがありません。

サーブレットがこのインターフェースを実装している場合、サーブレットのサービスメソッドで2つのスレッドが同時に実行されないことが保証されます。サーブレットコンテナは、サーブレットの単一インスタンスへのアクセスを同期するか、サーブレットインスタンスのプールを維持し、新しい各リクエストを空きサーブレットにディスパッチすることで、この保証を行うことができます。

SingleThreadModelは、すべてのスレッドセーフの問題を解決するわけではないことに注意してください。たとえば、SingleThreadModelサーブレットが使用されている場合でも、セッション属性と静的変数には、複数のスレッドで同時に複数のリクエストからアクセスできます。開発者は、インスタンス変数の使用を回避したり、これらのリソースにアクセスするコードのブロックを同期したりするなど、このインターフェイスを実装する代わりに、これらの問題を解決するために他の手段をとることをお勧めします。このインターフェースは、サーブレットAPIバージョン2.4で非推奨になりました。

于 2012-06-26T22:39:25.740 に答える