GET
를 제공하는 컨트롤러가 있다고 가정하십시오.
요청하고 Bean을 JSON으로 직렬화하고 리턴하여
IllegalArgumentException
에 대한 예외 핸들러를 제공합니다.
그것은 서비스에서 제기 될 수 있습니다 :
@RequestMapping(value = "/meta/{itemId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public MetaInformation getMetaInformation(@PathVariable int itemId) {
return myService.getMetaInformation(itemId);
}
@ExceptionHandler(IllegalArgumentException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
@ResponseBody
public String handleIllegalArgumentException(IllegalArgumentException ex) {
return ExceptionUtils.getStackTrace(ex);
}
메시지 변환기 :
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
<bean class="org.springframework.http.converter.StringHttpMessageConverter" />
</mvc:message-converters>
</mvc:annotation-driven>
이제 브라우저에서 지정된 URL을 요청하면 올바른 JSON 응답이 표시됩니다. 그러나 예외가 발생하면 문자열로 된 예외도 JSON으로 변환되지만
StringHttpMessageConverter
에서 처리되도록하고 싶습니다.
(결과
text/plain
MIME 유형). 어떻게해야합니까?
사진을 더 완전하고 복잡하게 만들기 위해 다음 핸들러도 있다고 가정합니다.
@RequestMapping(value = "/version", method = RequestMethod.GET)
@ResponseBody
public String getApplicationVersion() {
return "1.0.12";
}
이 핸들러는 리턴 문자열이 두
MappingJackson2HttpMessageConverter
에 의해 직렬화 될 수 있도록합니다.
그리고
StringHttpMessageConverter
통과 한
Accept-type
에 따라
클라이언트에 의해. 반환 유형과 값은 다음과 같아야합니다.
+ ---- + --------------------- + ---------------------- -+ ------------------ + ----------------------------- -------- + | NN | URL | 수락 유형 | 컨텐츠 유형 | 메시지 변환기 | | | | 요청 헤더 | 응답 헤더 | | + ---- + --------------------- + ---------------------- -+ ------------------ + ----------------------------- -------- + | 1. |/버전 | 텍스트/html;*/* | 텍스트/일반 | StringHttpMessageConverter | | 2. |/버전 | 응용 프로그램/json;*/* | 응용 프로그램/json | MappingJackson2HttpMessageConverter | | 3. |/meta/1 | 텍스트/html;*/* | 응용 프로그램/json | MappingJackson2HttpMessageConverter | | 4. |/meta/1 | 응용 프로그램/json;*/* | 응용 프로그램/json | MappingJackson2HttpMessageConverter | | 5. |/meta/0 (예외) | 텍스트/html;*/* | 텍스트/일반 | StringHttpMessageConverter | | 6. |/meta/0 (예외) | 응용 프로그램/json;*/* | 텍스트/일반 | StringHttpMessageConverter | + ---- + --------------------- + ---------------------- -+ ------------------ + ----------------------------- -------- +
-
답변 # 1
-
답변 # 2
문제와 관련된 몇 가지 측면이 있습니다 :
@ExceptionHandler(Exception.class) public ResponseEntity<String> handleIllegalArgumentException(Exception ex) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.TEXT_PLAIN); return new ResponseEntity<String>(ex.getMessage(), headers, HttpStatus.BAD_REQUEST); }
catch-all MIME 유형StringHttpMessageConverter
추가*/*
동안 지원되는 미디어 유형 목록MappingJackson2HttpMessageConverter
에 묶여있다 만.와이즈 비즈
간단한 경우 해결책은application/json
를 제공하고 있습니다 이 값은@RequestMapping
에 저장됩니다. (produces = ...
참조) ) 및 오류 처리기가 호출되면이 MIME 유형이 자동으로 상속되어 사용됩니다.HttpServletRequest
를 넣는 것입니다. 목록에서 첫 번째 :RequestMappingInfoHandlerMapping.handleMatch()
또한
StringHttpMessageConverter
를 제거<mvc:annotation-driven> <mvc:message-converters> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes"> <array> <util:constant static-field="org.springframework.http.MediaType.TEXT_PLAIN" /> </array> </property> </bean> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" /> </mvc:message-converters> </mvc:annotation-driven>
에서 주석 :produces
지금 :
@RequestMapping
@RequestMapping(value = "/meta/{itemId}", method = RequestMethod.GET) @ResponseBody public MetaInformation getMetaInformation(@PathVariable int itemId) { return myService.getMetaInformation(itemId); }
만 모든 유형을 버립니다. 처리 할 수 있음 (StringHttpMessageConverter
MappingJackson2HttpMessageConverter
등) 더 전달 될 수 있도록 허용(5, 6) 시나리오에서 예외가 발생한 경우
MetaInformation
우선권을 갖습니다.지금까지는 좋지만 불행히도
java.util.Collection
를 사용하면 상황이 더 복잡해집니다. . 핸들러 리턴 유형StringHttpMessageConverter
이 메시지 변환기는이 유형을ObjectToStringHttpMessageConverter
로 변환 할 수 있다고보고합니다. . 컬렉션 요소 유형이 지워지고java.util.Collection<MetaInformation>
라는 사실에서 한계가 발생합니다. 방법은java.lang.String
를 얻는다 그러나 변환 단계AbstractHttpMessageConverter.canWrite(Class<?> clazz, MediaType mediaType)
에 관해서는 확인을위한 클래스 실패합니다. 문제를 해결하기 위해 우리는java.util.Collection<?>
를 유지ObjectToStringHttpMessageConverter
를 위해 JSON 변환기를 사용해야하는 주석이지만 예외 핸들러에 대한 올바른 내용 유형을 강제하기 위해produces
를 지 웁니다.@RequestMapping
의 속성 :HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE
컨텍스트는 원래와 동일하게 유지됩니다 :
HttpServletRequest
현재 시나리오 (1,2,3,4)는 컨텐츠 유형 협상으로 인해 올바르게 처리되며 시나리오 (5,6)는 예외 처리기에서 처리됩니다.
대신 콜렉션 반환 유형을 배열로 대체 할 수 있으며 솔루션 # 1을 다시 적용 할 수 있습니다 :
@ExceptionHandler(IllegalArgumentException.class) @ResponseStatus(value = HttpStatus.BAD_REQUEST) @ResponseBody public String handleIllegalArgumentException(HttpServletRequest request, IllegalArgumentException ex) { request.removeAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE); return ExceptionUtils.getStackTrace(ex); } @RequestMapping(value = "/meta", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody public Collection<MetaInformation> getMetaInformations() { return myService.getMetaInformations(); }
토론 :
나는 그<mvc:annotation-driven> <mvc:message-converters> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" /> <bean class="org.springframework.http.converter.ObjectToStringHttpMessageConverter"> <property name="conversionService"> <bean class="org.springframework.context.support.ConversionServiceFactoryBean" /> </property> <property name="supportedMediaTypes"> <array> <util:constant static-field="org.springframework.http.MediaType.TEXT_PLAIN" /> </array> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>
생각 값에서 클래스를 상속해서는 안되고 메소드 서명에서 클래스를 상속해야합니다.@RequestMapping(value = "/meta", method = RequestMethod.GET) @ResponseBody public MetaInformation[] getMetaInformations() { return myService.getMetaInformations().toArray(); }
와
AbstractMessageConverterMethodProcessor.writeWithMessageConverters()
다음으로 변경해야합니다 :Type returnValueType = returnType.getGenericParameterType();
또는 (클래스 기반 컨버터가 너무 제한적인 경우)
HttpMessageConverter.canWrite(Class<?> clazz, MediaType mediaType)
그러면 매개 변수화 된 유형을 올바르게 처리하고 솔루션 # 1을 다시 적용 할 수 있습니다.
canWrite(Type returnType, MediaType mediaType)
관련 자료
- c# - NET 5 예외 발생 콘텐츠 스트림 오류
- javascript - 현재 클릭 한 버튼과 일치하도록 안의 콘텐츠를 변경하려면 어떻게해야합니까?
- powerquery - 기준에 따라 다른 열에서 선택하도록 열의 내용을 변경하고 열에서 선택할 때 해당 열을 비워 두는 방법
- javascript - 모든 드롭 다운 메뉴의 텍스트 콘텐츠는 개별적으로 업데이트하는 대신 동시에 변경됩니다
- ios - 우선 순위를 통해 고유 콘텐츠 크기를 변경하는 방법
- php - 속성을 변경하지 않고 단축 코드 내부의 콘텐츠를 변경하는 방법은 무엇입니까?
- dplyr - 아르 자형 - 기능이있는 열 내용을 새 내용으로 변경
- python - 파일 내용 읽기가 잘못된 경우 사용할 예외
- javascript - HTML5 맞춤 데이터 속성에서 div 콘텐츠 변경
- macos - Safari에서 콘텐츠 보안 정책을 변경하거나 비활성화 하시겠습니까?
- Python에서 함수를 적용한 후 목록 내용을 변경하는 방법
- python - Entry에서와 마찬가지로 canvascreate_text의 내용을 클릭하여 변경할 수 있습니까?
- python - discordpy에서 예외 (유형 오류)를 발생시키는 오류 처리기
- reactjs - 값이 변경되지 않는 핸들러가 작동하지 않는 이유는 무엇입니까?
- javascript - magnific popup - 프로그래밍 방식으로 콘텐츠를 팝업 양식에서 모달 스피너로 변경 한 다음 다시 양식으로 변경
- node.js - NodeJS를 사용하여 JSON 내용 변경
- c# - aspnet core razor - 전역 예외 처리기
- Powershell/XAML의 XML 파일에서 버튼의 내용을 변경하는 방법은 무엇입니까?
- javascript - fullcalendar v5에서 빈 이벤트 선택 내용을 변경하는 방법은 무엇입니까?
- c# - 다른 메서드 내에서 textBlock의 내용을 동적으로 변경하는 방법은 무엇입니까?
- spring - Java 개체 목록에 포함되지 않은 개체 찾기
- 메소드 매개 변수가있는 Spring AOP Aspect 어드바이스
- spring - JSP에서 첫 번째 열에 홀수 데이터를 표시하고 두 번째 열에 데이터를 표시하는 방법은 무엇입니까?
- spring - FilterRegistrationBean과 DelegatingFilterProxy의 차이점은 무엇입니까?
- spring boot - restcontroller에서 인터셉터의 데이터에 액세스
- java - 원인 - orgspringframeworkbeanspropertybatchupdateexception : jdbc 드라이버 클래스 [oraclejdbcdriveroracledriver]를로드 할 수 없습니다
- java - JSP에서 중첩 목록의 값을 검색하여 양식으로 다시 보냅니다
- spring - 네트워크가 가까운 곳에서 부팅 프로젝트를 시작할 수 없습니다
- java - 절대 uri - [http://wwwspringframeworkorg/tags/form]은 webxml 또는이 응용 프로그램과 함께 배포 된 jar 파일에서 확인할 수 없습니다
- spring mvc 프로젝트에서 URL을 어디에 지정합니까?
나는
produces = MediaType.APPLICATION_JSON_VALUE
를 제거 생각@RequestMapping
에서 Wyzwyz의 원하는 결과를 제공합니다.응답 유형은 수락 헤더의 내용 유형 값에 따라 협상됩니다.
<시간>수정
이 시나리오 3,4를 다루지 않기 때문에 여기
getMetaInformation
와 함께 작동하는 솔루션이 있습니다. 직접 :