아래와 같이 Controller와 Dto가 있을때, 파라미터로 받은 restAPITestDto의 변수와, Request의 url이나 헤더와 같은 정보를 같이 로깅하는 상황이 실무에서 생겨, 이에 대해 고민했던 처리방법을 적어보고자 합니다.
- Controller
@RestController
@RequestMapping("api")
@RequiredArgsConstructor
@Slf4j
public class RestAPIController {
@PostMapping("RequestBody/test2")
public String postRequestBody(@RequestBody RestAPITestDto restAPITestDto) {
log.info("postRequestBody log / first param : {}, second param : {}",restAPITestDto.getFirst(), restAPITestDto.getSecond());
return "ok";
}
}
- Dto
@Data
public class RestAPITestDto {
private String first;
private String second;
}
1. Controller에 HttpServletRequest 추가
우선 가장 쉽게 생각났던 방법입니다. 아래와 같이 컨트롤러내에 메서드에 HttpServletRequest를 추가하면 쉽게 가져올 수 있습니다. 그런데 해당 방법을 통해서는 만약 Service단에도 동일하게 Dto 정보와 Request정보가 함께 필요할때, Service단도 HttpServletRequest를 받을 수 있도록 파라미터를 수정해야 하기 때문에 단점이 있습니다.
@PostMapping("RequestBody/test2")
public String postRequestBody(@RequestBody RestAPITestDto restAPITestDto, HttpServletRequest httpServletRequest) {
log.info("postRequestBody log / first param : {}, second param : {}",restAPITestDto.getFirst(), restAPITestDto.getSecond());
log.info("url : {}",httpServletRequest.getRequestURL());
return "ok";
}
2. Filter에 @RequestBody 데이터 가져오기
아래와 같은 Filter나 Interceptor 같은곳에서는 HttpServletRequest를 가져오고 있으니, @RequestBody로 받는 RestAPITestDto 파라미터를 필터에 추가하는 방법을 해보려 하였으나, @RequestBody는 한번 읽으면 뒤쪽으로 제대로 전달되지 않는 이슈가 있어 HttpServletRequestWrapper로 감싸서 필터에서 읽는식으로 구현을 해야한다고 하는데.. 복잡하여 다른 방법을 찾았습니다.
@Slf4j
public class TimeCheckFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
String method = req.getMethod();
StringBuffer requestURL = req.getRequestURL();
long startTime = System.currentTimeMillis();
try {
log.info("TimeCheckFilter Method : {}, url : {},",method,requestURL);
//핵심 코드 doFilter
filterChain.doFilter(servletRequest,servletResponse);
}
catch (Exception e){
throw e;
}
finally {
long endTime = System.currentTimeMillis();
long gap = endTime - startTime;
log.info("FilterElaspedTime : {} ms",gap);
}
}
}
3. RequestContextHolder를 사용하여 Request정보 가져오기
아래와 같이 RequestContextHolder를 사용하면 Spring 전역으로 request정보를 가져올 수 있어, 컨트롤러 뿐만 아니라 Service에서도 선언만하면 가져올 수 있어 해당 방법을 통해 @RequestBody 로 받은 파라미터와 request의 url, 헤더를 같이 사용하는 부분을 해결하였습니다.
@PostMapping("RequestBody/test2")
public String postRequestBody(@RequestBody RestAPITestDto restAPITestDto) {
log.info("postRequestBody log / first param : {}, second param : {}",restAPITestDto.getFirst(), restAPITestDto.getSecond());
HttpServletRequest servletRequest = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
log.info("log : {}",servletRequest.getRequestURL());
return "ok";
}
'spring' 카테고리의 다른 글
spring jasypt를 활용한 DB접속정보 암호화 (0) | 2023.06.25 |
---|---|
Spring Data JPA 쿼리메서드 방식으로 MongoDB 연계 (0) | 2023.06.04 |
spring RequestBodyAdviceAdapter를 통한 apiKey 인증인가 적용 (0) | 2023.06.04 |
spring Filter에 @RequestBody 불러오기 / apiKey 인증인가 적용 (0) | 2023.06.04 |
spring Interceptor (0) | 2023.05.20 |
spring Filter (0) | 2023.05.20 |
spring Bean Validation 적용(@NotNull, @NotEmpty, @NotBlank, @Max, @Min) (0) | 2023.05.19 |
spring RestAPI 어노테이션 정리 (0) | 2023.05.14 |
댓글