2012-12-19 3 views
0

이전에는 JSF 2 앱용 쿠키를 기반으로 한 대화 세션에서 대화 세션 필터를 사용했습니다. 이제는 같은 메커니즘을 구축하고 싶지만 기술에 의존하지 않습니다. 내가 bindConversation(conversationId, request)에 도달했을 때 난 그냥 최대 절전 모드 Session에 매핑 된 conversationId를 가리키는 요청 속성을 추가, 지금어디서나 HttpServletRequest에 액세스

@Override 
protected void doFilterInternal(HttpServletRequest request, 
     HttpServletResponse response, FilterChain filterChain) 
     throws ServletException, IOException { 

    UUID conversationId = lookupConversationOrCreateIfNecessary(request, 
      response); 

    log.debug("Binding conversation '{}' to request '{}'", conversationId, 
      request); 
    bindConversation(conversationId, request); 

    try { 
     filterChain.doFilter(request, response); 
    } finally { 
     log.debug("Unbinding conversation '{}' from request '{}'", 
       conversationId, request); 
     unbindConversation(conversationId, request); 
    } 

} 

: 몇 가지 코드를 재사용, 나는 OncePerRequestFilter를 확장하는 클래스에서이 작성했습니다.

어쨌든 JSF에서는 FacesContext.getCurrentInstance().getExternalContext().getRequest()을 사용하여 현재 요청에 액세스하고 이것을 사용하여 CurrentSessionContext을 구현했습니다. 그러나 일반 서블릿에서 프로그래밍 방식으로 현재 요청에 액세스하려면 어떻게해야합니까?

참고 : 나는 OncePerRequestFilter의의 javadoc을 읽고하고 난 이걸 발견 :

서블릿 3.0로, 필터는 요청 또는 별도의 스레드에서 발생 ASYNC 파견의 일환으로 호출 할 수 있습니다. 웹 서버에 필터를 구성하여 비동기식 에 참여해야하는지 여부를 결정할 수 있습니다. 그러나 어떤 경우 서블릿 컨테이너는 다른 기본 구성을 가정합니다. 따라서 shouldNotFilterAsyncDispatch()는 스레드 초기화, 로깅, 보안 등을 제공하기 위해 을 전달하기 위해 두 유형의 모든 디스패치 중 실제로 이 호출되면 정적으로 선언하도록 재정의 할 수 있습니다. 이 메카니즘은 보충 유형을 가진 web.xml에서 필터를 구성 할 필요를 보완하고 대체하지 않습니다.

따라서 내가 원하는 것을 얻으려면 ThreadLocal을 사용하는 것이 위험할까요?

+0

ThreadLocal은 JSF가 사용하는 것으로서 위험하지 않아야합니다. JSF는 계측이 일어날 수있는 유일한 FacesServlet을 통해 모든 것이 라우팅되기 때문에 무엇을 할 수 있습니다. 비슷한 것을하고 싶다면 비슷한 전략을 사용해야합니다. – Gimby

+0

예, 필터가 ASYNC 디스패치로 구성된 경우 많은 스레드가 메커니즘을 사용합니다. 해당 스레드가 bindConversation 코드를 실행하는 스레드에서 생성되지 않는 한 NullPointerExceptions가 표시됩니다. 그렇지 않니? 또한 InheritableThreadLocal에 요청을 넣으면 컨테이너가 풀을 사용할 수 있으며 문제가 발생할 수 있으므로 정리가 까다로울 수 있습니다. – ElderMael

답변

1

당신이 질문에 언급했듯이 : ThreadLocal을 사용하는 것이 좋은 방법 인 것 같습니다. REQUEST와 ASYNC 둘 다에 필터를 사용하자마자 왜 안전하지 않을지 모르겠습니다.

EDIT

@Override 
protected void doFilterInternal(HttpServletRequest request, 
           HttpServletResponse response, FilterChain filterChain) 
     throws ServletException, IOException { 


    UUID conversationId = lookupConversationOrCreateIfNecessary(request, 
      response); 

    log.debug("Binding conversation '{}' to request '{}'", conversationId, 
      request); 

    ConversationHolder.setId(conversationId); 

    bindConversation(conversationId, request); 

    try { 
     filterChain.doFilter(request, response); 
    } finally { 
     log.debug("Unbinding conversation '{}' from request '{}'", 
       conversationId, request); 
     ConversationHolder.clear(); 
     unbindConversation(conversationId, request); 
    } 

} 

@Override 
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { 
    return false; //to be sure both REQUEST and ASYNC are filtered 
} 

그리고 conversationId 이래 ConversationHolder

public class ConversationHolder extends ThreadLocal<UUID>{ 

    private static ConversationHolder INSTANCE = new ConversationHolder(); 

    public static void setId(UUID conversationId){ 
      INSTANCE.set(conversationId); 
    } 

    public static UUID getId(){ 
     return INSTANCE.get(); 
    } 

    public static void clear(){ 
     INSTANCE.remove(); 
    } 

} 

는 요청들 사이에서 공유되지 로컬 변수이다.

ConversationHolder는 ThreadLocal이므로 doFilter (...) 중에 값을 얻는 것이 정확합니다. (요청 처리 중에 수동으로 새 스레드를 작성하는 경우는 제외하지만 권장되는 설계는 아닙니다.)

+1

javadoc이 명백하게'Servlet 3에서 소개 된 dispatcher type javax.servlet.DispatcherType.ASYNC 상태를 가지고 있기 때문에 정리에 관심이 있습니다.0은 필터가 하나의 요청 과정 동안 하나 이상의 스레드에서 호출 될 수 있음을 의미합니다. " – ElderMael

+0

은 일부 코드로 내 게시물을 편집했습니다. – ben75

+0

꽤 많이 생각했는데, HibernateTransactionManager와 비슷하지만 많은 요청에 따라 하나의 세션으로 보입니다! – ElderMael