2011-03-29 3 views
8

일단 패턴을 발견하면 ServletRequest 및 응답 객체가 서블릿의 로컬 ThreadLocal 변수에 배치됩니다. 서블릿 클래스에는 현재 요청 및 응답 객체를 가져 오는 메소드도 있습니다. 따라서 이러한 객체를 얻으려면 여전히 서블릿 객체로 작업해야합니다.서블릿에 ServletRequest와 Response를 저장하는 ThreadLocal : 무엇을 위해?

ThrealLocal 지역 변수를 가지고있는 점은 무엇입니까?

답변

15

점 (예를 들어 그들이 서블릿되지 않습니다) 그렇지 않으면 그들을하지 않았을 것이다 클래스의 요청과 응답 객체를하는 것입니다. 한 가지 예가 JSF 관리 빈입니다. 메소드는 HttpServletRequest 매개 변수를 사용하지 않으므로 FacesContext을 통해 요청을받을 수 있습니다.이 요청은 ThreadLocal 변수에 있습니다. 각 요청 (서블릿 컨테이너) 별도의 스레드에 의해 처리되기 때문에이 작동

이유이다. 그래서 thread = request. 컨테이너는 스레드 풀을 사용하는 경향이 있습니다. 따라서 항상 스레드 로컬에서 새로운 요청을 설정하고 이후에이를 정리하는 것이 바람직합니다 (예 : Filter). 그렇지 않으면 예기치 않은 동작이 발생할 수 있습니다.

하지만 코드에서이 문제를 피하는 것이 좋습니다. 요청이나 응답에서 필요한 것이 있으면 메소드 인수로 전달하십시오. 그렇지 않으면 당신은 (당신이 예를 들어, 서비스 계층에서 요청을 사용하는 유혹하는 경우) 당신이 한 번 온 것 코드의 저자의 의도가 무엇인지 100 % 확실하지 않다

+0

저는 GWT RemoteServiceServlet에 그런 것들을 직면했습니다. 왜 그들이 그렇게했는지 궁금합니다. 코드를 자세히 살펴본 후에는 RemoteServiceServlet을 확장해야하는 자신의 RpcService에서 구현할 추가 인터페이스를 제공한다는 사실을 깨달았습니다. 이 경우 자신의 서비스는 그 뒤에있는 서블릿을 알지 못합니다. – glaz666

3

그들은 당신이 다른 클래스에 이러한 개체에 대한 참조를 통과하지 않고 HttpServletRequest의와 HttpServletResponse를 프로젝트 내의 다른 클래스의에 액세스 할 수 있습니다. 웹 계층 코드와 비즈니스 논리가 섞여서 단위 테스트가 더 어려워 지므로 특히 좋아하는 패턴이 아닙니다.

0

을 레이어 경계를 위반하는 위험 건너 뛴다. 그러나 나는 그 코드가 인스턴스 변수로 매개 변수 나 설정으로 전달하지 않고 코드의 어떤 메서드에서든지 ServletRequest 인스턴스를 사용할 수 있다고 생각한다. 일반적으로 ThreadLocal 변수는 정적이며 ServletRequest의 인스턴스를 정적으로 가져올 수있는 메서드가 노출되어 있습니다. 예를 들어이 기술을 사용하면 Struts FromBeans에서 ServletRequest에 쉽게 액세스 할 수 있습니다.

0

Purpose of ThreadLocal ?

는 스레드로부터 안전하지 않습니다 어떤 목적을 가지고 있지만, 그 객체 (SimpleDateFormat의)에 대한 액세스를 동기화하지 않도록 할 때. 대신 각 스레드에게 객체의 자체 인스턴스를 제공하십시오.

ThreadLocal의 또는 set()을 정리할 때는 ThreadLocal의 remove() 메서드를 사용하는 것이 매우 중요합니다.

1

요청과 응답 객체가 스레드 지역 변수에 저장되어 있기 때문에,이 방법 매개 변수로 주위를 통과 할 필요없이 해당 객체에 안전하게 접근 할 스레드 수.

예 1 : 지역 스레드없이

public class MyServlet extends Servlet { 
    private MyObject myObject = new MyObject(); 

    public void service(ServletRequest request, ServletResponse response) { 
     myObject.doSomething(request, response); 
    } 
} 

public class MyObject { 
    private MyOtherObject myOtherObject = new MyOtherObject(); 
    public void doSomething(ServletRequest request, ServletResponse response) { 
     // I do nothing with request/response, but need to accept them in order 
     // to pass them to myOtherObject 
     myOtherObject.doSomethingElse(request, response); 
    } 
} 

public class MyOtherObject { 
    public void doSomethingElse(ServletRequest request, ServletResponse response) { 
     // Do something else with request/response 
    } 
} 

예 2 :

public class MyServlet extends Servlet { 
    private MyObject myObject = new MyObject(); 

    private static ThreadLocal<ServletRequest> currentRequest = new ThreadLocal<ServletRequest>(); 

    public static ServletRequest getCurrentRequest() { 
     return currentRequest.get(); 
    } 

    private static ThreadLocal<ServletResponse> currentResponse = new ThreadLocal<ServletResponse>(); 

    public static ServletResponse getCurrentResponse() { 
     return currentResponse.get(); 
    } 

    public void service(ServletRequest request, ServletResponse response) { 
     ... 
     currentRequest.set(request); 
     currentResponse.set(response); 
     ... 
     myObject.doSomething(); 
    } 
} 

public class MyObject { 
    private MyOtherObject myOtherObject = new MyOtherObject(); 
    public void doSomething() { 
     // I do not need to know about request/response as I do nothing with them 
     myOtherObject.doSomethingElse(); 
    } 
} 

public class MyOtherObject { 
    public void doSomethingElse() { 
     // Now I can get the current request/response in a thread safe 
     // manner and without having to accept them as parameters 
     ServletRequest request = MyServlet.getCurrentRequest(); 
     ServletResponse response = MyServlet.getCurrentResponse(); 

     // Do something with request/response 
    } 
} 

물론, 단지 주변, 가장 쉬운 일이 개체를 전달하는 간단한 서블릿 지역 스레드하지만 복잡한 시나리오에 정적이지만 스레드 안전 getter를 갖는 것이 유용 할 때가 있습니다.

+0

@matt b - 요점을 찾지 못했습니다. 요청과 응답은 threadlocals에 저장되므로 다른 스레드가 간섭하지 않습니다. – Bozho

2

다른 사람들은 제시 한 시나리오에서 Thread Locals의 사용법에 대해 꽤 많이 언급했습니다. 하지만 경고를 받으려면 Thread Local relying 구현이 "스레드"와 관련이 있으며 요청 모델 당 단일 스레드에서 벗어날 때 중단됩니다. 예는 많은 수의 사용자 요청에 대해 동시에 소수의 스레드가 사용되는 이벤트 기반 서버입니다.

-1

이것은 정말 끔찍합니다. 가능한 한 빨리 HTTP 요청/세션에서 필요한 값을 얻어야합니다. 메소드 호출 또는 전송 객체에서이 값을 전달할 수 있습니다. 테크놀로지가없는 메소드/클래스를 작성하려고 노력해야합니다. 메소드/클래스가 ThreadLocal에서 http 요청을 얻으면 쓸모없는 클래스가됩니다. http 이외의 다른 컨텍스트에서는 더 이상 유용하지 않습니다.

사람들이 BO (Business Objects) 또는 DAO의 ThreadLocal에서 http 요청을 가져 오는 것이 특히 충격적입니다. HTTP 요청은 응용 프로그램의 표현 계층이 아닌 다른 계층에 나타나서는 안됩니다.

관련 문제