2011-10-18 1 views
1

webappは、SpringのOpenSessionInViewInterceptorを使用して、リクエストごとにHibernateセッションを開き、リクエスト処理の終了時に閉じる。これは非常にうまくいく。しかし、ファイルのダウンロードのような要求の中には、セッションを開いたままにしてDB接続を張っておく時間が長くかかることがあります。私たちの場合、ファイルデータをレスポンス出力ストリームにコピーすることは、コントローラが行う最後の処理であり、Hibernateセッションは必要ありません(ファイルデータはサーバファイルシステムから読み込まれます)。これらのファイルのダウンロード要求は、db接続プール内のほとんどの接続を迅速に消費する可能性があります。OpenSessionInViewInterceptorを使用するとセッションを終了する(&db接続をプールに戻す)方法

私はコントローラにSessionFactoryへの参照を与えられた、とだけ応答出力ストリームにファイルデータをコピーする前に、次のメソッドを呼び出しました:

SessionFactoryUtils.closeSession(SessionFactoryUtils.getSession(sessionFactory, false)); 

OpenSessionInViewInterceptorは後で要求プロセスで同じことを行いセッションを閉じることは冪等であるように見えます(つまり、このメソッドを複数回呼び出すと、1回呼び出すのと同じ効果があります)。言い換えれば、この変更のローカルテストは順調でした。しかし、それはちょっと危険なようです。 Springのそれ以降のバージョンでOpenSessionInViewInterceptorまたはSessionFactoryUtilsが変更された場合、このアプローチは微妙な方法で壊れている可能性があります(接続が漏れている可能性があります)。

最終的な目標は、ファイルデータの送信を開始する前にデータベース接続を閉じることです。これはその達成方法の1つです。もう1つの解決策は、コントローラが入力ストリームを属性として要求に入れ、フィルタを(OpenSessionInViewInterceptorの後に起動する)入力ストリームのデータを応答にコピーすることです。これには独自の課題があります(たとえば、コントローラに集中する代わりに、コントローラとフィルタの間で関連するコードが分割されるなど)。

これを処理するより良い方法はありますか?

答えて

2

1つのオプションは、ファイルを返すコントローラ/アクションにOSiVを使用しないことです。もう1つは、自信を持って独自のバージョンを作成することです(結局のところ、それほど複雑ではありません)。

インターセプタ/ utilsが変更された場合はリークリークの可能性があります。私は、インターセプターがそのことをやった後でファイルを返す何かを持っているという考えに興奮していません。フォローアップインターセプター(またはフィルター、IMOは連鎖インターセプターでそれをやっているかもしれませんが、おそらくクリーナーです)によってぶら下がっている状態を持つことを意味し、それは私を厄介でエラーを起こしやすいものにします。

+0

これはこれまでのやり方です。ファイルのダウンロード操作にOSiVを使用しないでください。 –

+0

提案していただきありがとうございます。私はそのオプションを検討しましたが、アプリケーション内の別のパスからのファイルダウンロードがいくつかあります。 OSiVは現在すべての要求に適用されています。分散したファイルのダウンロードパスにより、OSiVを選択的にオプトアウトすることが困難になります。おそらく、すべてのファイルのダウンロードを共通のパスに移動する必要があります。そのため、これらの要求にOSiVを適用しない方が簡単でしょう。 –

関連する問題