8

サーブレット仕様(前の質問を参照)は、同じスレッドがすべてのフィルターと関連するサーブレットを実行することを保証します。これを考えると、 (適切にクリーンアップすることを前提として)HttpServletRequest.setAttributeを使用するオプションがある場合、を使用してデータを渡すことの使用法はわかりません。文字列キーやマップが使用されていないため、型安全性とパフォーマンスの向上というThreadLocal2つの利点があると思います(おそらく(文字列以外の)スレッドIDによるスレッドコレクションへの場合を除く)。ThreadLocal

誰かが私が正しいかどうかを確認して、放棄を進めることができますsetAttributeか?

4

4 に答える 4

3

HttpServletRequestを処理しているものが何であれ、コードの「背後」に「グローバル」変数を設定しようとしている場合は、スレッドローカルがより適切に機能します。JSP / JSFページ、またはHttpServletRequestから読み取るその他のWeb UIコンポーネントを使用している場合は、ThreadLocalから情報を自分で取得する必要があります。この2つは、ほとんどのWebプログラミングでは同等ではありません。

于 2012-04-10T21:22:41.883 に答える
3

この方法でThreadLocalを使用することは、共有状態を維持するためにある種のシングルトンに依存していることを意味します。最終的に、これは、機能のカプセル化の難しさ、依存関係の認識、機能の交換(またはモックアウト)の不能など、多くの欠点があるため、通常は不十分な設計と見なされます。

属性またはセッションを使用することによるパフォーマンスのオーバーヘッドは、シングルトンでのThreadLocal変数のあまり一般的でない提案を処理する場合と比較して、おそらく価値があります。ただし、これはもちろん、特定のユースケースとプロジェクトによって異なります。アプリケーションの状態を維持する方法としてサーブレットでシングルトンを使用することは、アプリケーションの状態をサーブレットと共有することが難しいため(依存関係を挿入するのが難しい)、ある程度一般的ですが、これらのオブジェクトのシングルトンオブジェクトがユーザーごとの状態(EJB以外)を維持することはまれです。 )。

セッションを使用する場合、またはコンテナオブジェクトを属性として設定する場合は、String(O(1))を介した単一のフェッチのみを処理し、次にコンテナタイプ(必要なすべての値)。さらに後のコードを呼び出すには、必要に応じてパラメーターを取得し、任意のタイプのグローバルまたはシングルトンを使用することをできるだけ避ける必要があります。

最終的に、パフォーマンスという名目でやや変わった(賢い)ソリューションを検討する前に、常に最初に単純な実装をテストして、そのパフォーマンスが適切かどうかを確認してください。ここで保存される可能性のある2nsは、dbクエリとtcp接続の確立に費やされる20+msと比較しておそらく重要ではありません。

于 2012-04-10T21:55:30.727 に答える
3

ThreadLocalに反対することをお勧めします。

なぜそれを検討しているのかはわかりますが、時期尚早の最適化の罠に陥っていると思います。ThreadLocalsは本質的にグローバル変数であり、優れた設計になることはめったにありません。時間の節約はごくわずかです。これがサーバーのスループットのボトルネックになることは決してないことを保証します。

スレッドモデルがまったく異なるため、一部の要求に対する非同期応答の使用を開始する場合(たとえば、ロングポーリングをサポートする場合)、ThreadLocalを使用すると問題が発生する可能性があります。

于 2012-04-11T18:23:44.063 に答える
3

ThreadLocalはHttpServletRequest.setAttribute( "key"、 "value")よりも望ましいですか?

具体的な機能要件によって異なります。

たとえば、JSFはをに格納しFacesContextますThreadLocal。これにより、「raw」HttpServletRequestや、マネージドBeanなどHttpServletResponseによって実行されるコード内の任意の場所を含むすべてのJSFアーティファクトにアクセスできます。FacesServlet他のほとんどのJavaベースのMVCフレームワークも同じ例に従います。

あなたのコメントによると、

主に、UserオブジェクトとEntityManagerオブジェクトをユーザーフィルターとデータベースフィルターからサーブレットに転送する必要があります。また、これらは将来のコードで頻繁かつ予期せず必要になることがわかり、サーブレットをはるかに超えて(つまり、doGetによって呼び出されるネストされたコードで)使用したいと思っています。より深いコードのためのより良い方法があるかもしれないと私は感じます-提案?

これUserがセッション属性であると想定している例については、JSFと同じアプローチを採用したいと思います。ThreadLocal<Context>ここでContext、現在の参照を保持するカスタムラッパークラスを作成します。これにより、コード内のどこからHttpServletRequestでもHttpServletResponseアクセスできるようになります。必要に応じて、クラスUserから直接取得するための便利なメソッドを提供します。Context

例としてEntityManagerは、同じアプローチに従うこともできますが、私は個人的には同じアプローチではなく ThreadLocal<Context>、異なるアプローチを採用します。または、サービス層のJNDIから取得するだけで、トランザクションをよりきめ細かく制御できます。いずれの場合も、コミット/クローズを適切に処理することを絶対に確認してください。コンテナからの永続性とトランザクション管理の引き継ぎは、細心の注意を払って行う必要があります。私は、EJB /JPAのような既存の適切に設計されたAPI/フレームワークを使用することに対する嫌悪感を本当に再考します。そうしないと、すでに標準化されているすべてのAPIなどを再発明するという完全な時間の浪費のリスクがあります。

参照:

于 2012-04-12T04:24:09.543 に答える