성윤님이 코드로 등록해 로그를 찍어 공개하는 바람에 김이 빠져버린 퀴즈. 원래 문제만 보고 푸는 퀴즈였는데…
어쨌든 답을 정리하고 설명해보자. 매번 로그 찍어가며 원하는 요청 조건을 찾아낼 수는 없으니까 각 요청조건의 적용 규칙을 알아야지.
@RequestMapping의 각 항목은 RequestCondition 타입으로 만들어진 요청조건 클래스로 정의된다. @RequestMapping의 엘리먼트 타입은 모두 배열이니 {}를 이용해 복수개 설정이 가능하다. 또, 타입레벨과 메소드 레벨 양쪽에 정의가 가능하다. 최종 적용은 메소드 단위이니 타입 레벨의 조건과 어떻게 결합되는지 알아야 한다. 여기에 수퍼 클래스나 인터페이스의 타입&메소드 레벨 조건도 결합할 수 있으니 단순하게 봐도 조합 방법이 엘리먼트 값 여러 개 * 메소드&타입 * 수퍼 타입&메소드 해서 최소 8가지. 문제는 요청조건마다 엘리먼트 값의 조합이나 메소드&타입 조합방법이 다르다는 것.
문제를 살펴보자.
1.
@Controller
@RequestMapping({“/a”, “/b”})
public class MyController {
@RequestMapping({“/c”, “/d”})
public void hello() {}
이건 URL경로 조건. 디폴트 엘리먼트라 value로 해도 되고, 단독으로 사용되면 엘리먼트 이름은 생략 가능.
각 엘리먼트 값의 조합은 OR. 메소드만 놓고 보면 /c 또는 /d.
타입과 메소드의 조합도 OR이지만 단순히 a,b,c,d로 조합하는게 아니라 타입 경로+메소드 경로로 결합 가능한 모든 경우로 조합한다는 것이 특징이다. 결국 /a/c, /a/d, /b/c, /b/d의 네 가지 조합이 만들어지고 OR로 결합되니 이 중의 하나면 된다. AND라면 말이 안되니까. 한가지 주의할 점은 다른 조건과 다르게 URL을 조건을 지정안 한다고 조건을 다 만족하는게 아니다. URL조건이 없으면 ""인데 suffix / 규칙 때문에 "/”나 마찬가지다. 결국 서블릿 매핑의 루트 URL에 연결된다.
최종 요청조건은 {[/a/c || /a/d || /b/c || /b/d], methods=[], params=[], headers=[], consumes=[], produces=[], custom=[]} 으로 표현된다. 스프링 로그를 찍어보면 조합된 조건이 이렇게 간결한 식으로 나온다.
2.
@Controller
@RequestMapping(params={“a”, “b”})
public class MyController {
@RequestMapping(params={“c”, “d”})
public void hello() {}
파라미터 조합은 AND다. 엘리먼트 값들도 AND로. 타입, 메소드도 AND로 따라서 최종 조건은 한 가지다. 위의 매핑이라면 파라미터에 a,b,c,d 네 가지가 다 존재해야지만 조건 만족.
조건식은 {[], methods=[], params=[a && b && c && d], headers=[], consumes=[], produces=[], custom=[]}
3.
@Controller
@RequestMapping(headers={“a”, “b”})
public class MyController {
@RequestMapping(headers={“c”, “d”})
public void hello() {}
헤더 조건도 파라미터와 동일하게 타입, 메소드, 엘리먼트 값이 모두 AND로 조합된다. 매핑 가능한 요청조건은 한 가지.
조건식은 {[], methods=[], params=[], headers=[a && b && c && d], consumes=[], produces=[], custom=[]}
여기까지는 쉬운데 다음부터는 좀 정확한 이해가 필요하다.
4.
@Controller
@RequestMapping(headers={“a”, “Content-Type=application/json”, “Content-Type=multipart/form-data”})
public class MyController {
@RequestMapping(headers={“c”, “d”})
public void hello() {}
타입에 헤더 조건이 3개, 메소드에 2개다. 헤더 조건은 AND 조합이라고 했으니 결국 조건은 한 가지?
아니다. 두 가지다. header로 정의했더라도 Context-Type은 무시된다. 헤더 조건은 a,c,d 세 가지만 적용된다. Content-Type은 대신 3.1에 새로 등장한 consumes 조건으로 바뀐다. 따라서 타입에 붙은 두 개의 Content-Type 헤더 조건 두 가지는 consumes에 정의된 것으로 취급되는데, consumes는 헤더 값을 이용하지만 다른 헤더와 달리 AND가 아니라 OR조건이다. 따라서 헤더 조건 3가지가 AND로 묶이고, Content-Type 두 가지는 OR로 묶여서 최종적으로 2가지 요청조건이 만들어진다.
Content-Type은 headers에서 무시하고 몰래 consumes로 처리하는 이유는 뭔가? headers에서 안 쓸 거면 에러를 내든가하지. 왜냐하면 3.0에서 작성된 코드를 3.1에서 사용될 수 있도록 하기 위해서다. 구버전 호환성을 목숨처럼 지키는 스프링 다운 해결책이다.
조건식은 {[], methods=[], params=[], headers=[a && c && d], consumes=[application/json || multipart/form-data], produces=[], custom=[]}
5.
@Controller
@RequestMapping(headers={“a”, “b”})
public class MyController {
@RequestMapping(headers={“c”, “d”, “Content-Type=application/json”}, consumes=”multipart/form-data”)
public void hello() {}
4번 문제의 응용이다. 일반 헤더 조건은 AND로 결합해서 한 가지. Content-Type헤더는 consumer로 넘어가므로 consumes가 결국 두 가지가 된다. consumes는 OR이니까 최종 요청조건은 두 가지.
조건식은 {[], methods=[], params=[], headers=[a && b && c && d], consumes=[application/json || multipart/form-data], produces=[], custom=[]}
6.
@Controller
@RequestMapping(consumes={“application/xml”, “application/x-www-form-urlencoded”})
public class MyController {
@RequestMapping(consumes={”multipart/form-data”, “application/json”})
public void hello() {}
consumes는 다른 조건과 다르게 메소드 조건이 타입 조건을 오버라이딩하는 식이다. 타입만 있으면 타입 조건을 쓰지만 메소드 조건이 있으면 타입 조건을 무시한다. 그래서 이건 메소드 조건 두 가지만 OR로 결합되서 두 가지.
조건식은 {[], methods=[], params=[], headers=[], consumes=[multipart/form-data || application/json], produces=[], custom=[]}
정답은 4,1,1,2,2,2
그럼 수퍼 클래스나 인터페이스의 타입&메소드 레벨에 붙은 @RequestMapping과의 조합은? 그건 http://toby.epril.com/?p=1207 에서 설명한 스프링의 일반적인 오버라이딩스러운 규칙을 적용하면 된다.
Related posts:
- 스프링 3.1 (10) 심심풀이 @RequestMapping 요청 조건 퀴즈
- Inside Spring (6) 애노테이션 설정 지원 스프링 웹 테스트용 DispatcherServlet 만들기
- Spring 상식퀴즈 (1) – DI 태클하기
- Spring 3.0 EL (Spel)을 이용한 AssertThrows 확장 (2)
- S1A 2008 둘째날 – Grails
- 토비의 스프링 3 간략 목차
- 스프링 빈의 이름은 한글로 지어도 된다
- Spring 3.0 (58) Static Class를 XML없이 빈으로 등록하기
- Spring 3.0 EL (Spel)을 이용한 AssertThrows 확장 (1)
- 스프링 3.1 (8) web.xml 없는 스프링 개발
- TheSpringExperience 2007 둘째날
- Spring 2.0 XML확장기능 (3)
- Spring 3.0 @MVC 메소드에서 자동으로 리턴 모델에 추가되는 것들
- Spring ROO 대충대충 분석 (2) ROO란 무엇인가?
- S1A 2008 둘째날 SpringSecurity 2.5
Facebook comments:
mbt blood shoe 스프링 3.1 (11) 심심풀이 @RequestMapping 요청 조건 퀴즈 풀이 » Toby’s Epril
free shipping payless shoes 스프링 3.1 (11) 심심풀이 @RequestMapping 요청 조건 퀴즈 풀이 » Toby’s Epril
http://zhuwowo123.com/plus/view.php?aid=27313 스프링 3.1 (11) 심심풀이 @RequestMapping 요청 조건 퀴즈 풀이 » Toby’s Epril
http://www.xinchengyi.net/plus/view.php?aid=465437 스프링 3.1 (11) 심심풀이 @RequestMapping 요청 조건 퀴즈 풀이 » Toby’s Epril
http://www.ooxxbb.com/forum.php?mod=viewthread&tid=91964&fromuid=22893 스프링 3.1 (11) 심심풀이 @RequestMapping 요청 조건 퀴즈 풀이 » Toby’s Epril
mbt reviews 스프링 3.1 (11) 심심풀이 @RequestMapping 요청 조건 퀴즈 풀이 » Toby’s Epril
shimano mtb shoes 스프링 3.1 (11) 심심풀이 @RequestMapping 요청 조건 퀴즈 풀이 » Toby’s Epril
Hi there, I enjoy reading all of your article. I wanted to write a little comment to support you.
thank you for share!
nice articles
Well said Keri! I find my links or photos don’t get as many views as plain text (I’ve been advised this is a facebook controlled thing? If that is even possible but my stats seem to reflect just that!?!?) but I do post a mix of all – more interesting to me and ‘fans’.
des sacs hermes lindy pour femme r茅plique http://www.modetaschen.in/fr/hermes-lindy-34-bags-c17.html
TG4GNdtP crestor generic cost walmart