2016-05-31 12 views
5

今私は多くのことを試しましたが、私はパズルを欠いているようです。私はHttpServletRequestからいくつかのSessionContextを読み込むリクエストスコープのBeanを持っています。この属性はフィルタに設定されます。コードが正しいスレッドで実行されている間、これは絶対にうまく動作します。Springのリクエストスコープ付きBeanを子スレッドに割り当てる(HttpServletRequest)

@Component 
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.INTERFACES) 
public class SessionContextProviderImpl implements SessionContextProvider<SessionContext> { 
    private final HttpServletRequest _request; 

    @Autowired 
    public SessionContextProviderImpl(HttpServletRequest request) { 
     _request = request; 
    } 

    @Override 
    public SessionContext get() { 
     return (SessionContext) _request.getAttribute(Constants.SESSION_CONTEXT_IDENTIFIER); 
    } 
} 

は今、私は新しい機能のCompletableFuture 8SのJavaを使用して開始し、私は結果の要求スレッドが待機中に並行して、これらの機能のコンピューティングのもののうち3つを持っています。私がしたいのは、オリジナルのhttpスレッドから生成された子スレッドで使用できるように、Beanまたは要求を昇進/伝播することです。特に私は、非同期で提供されるCompletableFuture内部からHttpServletRequestからSessionContextを取得したいと思います。

final HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); 
request.getAttribute(Constants.SESSION_CONTEXT_IDENTIFIER); 

しかし、これは明らかに、要求がBeanをスコープと同じ結果を持っている:私が試したものを

は、この(GETの置き換え実装)です。 Well "getRequest"はスローされた例外の代わりにnullを返します。

ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) beanFactory; 

org.springframework.beans.factory.config.Scope simpleThreadScope = new SimpleThreadScope(); 

cbf.registerScope("simpleThreadScope", simpleThreadScope); 

、私は「simpleThreadScope」とSessionContextProviderImplの範囲を設定します。私はこのoriginal postを試みた第三のアプローチとして

。残念ながら、これはどちらもうまくいかず、リクエストスコープの外で使用されるという例外を投げました。

私が使用している環境:スプリングインジェクションと一緒にジャージー。

多分誰か考えているのですか?

に関していかなる将来の冒険者のために

答えて

6

を:

私は春のコードを掘るためにいくつかの時間がかかったとinheritableRequestAttributesHolderを持ってRequestContextHolderを見つけました。

継承可能なスレッドローカル変数は、スレッドごとの属性が維持されている場合に、通常のスレッドローカル変数よりも優先されます(これは、以下を継承しています:InheritableThreadLocal)変数(例えば、ユーザーID、トランザクションID)内のすべての子スレッドは、作成された子スレッドに自動的に送信されなければなりません。

したがって、RequestContextHolderにはフィールドがあり、実際にはsetRequestAttributesはinheritableRequestAttributesHolderを使用するフラグをサポートしています。さらに、RequestContextListener - > requestInitializedを見ると、フラグ(= false)なしで呼び出されます。だから私がやったことはこれです:

public class InheritableRequestContextListener extends RequestContextListener { 
    private static final String REQUEST_ATTRIBUTES_ATTRIBUTE = 
     InheritableRequestContextListener.class.getName() + ".REQUEST_ATTRIBUTES"; 

    @Override 
    public void requestInitialized(ServletRequestEvent requestEvent) { 
     if (!(requestEvent.getServletRequest() instanceof HttpServletRequest)) { 
      throw new IllegalArgumentException(
        "Request is not an HttpServletRequest: " + requestEvent.getServletRequest()); 
     } 
     HttpServletRequest request = (HttpServletRequest) requestEvent.getServletRequest(); 
     ServletRequestAttributes attributes = new ServletRequestAttributes(request); 
     request.setAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE, attributes); 
     LocaleContextHolder.setLocale(request.getLocale()); 
     RequestContextHolder.setRequestAttributes(attributes, true); 
    } 
} 

私はSessionContextProviderに子スレッドでアクセスできます。

+0

要求が完了した後、どのようにrequestattributesを使用していますか。要求が完了すると、ヘッダー属性などの要求属性が失われています。私は、RequestContextHolder.setRequestAttributes(属性、真)を使用しようとしました。まだ運がない。 –

+0

要求の実行を妨げず、完全に独立して動作するスレッドでコンテキストを使用する場合は、DelegatingSecurityContextExecutor https:// docsのような異なるソリューションを探す必要があります。spring.io/spring-security/site/docs/current/reference/html/concurrency.html –

+0

コンポーネントですか?構成クラス?どのような注釈をクラスに追加する必要がありますか? –

関連する問題