Java 确定ExceptionHandler中可接受的内容类型
在Spring应用程序中,我有一个通常返回图像的端点(Java 确定ExceptionHandler中可接受的内容类型,java,spring,spring-mvc,spring-boot,Java,Spring,Spring Mvc,Spring Boot,在Spring应用程序中,我有一个通常返回图像的端点(products=MediaType.image\u PNG\u VALUE) 我还有@ExceptionHandler函数来处理各种函数 我正在试图找到一种方法,从@ExceptionHandler中确定客户端是否接受text/plain或text/json,以便在发生错误时,我可以返回其中一个,或者如果他们只希望image/png,则可以忽略它 如何确定可以为给定请求返回哪些可接受的内容类型?您可以访问请求以检查标题并返回适当的响应。这是
products=MediaType.image\u PNG\u VALUE
)
我还有@ExceptionHandler
函数来处理各种函数
我正在试图找到一种方法,从@ExceptionHandler
中确定客户端是否接受text/plain
或text/json
,以便在发生错误时,我可以返回其中一个,或者如果他们只希望image/png
,则可以忽略它
如何确定可以为给定请求返回哪些可接受的内容类型?您可以访问请求以检查标题并返回适当的响应。这是标准的 下面是一个例子:
@ControllerAdvice
public class MyExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(value = {RuntimeException.class})
protected ResponseEntity<Object> handleMyException(RuntimeException ex, WebRequest request) {
List<String> acceptableMimeTypes = Arrays.asList(request.getHeaderValues(HttpHeaders.ACCEPT));
if (acceptableMimeTypes.contains(MediaType.TEXT_PLAIN_VALUE)) {
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE)
.body("hello");
}
throw ex;
}
}
@ControllerAdvice
公共类MyExceptionHandler扩展了ResponseEntityExceptionHandler{
@ExceptionHandler(值={RuntimeException.class})
受保护的ResponseEntity handleMyException(RuntimeException ex,WebRequest请求){
List-acceptableMimeTypes=Arrays.asList(request.getHeaderValues(HttpHeaders.ACCEPT));
if(acceptablemmetypes.contains(MediaType.TEXT\u PLAIN\u VALUE)){
返回ResponseEntity.ok()
.header(HttpHeaders.CONTENT\u类型、MediaType.TEXT\u普通值)
.body(“你好”);
}
掷骰子;
}
}
有一些参数spring mvc
可以自动注入controller
方法,而WebRequest
(即spring
对http
请求的表示)就是其中之一。如果客户端发送了一个带有请求的Accept:text/plain
头,那么上面的示例将返回字符串hello
,如果存在RuntimeException
。如果没有异常,则根本不会触发此逻辑,因此端点将只返回它通常返回的任何内容。您可以阅读有关@ControllerAdvice
和@ExceptionHandler
的更多信息
当然,一定要考虑要处理的确切异常类型,以及要返回的语义上合适的状态代码,以便客户端知道如何正确解释响应。这就是我想到的答案。它与YoungSpice的类似,但更灵活,直接使用MediaType(这意味着它将处理通配符类型,如
text/*
等):
private ResponseEntity buildResponse(WebRequest请求、HttpStatus状态、字符串消息){
HttpHeaders httpHeader=新的HttpHeaders();
列表接受头=
parseMediaTypes(Arrays.asList(request.getHeaderValues(HttpHeaders.ACCEPT));
if(acceptHeader.stream().anyMatch(mediaType->mediaType.isCompatibleWith(mediaType.APPLICATION_JSON))){
httpHeader.setContentType(MediaType.APPLICATION_JSON);
返回新的响应属性(“{\”错误\“:\”+消息+“\”}”,httpHeader,状态);
}else if(acceptHeader.stream().anyMatch(mediaType->mediaType.isCompatibleWith(mediaType.TEXT\u PLAIN))){
httpHeader.setContentType(MediaType.TEXT\u PLAIN);
返回新的响应属性(消息、httpHeader、状态);
}否则{
返回ResponseEntity.status(status).body(null);
}
}
基本上,它使用MediaType.parseMediaTypes()
来解析Accept
头,然后我对它们进行流式处理,并使用MediaType.isCompatibleWith()
函数来检查我的目标是否可接受。这将允许它处理头中类似于application/*
的内容,而不是直接使用application/json
另外,如果请求中没有明确提供
Accept
,则会出现一个隐含的*/*
,它似乎按预期工作。对于下一个投票人,是否愿意分享原因?我问了一个很狭隘的问题。我可以提供一些示例代码,但它不会给问题添加任何内容,至于我的实际问题,我不知道从哪里开始。我可能只需要一两行。
private ResponseEntity<String> buildResponse(WebRequest request, HttpStatus status, String message) {
HttpHeaders httpHeader = new HttpHeaders();
List<MediaType> acceptHeader =
MediaType.parseMediaTypes(Arrays.asList(request.getHeaderValues(HttpHeaders.ACCEPT)));
if (acceptHeader.stream().anyMatch(mediaType -> mediaType.isCompatibleWith(MediaType.APPLICATION_JSON))) {
httpHeader.setContentType(MediaType.APPLICATION_JSON);
return new ResponseEntity<>("{ \"error\": \"" + message + "\" }", httpHeader, status);
} else if (acceptHeader.stream().anyMatch(mediaType -> mediaType.isCompatibleWith(MediaType.TEXT_PLAIN))) {
httpHeader.setContentType(MediaType.TEXT_PLAIN);
return new ResponseEntity<>(message, httpHeader, status);
} else {
return ResponseEntity.status(status).body(null);
}
}