본문 바로가기
spring

spring 파라미터와 Request정보가 같이 필요할 때 처리방법

by 토망이 2023. 5. 20.

아래와 같이 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";
}

 

댓글