웹 환경 추가
웹 스코프는 우베 환경에서만 동작하므로 web 환경이 동작하도록 라이브러리를 추가하였다.
request 스코프 예제 개발
만일 동시에 여러개의 요청이오면 정확히 어떤 요청이 남긴 로그인지 구분하기 어렵다.
이럴때 사용하기 좋은 것이 request 스코프이다.
package hello.core.common;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.UUID;
@Component
@Scope(value = "request")
public class MyLogger {
private String uuid;
private String requestURL;
public void setRequestURL(String requestURL) {
this.requestURL = requestURL;
}
public void log(String message){
System.out.println("["+uuid+"]" +"["+requestURL+"] "+message);
}
@PostConstruct
public void init(){
uuid = UUID.randomUUID().toString();
System.out.println("["+uuid+"] request scope bean create:" + this);
}
@PreDestroy
public void close(){
System.out.println("["+uuid+"] request scope bean close:" + this);
}
}
로그를 출력하기위한 코드이다.
request 스코프로 지정했다. 이 빈은 HTTP 요청 당 하나씩 생성되고, HTTP 요청이 끝나는 시점에 소멸된다.
이 빈이 생성되는 시점에 자동으로 @PostContruct 초기화 메서드를 사용하여 uuid를 생성해 저장해둔다 이 빈은
HTTP요청 당 하나씩 만들어지므로 uuid를 저장해두면 다른 요청과 구분할 수 있다.
이 빈이 소멸되는 시점에 @PreDestroy를 사용하여 종료 메시지를 남긴다.
requestURL은 이 빈이 생성되는 시점에는 알 수 없기때문에, 외부에서 setter로 입력받는다.
package hello.core.web;
import hello.core.common.MyLogger;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
@Controller
@RequiredArgsConstructor
public class LogDemoController {
private final LogDemoService logDemoService;
private final MyLogger myLogger;
@RequestMapping("log-demo")
@ResponseBody
public String logDemo(HttpServletRequest request){
String requestURL = request.getRequestURL().toString();
myLogger.setRequestURL(requestURL);
myLogger.log("controller test");
logDemoService.logic("testId");
return "OK";
}
}
컨트롤러를 만들었다.
No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131) ~[spring-web-5.3.8.jar:5.3.8]
실행시켜보니 위와 같은 에러가 발생하였다.
그 이유는 MyLogger가 repuest 스코프라서 요청이 들어와야 쓸 수 있는데
컨트롤러에서 의존관계 주입할 것이 없기 때문에 에러가 발생하였다.
package hello.core.web;
import hello.core.common.MyLogger;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class LogDemoService {
private final MyLogger myLogger;
public void logic(String id) {
myLogger.log("service id =" + id);
}
}
서비스 계층에서도 로그를 출력해보기 위해 만들었다.
중요한 점은 request scope를 사용하지 않고 파라미터로 이 모든 정보를 서비스 계층에 넘긴다면
파라미터가 많아서 지저분해진다 더 문제는 requestURL 같은 웹과 관련된 정보가 웹과 관련없는 서비스 계층까지
넘어가게 된다. 웹과 관련된 부분은 컨트롤러까지만 사용하는 것이 유지보수 차원 에서 좋다.
'웹프로그래밍 > Spring 핵심 원리' 카테고리의 다른 글
54. 스코프와 프록시 (0) | 2021.10.14 |
---|---|
53. 스코프와 Provider (0) | 2021.10.14 |
51. 웹 스코프 (0) | 2021.10.14 |
50. 프로토타입 스코프 - 싱글톤 빈과 함께 사용시 Provider로 문제 해결 (0) | 2021.09.09 |
49. 프로토타입 스코프 - 싱글톤 빈과 사용시 문제점 (0) | 2021.09.01 |