2013-06-06 2 views
3

JSON과 HTML을 모두 소비/생성하는 스프링 MVC 3.2 컨트롤러를 작성하려고합니다. 클라이언트에서 Accept 헤더 중 하나 text/html 또는 application/json,클라이언트가 받아 들일 때 다른 콘텐츠 형식보다 텍스트/html 우선 순위 지정 */*

이 포함 된 경우

@Controller 
public class FooController { 
    @RequestMapping(value="/foo", produces="text/html") 
    public String fooHTML() { 
     // ... 
    } 

    @RequestMapping(value="/foo", produces="application/json") 
    public String fooJSON() { 
     // ... 
    } 
} 

이 화려하게 작동하지만 다음 Internet Explorer가 있었다 : 나는 다른 콘텐츠 유형을 생산하는 두 개의 핸들러 방법이있다. here으로 언급했듯이 IE의 Accept 헤더는 다양하지만 끝에는 text/html이 포함되지 않으며 항상 끝에 */*이 있습니다. Spring이 IE로부터 요청을 받으면 내 콘트롤러에 의해 생성 된 콘텐트 타입과 직접적으로 같은 콘텐트 타입을 볼 수 없지만, */* 와일드 카드를 래치하면 두 매핑이 모두 적용될 것이라고 (정확하게) 결정된다.

여러 일치하는 핸들러 맵핑에 직면 한 Spring은 RequestMappingHandlerMapping 빈에서 기본적으로 사전 순서에 해당하는만큼 맵핑을 정렬하고 첫 x 째를 선택하고 계속 이동합니다. 저의 관점에서이 문제는 text/html을 우선으로하여 application/json을 우선시합니다. 클라이언트가 특별히 application/json을 요청하지 않는 한, 오히려 text/html을 반환하는 편이 낫습니다. 그런 식으로 IE와 같은 바보 같은 클라이언트에게 HTML을 제공하고 JSON을 내 API 사용자와 같은 콘텐츠 유형에 익숙한 클라이언트에게 제공 할 수 있습니다.

핸들러를 다르게 정렬하기 위해 RequestMappingHandlerMapping을 확장 할 필요가없는 사람이이를 수행하는 방법을 알고 있습니까? 간단한 해결 방법이 있습니까?

참고 : on the Spring blog으로 설명한 ContentNegotiationManager에서 기본 콘텐츠 형식을 설정해 보았습니다. Accept 헤더가 지정되지 않은 경우에만 해당 설정이 적용되므로 내 문제는 해결되지 않습니다.

답변

1

하나의 해결책은 fooJSON()의 우선 순위를 value 매개 변수로 낮추는 것입니다.

실제적으로 패턴 /foo/foo{1}은 동일합니다. 두 번째는하지만, "보다 일반적인"로 간주되며, 마지막으로 사용됩니다

@Controller 
public class FooController { 
    @RequestMapping(value="/foo", produces="text/html") 
    public String fooHTML() { 
     // ... 
    } 

    @RequestMapping(value="/foo{1}", produces="application/json") 
    //       ^^^------- changed here 
    public String fooJSON() { 
     // ... 
    } 
} 

이 방법 :

  • text/htmlfooHTML()
  • application/json로 이동 fooJSON()
  • */*가 간다에 간다 fooHTML()
  • 기타 406 - Not Acceptable 오류
+0

"다른 것"은 무엇을 의미합니까? '*/*'에 매핑되지 않는 것이 있습니까 ??? –

+0

내 의견을 무시하고 ... 당신이 그것을 의미하는 것을 깨달았습니다. –

+0

매우 창의적입니다. 나는 그것을 생각하지 않았을 것이다. 불행히도, 그것은 수용 할 수없는 어떤 방식으로 나를 제한합니다. '/ foo/{1}'-> JSON 매핑과'/ foo/{/ foo/{/ foo}} '를 선언하면 두 콘텐츠 유형 모두에 응답하기 위해/foo/someID} /'-> HTML 매핑, 중첩,/foo/some-foo-id /와'*/* '는 JSON을 선택합니다. –

1

이 문제를 해결하는 방법 중 하나는 HTML 버전의 응답을 제공하는 요청 매핑에 ALL mimetype을 추가하는 것입니다.

@RequestMapping(value="/foo", produces={"text/html", "*/*"}) 
public String fooHTML() { 
    // ... 
} 

이것은 이전에 매핑되지 않은 MIME 형식에 대해 HTML 응답이 제공됨을 의미합니다. 필자의 경우에는 그 동작이 바람직하지만 406 (Not Acceptable) 응답 코드를 반환해야하는 경우이 코드는 작동하지 않습니다.