RequestContextHolder 는 Spring 컨텍스트에서 HttpServletRequest 에 직접 접근할 수 있도록 도와주는 역할을 한다. Spring 2.x 부터 제공되던 기능으로 이를 활용하면 HttpServletRequest 사용하기 위해 이를 메소드 파라미터로 연이어 넘겨받을 필요가 없다.
예를 들어 RequestContextHolder 를 사용하지 않고 Service 단에서 HttpServletRequest 를 참조해야 한다고 하면 아래와 같이 해야 한다.
@RestController
@RequiredArgsConstructor
@Log4j2
public class TestController {
private final TestService testService;
@GetMapping("hello")
public void hello(HttpServletRequest request){
testService.hello(request);
}
}
@Service
@Log4j2
public class TestService {
public void hello(HttpServletRequest request){
log.info(request.getRequestURI());
}
}
하지만 RequestContextHolder 를 사용한다면 파라미터로 넘길 필요없이 필요한 곳에서 직접 참조할 수 있다.
@RestController
@RequiredArgsConstructor
@Log4j2
public class TestController {
private final TestService testService;
@GetMapping("hello")
public void hello(){
testService.hello(request);
}
}
@Service
@Log4j2
public class TestService {
public void hello(){
HttpServletRequest req = TestUtils.getCurrReq();
log.info(req.getRequestURI());
}
}
public class TestUtils {
public static HttpServletRequest getCurrReq(){
return ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();
}
}
참고로 RequestContextHolder 에서 RequestAttribute 를 구해오는 메소드는 위에서 사용한 currentRequestAttributes() 외에 getRequestAttributes() 도 있다. 둘의 차이는 구해오려는 RequestAttributes 가 없을 경우 전자는 예외를 발생시키고 후자는 그냥 null 을 리턴한다. 나는 http 프로토콜을 이용하는 프로젝트라면 request 정보가 없다는 거 자체가 정상적인 상황이 아니기 때문에 currentRequestAttributes() 를 사용했다.
이와 비슷한 역할 해줬던 것이 과거 ThreadLocal 이었는데 RequestContextHolder 도 기본적으로 이를 활용하고 동작방식은 아래와 같다.
- ThreadLocal을 사용해서 servlet이 호출되면 key,value (thread,HttpservletRequest)를 보관한다.
- 호출된 servlet과 동일한 thread내에서는 어느 곳에서든 같은 HttpServletRequest를 꺼내서 쓸수 있다.
- servlet이 종료 될 때 해당 thread를 key로 갖는 쌍을 제거한다.
자동으로 제거까지 해주니 더이상 Thread 내에서 데이터를 공유하기 위해 ThreadLocal를 사용하며 명시적으로 제거하는 작업을 해주지 않아도 된다.
http://dveamer.github.io/backend/SpringRequestContextHolder.html
https://syundev.tistory.com/244
https://welchsy.tistory.com/269
'Backend > Spring+Boot' 카테고리의 다른 글
@ResquestParam, @RequestBody 와 Get, Post (0) | 2021.04.26 |
---|---|
threadContextInheritable (0) | 2021.04.23 |
Spring Security AuthenticationException message (0) | 2021.04.22 |
SpringBoot MVC 자동구성 제어하기 (0) | 2021.04.21 |
SpringBoot 정적자원 (0) | 2021.04.20 |