2016년 4월 8일 금요일

Spring Web 에서 request parameter 추가

Spring Web 에서 Client 가 요청한 주소에 기반해서 값을 request 에서 가져올 수 있지만, 가끔 그 매개변수에 서버 쪽에서 어떤 값을 추가해서 받아야 할 필요가 있을 때가 있습니다. 저의 경우는 Spring MVC 에서 실제 요청을 받은 Controller 의 method 명을 알고자 할 때 강제로 Exception 을 발생시켜 첫번째 라인의 method 명을 알아내는 방식보다는, 이 방식으로 요청되는 주소에서 값을 얻어서(주소에 method 명이 유추되도록 구성되어야 하겠죠) request 에 추가하도록 처리하였습니다.

원리는 간단하면서도 살짝 복잡합니다. 일단 HttpServletRequest 라는 개체는 setParameter 라는 것이 존재하지 않습니다. 이와 같이 매개변수를 개발자가 마음대로 조작할 수 있을 경우 문제가 더 클 수 있기 때문입니다. 그래서 약간의 우회적인 방법이 필요합니다.

먼저, Filter 을 등록해야 합니다. Interceptor 는 불가능한 것으로 압니다. Filter 에서 doFilter method 등을 Override 받아 구현할 때 HttpServletRequest, HttpServletResponse, FilterChain 을 매개변수를 받을 것입니다. 이 때 매개변수로 받은 HttpServletRequest 개체를 생성자로 받아서 이를 확장할 HttpServletRequestWrapper 클래스를 상속받아 구현하는 것입니다. 통상적으로 request 의 getParameterMap() 을 이용해 Map 에 매개변수들을 저장한 뒤 getParameter(), getParameterMap(), getParameterNames(), getParameterValues() 등을 Override 해서 구현하고, setParameter() 을 새롭게 구현(setParameter() 는 2 개의 오버로드된 method 로 구현합니다)하는 형태가 됩니다.

이렇게 구현된 HttpServletRequestWrapper 는 HttpServletRequest 의 구현체 중 하나이기 때문에 Controller 로 전송되어도 사용에 크게 문제가 없습니다(OOP Design Pattern 의 장점).



저는 보통 이렇게 구현해놓고 씁니다.


public class HttpRequestWithModifiableParameters extends HttpServletRequestWrapper {

    Map<String, String[]> params;

    public HttpRequestWithModifiableParameters(HttpServletRequest request) {

        super(request);
        this.params = request.getParameterMap();

    }

    @Override
    public String getParameter(String name) {

        String[] paramArray = getParameterValues(name);

        if (paramArray != null && paramArray.length > 0) {

            return paramArray[0];

        } else {

            return null;

        }

    }

    @Override
    public Map<String, String[]> getParameterMap() {

        return Collections.unmodifiableMap(params);

    }

    @Override
    public Enumeration<String> getParameterNames() {

        return Collections.enumeration(params.keySet());

    }

    @Override
    public String[] getParameterValues(String name) {

        String[] result = null;
        String[] temp = params.get(name);

        if (temp != null) {

            result = new String[temp.length];
            System.arraycopy(temp, 0, result, 0, temp.length);

        }

        return result;
    }

    public void setParameter(String name, String value) {

        String[] oneParam = {value};
        setParameter(name, oneParam);

    }

    public void setParameter(String name, String[] values) {

        params.put(name, values);

    }

}


그래도 남용은 하지 말아야겠습니다.

댓글 2개: