Spring MVC 기반으로 개발 하는 경우, URL 기준이 아닌, Method 기준 으로 AOP 를 사용할 때가 있다. 스타일 차이라고 생각 한다.


보통 Interceptor 를 사용 하면, HttpServletRequest, HttpServletResponse 객체를 기본적으로 사용할 수 있다. Tomcat Filter 의 기능과 비슷하기 때문이다. 처리 방법에 따라 다르겠지만, 시점이 Controller 호출 전 이기 때문에, @ModelAttribute 를 사용하여 개발 한다면, Http 요청 시 사용되는 파라미터가 Model 로 값이 들어가기 전이기 때문에, 원시 적인 방법인 request.getParameter(String key) 함수를 사용해야 한다. 더 나은 방법은 AOP 기법을 활용 하는 것이다.


AOP 는 Method 기준으로 사용되기 때문에 원하는 시점을 선택하여 적용이 가능 하다. Controller 를 호출 하기전에 끼어드는 방식으로 Around 방식을 사용하면 Model 에 값이 들어간 후 이기 때문에, 데이터의 가공을 편하게 할 수 있다. Model은 joinPoint.getArgs() 함수를 사용하여 값 확인이 가능 하다. 아래는 예제 소스 이다.


/**
 * CustomAspect
 *
 * @author whitelife
 * @since 2014.10.05
 * @version 0.1
 */
public class CustomAspect {

    /**
     * Custom Aspect
     *
     * @param joinPoint Proxy Method Info
     * @return joinPoint
     * @throws Throwable
     */
    public Object customAspect(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result = null;

        // (Before) doing...        

        for (Object obj : joinPoint.getArgs()) {
            if (obj instanceof HttpServletRequest || obj instanceof MultipartHttpServletRequest) {
                HttpServletRequest request = (HttpServletRequest) obj;

                // Doing...

            }
        }

        try {
            result = joinPoint.proceed();
        } catch (Throwable e) {
            throw e;
        }

        // (After) doing...     

        return result;
    }
}


ProceedingJoinPoint 클래스는 Target Class, Target Method 정보 를 담고 있다. proceed 메소드 호출 시 Target Method 를 실행 한다. 보통 joinPoint.getArgs() 함수 를 사용하여 Target Method 의 인자 값을 확인하여 사용하지만, 매번 Controller Method 에 인자로 HttpServletRequest 를 넣어줘야 하는 불편함이 있다.


HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();


위 방법을 사용하면, AOP 에서도 HttpServletRequest 객체에 접근이 가능하다. Controller 개발 시 인자로 HttpServletRequest 를 받을 필요가 없다. 편리하게 사용할 수 있겠다.


ServletRequestAttributes 는 HttpRequest 가 오는 경우, RequestContextListener.requestInitialized(ServletRequestEvent requestEvent) 함수에 의해 값이 전달 되기 때문에 값을 받을 수 있는 것이다. RequestContextListener 의 일부 이다. 아래와 같이 구현 되어 있다.


public void requestInitialized(ServletRequestEvent requestEvent) {
    if (!(requestEvent.getServletRequest() instanceof HttpServletRequest)) {
        throw new IllegalArgumentException(
                "Request is not an HttpServletRequest: "
                        + requestEvent.getServletRequest());
    }

    HttpServletRequest request = (HttpServletRequest) requestEvent
            .getServletRequest();
    ServletRequestAttributes attributes = new ServletRequestAttributes(
            request);
    request.setAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE, attributes);
    LocaleContextHolder.setLocale(request.getLocale());
    RequestContextHolder.setRequestAttributes(attributes);
}


ArgumentResolver 를 사용하여 구현도 가능 하지만, 해당 기능은 공통적으로 필요한 값을 추가 하는 용도라고 판단이 된다.


무조건 정답이라고 할 수는 없다. 적합한 방법을 사용하여 작업 하면 된다고 판단 된다.


참고 사이트


+ Recent posts