티스토리 뷰
2) 아규먼트 리졸버를 이용해 HTTP Header정보를 Map객체에 담아서 Controller에게 전달하기
- 참고로 Map이나 Map을 상속받고 있는 객체는 스프링에서 내부적으로 사용하고 있는 아규먼트 리졸버가 선처리하고 있기 때문에 직접 사용할 수 없다고 그랬습니다. 그래서 Map객체를 전달하려면 Map을 필드로 가지고 있는 별도의 객체를 선언한 후 사용해야 합니다.
- 그렇기 때문에 Map을 필드로 가지고 있는 HeaderInfo라는 클래스를 작성하겠습니다.
- 그 전에 해당 클래스랑 아규먼트 리졸버를 모아둔 패키지를 생성하겠습니다. argumentresolver 라는 이름의 패키지를 생성합니다. 그리고 해당 패키지에 헤더의 정보를 담을 HeaderInfo.java 클래스를 생성합니다.
- 이러한 HeaderInfo 클래스는 Map을 직접 사용할 수 없기 때문에 그냥 필드로 Map을 하나 가지고 있고 실제 HeaderInfo 생성자에서 Map이 생성되도록 작성합니다. 그리고 값을 넣고 꺼낼 수 있는 put(), get() 메서드를 정의합니다.
- 다음은 HandlerMathodArgumentResolver 인터페이스를 구현하고 있는 HeaderMapArgumentResolver.java 라는 클래스를 작성합니다. HandlerMathodArgumentResolver 인터페이스는 resolveArgument와 supportsParameter, 두 가지 메서드를 가지고 있습니다.
- Controller 메서드의 인자가 네 개일 경우에 supportsParameter 메서드가 네 번 호출이 됩니다. 그러니까 supportsParameter는 resolver가 적용 가능한지 검사하는 역할을 합니다.
- supportsParameter는 컨트롤러 메서드의 인자의 정보를 파라미터로 전달받는데, 해당 파라미터 정보에 원하는 정보가 있다면 true를 반환하고, 없다면 false를 반환하도록 합니다.
- 여기서 파라미터 타입이 방금 만든 HeaderInfo라는 클래스 타입이면 true를 리턴하도록 메서드를 작성하겠습니다.
- 그리고 supportsParameter가 true를 리턴할 경우에만 resolveArgument 메서드가 호출이 돼요. 그리고 이 resolveArgument가 리턴한 값은 Controller 메서드의 인자로 전달이 되는 겁니다.
- resolveArgument로 넘어온 모든 헤더 정보를 HeaderInfo 객체에 담아서 리턴을 합니다.
- 먼저 HeaderInfo 객체를 하나 생성하고 이때 넘어온 NativeWebRequest 로부터 헤더의 name들을 Iterator 형태로 꺼냅니다. 그리고 while 문 안에서 헤더의 이름과 헤더의 value를 얻어내서 headerInfo에다가 put() 메서드로 값을 넣어줍니다.
- 그리고 확인을 위해서 임시로 콘솔에 출력을 합니다. 해당 부분이 실행이 되면 헤더에 어떤 어떤 정보들이 들어있는지 콘솔에 출력해서 알아볼 수 있을 것 같습니다.
- 생성한 아규먼트 리졸버를 적용을 하려면 WebMvcConfiguration 클래스에다가 addArgumentResolver라는 메서드를 오버라이딩하고 인자로 넘어온 아규먼트 리졸버에 앞에서 생성한 아규먼트 리졸버를 넘겨줄 수 있도록 추가합니다.
- 여기까지 아규먼트 리졸버를 생성하고 생성한 아규먼트 리졸버를 등록을 하였습니다.
- 그러면 Controller에서 메서드를 호출할 때 아규먼트 리졸버가 메서드의 파라미터에 대한 작업을 수행하여 조건에 맞으면 해당 파라미터에 대한 처리를 합니다.
- 그래서 메서드의 파라미터에 해당 객체인 headerInfo를 넘겨야 합니다. list 메서드의 파라미터에 headerInfo를 추가하고 headerInfo의 get() 메서드에다가 user-agent를 넘기면 값이 출력됩니다.
- 페이지에 접속하면 콘솔에 헤더 정보와 user-agent 정보가 나오고 있는 것을 확인할 수 있습니다.
실습코드
HeaderInfo.java
package kr.or.connect.guestbook.argumentresolver;
import java.util.HashMap; import java.util.Map;
public class HeaderInfo { private Map<String, String> map;
public HeaderInfo() { map = new HashMap<>(); }
public void put(String name, String value) { map.put(name, value); }
public String get(String name) { return map.get(name); }
} |
HeaderMapArgumentResolver.java
package kr.or.connect.guestbook.argumentresolver;
import java.util.Iterator;
import org.springframework.core.MethodParameter; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer;
public class HeaderMapArgumentResolver implements HandlerMethodArgumentResolver {
@Override public boolean supportsParameter(MethodParameter parameter) { return parameter.getParameterType() == HeaderInfo.class; }
@Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
HeaderInfo headerInfo = new HeaderInfo();
Iterator<String> headerNames = webRequest.getHeaderNames(); while(headerNames.hasNext()) { String headerName = headerNames.next(); String headerValue = webRequest.getHeader(headerName); // System.out.println(headerName + " , " + headerValue); headerInfo.put(headerName, headerValue); }
return headerInfo; }
} |
생각해보기
- 컨트롤러 메소드에서 자주 사용되는 값이 있을 경우 아규먼트 리졸버를 만들어서 넘겨주도록 하면 편리하게 사용할 수 있습니다. 아규먼트 리졸버에 대한 예를 인터넷에서 찾아보시고 어떤 값을 넘기면 유용할지 고민해 보세요.
참고 자료
[참고링크] A Custom Data Binder in Spring MVC
http://www.baeldung.com/spring-mvc-custom-data-binder
[참고링크] Using custom arguments in Spring MVC controllers
https://sdqali.in/blog/2016/01/29/using-custom-arguments-in-spring-mvc-controllers/
'부스트코스 웹 프로그래밍 > 5. 웹 앱 개발: 예약서비스 3' 카테고리의 다른 글
7. 아규먼트 리졸버 - BE (1) (0) | 2019.08.10 |
---|---|
6. 인터셉터 - BE (2) (0) | 2019.08.10 |
6. 인터셉터 - BE (1) (0) | 2019.08.10 |
5. Spring 에서의 Session 사용법 - BE (0) | 2019.08.10 |
4. 상태유지기술(Cookie & Session) - BE (5) (0) | 2019.08.09 |