我有一个基于Spring MVC的 Rest web 服务。我使用 a@RestControllerAdvice
来处理从我的 s 抛出的异常@Controller
。
控制器
调用示例如下
@GetMapping(value = "/{id}/{name:.+}", produces = { MediaType.APPLICATION_OCTET_STREAM_VALUE,
MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE })
ResponseEntity<byte[]> getSomething(
@PathVariable("id") String id, @PathVariable("name") String name) throws customException;
一种可以产生 3 种媒体类型的 基本APPLICATION_OCTET_STREAM_VALUE
方法:APPLICATION_XML_VALUE
APPLICATION_JSON_VALUE
customException
异常处理程序
my 的定义@RestControllerAdvice
如下:
@ExceptionHandler({ CustomException.class })
public ResponseEntity<Object> handleException(CustomException e) {
ErrorDto err = errorMapper.map(e);
Enumeration<String> en = httpServletRequest.getHeaders(HttpHeaders.ACCEPT);
while (en.hasMoreElements()) {
String list = en.nextElement();
StringTokenizer st = new StringTokenizer(list, ",");
while (st.hasMoreTokens()) {
String acc = st.nextToken();
MediaType contentTypeHeader = MediaType.valueOf(acc);
if (MediaType.APPLICATION_XML.includes(contentTypeHeader)) {
JAXBElement<ErrorDto> ret = new ObjectFactory().createError(err);
return ResponseEntity.status(HttpStatus.PRECONDITION_FAILED)
.contentType(MediaType.APPLICATION_XML).body(ret);
} else if (MediaType.APPLICATION_JSON.includes(contentTypeHeader)) {
return ResponseEntity.status(HttpStatus.PRECONDITION_FAILED)
.contentType(MediaType.APPLICATION_JSON).body(err);
}
}
}
return ResponseEntity.status(HttpStatus.NOT_ACCEPTABLE).body(null);
}
根据请求accept header,如果没有设置accept,则@ExceptionHandler
返回null body和NOT_ACCEPTABLE
http响应状态,ErrorDto
如果accept是typeAPPLICATION_JSON
或者JaxbElement
ofErrorDto
是accept是type ,则返回type对象APPLICATION_XML
请注意,当响应包含正文时,我指定了响应的内容类型。
问题
我的问题是当客户端使用多个接受标头进行调用时,Spring 会尝试HttpMessageConverter
根据接受标头而不是响应内容类型来获取。下面是一个例子:
当客户端调用一个引发异常(然后返回 errorDto)的方法时,具有多个 Accept 标头,如下所示:
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_OCTET_STREAM_VALUE);
headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_XML_VALUE);
HttpEntity<?> entity = new HttpEntity<>(body, headers);
restTemplate.exchange(uriComponents.encode().toUri(), httpMethod, entity, Class);
Spring 未按预期返回带有 XML 格式错误的响应。它寻找一个Octet-Stream <-> JaxbElement
不存在的转换器,并且不尝试根据响应内容类型找到转换器。
如何根据响应内容类型强制 Spring 使用转换器?
我在用着 :
- Spring Boot 1.4.0.RELEASE