일단 패턴을 발견하면 ServletRequest
및 응답 객체가 서블릿의 로컬 ThreadLocal
변수에 배치됩니다. 서블릿 클래스에는 현재 요청 및 응답 객체를 가져 오는 메소드도 있습니다. 따라서 이러한 객체를 얻으려면 여전히 서블릿 객체로 작업해야합니다.서블릿에 ServletRequest와 Response를 저장하는 ThreadLocal : 무엇을 위해?
이 ThrealLocal
지역 변수를 가지고있는 점은 무엇입니까?
일단 패턴을 발견하면 ServletRequest
및 응답 객체가 서블릿의 로컬 ThreadLocal
변수에 배치됩니다. 서블릿 클래스에는 현재 요청 및 응답 객체를 가져 오는 메소드도 있습니다. 따라서 이러한 객체를 얻으려면 여전히 서블릿 객체로 작업해야합니다.서블릿에 ServletRequest와 Response를 저장하는 ThreadLocal : 무엇을 위해?
이 ThrealLocal
지역 변수를 가지고있는 점은 무엇입니까?
점 (예를 들어 그들이 서블릿되지 않습니다) 그렇지 않으면 그들을하지 않았을 것이다 클래스의 요청과 응답 객체를하는 것입니다. 한 가지 예가 JSF 관리 빈입니다. 메소드는 HttpServletRequest
매개 변수를 사용하지 않으므로 FacesContext
을 통해 요청을받을 수 있습니다.이 요청은 ThreadLocal
변수에 있습니다. 각 요청 (서블릿 컨테이너) 별도의 스레드에 의해 처리되기 때문에이 작동
이유이다. 그래서 thread = request. 컨테이너는 스레드 풀을 사용하는 경향이 있습니다. 따라서 항상 스레드 로컬에서 새로운 요청을 설정하고 이후에이를 정리하는 것이 바람직합니다 (예 : Filter
). 그렇지 않으면 예기치 않은 동작이 발생할 수 있습니다.
하지만 코드에서이 문제를 피하는 것이 좋습니다. 요청이나 응답에서 필요한 것이 있으면 메소드 인수로 전달하십시오. 그렇지 않으면 당신은 (당신이 예를 들어, 서비스 계층에서 요청을 사용하는 유혹하는 경우) 당신이 한 번 온 것 코드의 저자의 의도가 무엇인지 100 % 확실하지 않다
그들은 당신이 다른 클래스에 이러한 개체에 대한 참조를 통과하지 않고 HttpServletRequest의와 HttpServletResponse를 프로젝트 내의 다른 클래스의에 액세스 할 수 있습니다. 웹 계층 코드와 비즈니스 논리가 섞여서 단위 테스트가 더 어려워 지므로 특히 좋아하는 패턴이 아닙니다.
을 레이어 경계를 위반하는 위험 건너 뛴다. 그러나 나는 그 코드가 인스턴스 변수로 매개 변수 나 설정으로 전달하지 않고 코드의 어떤 메서드에서든지 ServletRequest
인스턴스를 사용할 수 있다고 생각한다. 일반적으로 ThreadLocal
변수는 정적이며 ServletRequest
의 인스턴스를 정적으로 가져올 수있는 메서드가 노출되어 있습니다. 예를 들어이 기술을 사용하면 Struts FromBeans에서 ServletRequest
에 쉽게 액세스 할 수 있습니다.
는 스레드로부터 안전하지 않습니다 어떤 목적을 가지고 있지만, 그 객체 (SimpleDateFormat의)에 대한 액세스를 동기화하지 않도록 할 때. 대신 각 스레드에게 객체의 자체 인스턴스를 제공하십시오.
ThreadLocal의 또는 set()
을 정리할 때는 ThreadLocal의 remove()
메서드를 사용하는 것이 매우 중요합니다.
요청과 응답 객체가 스레드 지역 변수에 저장되어 있기 때문에,이 방법 매개 변수로 주위를 통과 할 필요없이 해당 객체에 안전하게 접근 할 스레드 수.
예 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를 갖는 것이 유용 할 때가 있습니다.
@matt b - 요점을 찾지 못했습니다. 요청과 응답은 threadlocals에 저장되므로 다른 스레드가 간섭하지 않습니다. – Bozho
다른 사람들은 제시 한 시나리오에서 Thread Locals의 사용법에 대해 꽤 많이 언급했습니다. 하지만 경고를 받으려면 Thread Local relying 구현이 "스레드"와 관련이 있으며 요청 모델 당 단일 스레드에서 벗어날 때 중단됩니다. 예는 많은 수의 사용자 요청에 대해 동시에 소수의 스레드가 사용되는 이벤트 기반 서버입니다.
이것은 정말 끔찍합니다. 가능한 한 빨리 HTTP 요청/세션에서 필요한 값을 얻어야합니다. 메소드 호출 또는 전송 객체에서이 값을 전달할 수 있습니다. 테크놀로지가없는 메소드/클래스를 작성하려고 노력해야합니다. 메소드/클래스가 ThreadLocal에서 http 요청을 얻으면 쓸모없는 클래스가됩니다. http 이외의 다른 컨텍스트에서는 더 이상 유용하지 않습니다.
사람들이 BO (Business Objects) 또는 DAO의 ThreadLocal에서 http 요청을 가져 오는 것이 특히 충격적입니다. HTTP 요청은 응용 프로그램의 표현 계층이 아닌 다른 계층에 나타나서는 안됩니다.
저는 GWT RemoteServiceServlet에 그런 것들을 직면했습니다. 왜 그들이 그렇게했는지 궁금합니다. 코드를 자세히 살펴본 후에는 RemoteServiceServlet을 확장해야하는 자신의 RpcService에서 구현할 추가 인터페이스를 제공한다는 사실을 깨달았습니다. 이 경우 자신의 서비스는 그 뒤에있는 서블릿을 알지 못합니다. – glaz666