성윤님이 코드로 등록해 로그를 찍어 공개하는 바람에 김이 빠져버린 퀴즈. 원래 문제만 보고 푸는 퀴즈였는데…

어쨌든 답을 정리하고 설명해보자. 매번 로그 찍어가며 원하는 요청 조건을 찾아낼 수는 없으니까 각 요청조건의 적용 규칙을 알아야지.

@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:

  1. 스프링 3.1 (10) 심심풀이 @RequestMapping 요청 조건 퀴즈
  2. Inside Spring (6) 애노테이션 설정 지원 스프링 웹 테스트용 DispatcherServlet 만들기
  3. Spring 상식퀴즈 (1) – DI 태클하기
  4. Spring 3.0 EL (Spel)을 이용한 AssertThrows 확장 (2)
  5. S1A 2008 둘째날 – Grails
  6. 토비의 스프링 3 간략 목차
  7. 스프링 빈의 이름은 한글로 지어도 된다
  8. Spring 3.0 (58) Static Class를 XML없이 빈으로 등록하기
  9. Spring 3.0 EL (Spel)을 이용한 AssertThrows 확장 (1)
  10. 스프링 3.1 (8) web.xml 없는 스프링 개발
  11. TheSpringExperience 2007 둘째날
  12. Spring 2.0 XML확장기능 (3)
  13. Spring 3.0 @MVC 메소드에서 자동으로 리턴 모델에 추가되는 것들
  14. Spring ROO 대충대충 분석 (2) ROO란 무엇인가?
  15. S1A 2008 둘째날 SpringSecurity 2.5

Facebook comments:

to “스프링 3.1 (11) 심심풀이 @RequestMapping 요청 조건 퀴즈 풀이”

  1. mbt blood shoe 스프링 3.1 (11) 심심풀이 @RequestMapping 요청 조건 퀴즈 풀이 » Toby’s Epril

  2. free shipping payless shoes 스프링 3.1 (11) 심심풀이 @RequestMapping 요청 조건 퀴즈 풀이 » Toby’s Epril

  3. mbt reviews 스프링 3.1 (11) 심심풀이 @RequestMapping 요청 조건 퀴즈 풀이 » Toby’s Epril

  4. shimano mtb shoes 스프링 3.1 (11) 심심풀이 @RequestMapping 요청 조건 퀴즈 풀이 » Toby’s Epril

  5. Hi there, I enjoy reading all of your article. I wanted to write a little comment to support you.

  6. 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

Leave a Reply to michael kors black friday sale 2013 Cancel reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

© 2017 Toby's Epril Suffusion theme by Sayontan Sinha