【发布时间】:2021-12-03 02:13:24
【问题描述】:
我仍然是 Spring Boot 的新手,但我有一个 Web 应用程序,它设置为处理 XML 请求(当请求具有“Content-type: application/xml”标头时)或 JSON 请求(当请求有一个“内容类型:应用程序/xml”标头),我注意到如果“内容类型”标头丢失,或者包含“内容类型:应用程序/xml”或“内容类型”以外的其他内容: application/json”,我收到“415”响应错误代码。日志还显示如下消息:
.w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/x-www-form-urlencoded' not supported]
我发现了这个较旧的 SO 线程:
Springboot exception handler doesn't catch exception
并且一直在尝试实现由“Sannu”于 2016 年 12 月 17 日 13:55 发布的代码。这是我构建并正在测试的代码(作为测试,我试图将错误响应代码更改为“500”并且还有错误响应消息):
import org.apache.logging.log4j.LogManager;
import org.springframework.http.ResponseEntity;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;
import mil.nga.geoaxis.pdp.models.ErrorResponse;
import org.springframework.http.HttpStatus;
@ControllerAdvice
public class SpringExceptionHandler extends ExceptionHandlerExceptionResolver
{
@ExceptionHandler(org.springframework.web.HttpMediaTypeNotSupportedException.class)
public ResponseEntity<Object> handleControllerException(HttpMediaTypeNotSupportedException ex, WebRequest req)
{
ErrorResponse errorResponse = null;
//ex.printStackTrace();
errorResponse = new ErrorResponse();
errorResponse.setCode(HttpCodes.HTTP_CODE_INTERNAL_ERROR);
System.out.println("In SpringExceptionHandler.handleControllerException: HttpStatus.INTERNAL_SERVER_ERROR.value()=[" + HttpStatus.INTERNAL_SERVER_ERROR.value() + "]");
System.out.println("In SpringExceptionHandler.handleControllerException: ex.getMessage()=[" + ex.getMessage() + "]");
int myCode = errorResponse.getCode();
System.out.println("In SpringExceptionHandler.handleControllerException: errorResponse.getCode()/String.valueOf(myCode)=[" + String.valueOf(myCode) + "]");
errorResponse.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
errorResponse.setMessage(ex.getMessage());
myCode = errorResponse.getCode();
System.out.println("In SpringExceptionHandler.handleControllerException: errorResponse.getCode()/String.valueOf(myCode)=[" + String.valueOf(myCode) + "]");
return new ResponseEntity<Object>(errorResponse, HttpStatus.valueOf(errorResponse.getCode()));
}
}
但是,当我测试并发送一个没有“Content-type:”标头的请求(使用 curl)时,我仍然收到看起来是带有“100”响应代码的响应,然后是带有“ 415" 响应代码,没有响应消息。
仅供参考,这是正在出现的日志记录的一部分:
In SpringExceptionHandler.handleControllerException: HttpStatus.INTERNAL_SERVER_ERROR.value()=[500]
In SpringExceptionHandler.handleControllerException: ex.getMessage()=[Content type 'application/x-www-form-urlencoded' not supported]
In SpringExceptionHandler.handleControllerException: errorResponse.getCode()/String.valueOf(myCode)=[0]
In SpringExceptionHandler.handleControllerException: errorResponse.getCode()/String.valueOf(myCode)=[500]
WARN 15428 --- [io-18443-exec-1] .m.m.a.ExceptionHandlerExceptionResolver : Failure in @ExceptionHandler ....errorhandling.SpringExceptionHandler#handleControllerException(HttpMediaTypeNotSupportedException, WebRequest)
谁能指出为什么这似乎无法发送错误代码和响应消息?
[仅供参考,我在 Spring Boot 2.5.6 下执行此操作。]
提前致谢!
吉姆
编辑 1:我根据 huy 的建议修改了这个类:
import org.apache.logging.log4j.LogManager;
import org.springframework.http.ResponseEntity;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;
@ControllerAdvice
public class SpringExceptionHandler
{
@ExceptionHandler(org.springframework.web.HttpMediaTypeNotSupportedException.class)
public ResponseEntity handleControllerException(HttpMediaTypeNotSupportedException ex, WebRequest req)
{
ErrorResponse errorResponse = null;
//ex.printStackTrace();
errorResponse = new ErrorResponse();
//errorResponse.setCode(HttpCodes.HTTP_CODE_INTERNAL_ERROR);
System.out.println("In SpringExceptionHandler.handleControllerException: HttpStatus.INTERNAL_SERVER_ERROR.value()=[" + HttpStatus.INTERNAL_SERVER_ERROR.value() + "]");
System.out.println("In SpringExceptionHandler.handleControllerException: ex.getMessage()=[" + ex.getMessage() + "]");
int myCode = errorResponse.getCode();
System.out.println("In SpringExceptionHandler.handleControllerException: errorResponse.getCode()/String.valueOf(myCode)=[" + String.valueOf(myCode) + "]");
errorResponse.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
errorResponse.setMessage(ex.getMessage());
myCode = errorResponse.getCode();
System.out.println("In SpringExceptionHandler.handleControllerException: errorResponse.getCode()/String.valueOf(myCode)=[" + String.valueOf(myCode) + "]");
return ResponseEntity
.status(HttpStatus.valueOf(415))
.body(ex.getMessage());
}
}
上面的代码会导致错误代码为 415 的响应,以及来自 HttpMediaTypeNotSupportedException 异常的文本错误消息。
【问题讨论】:
-
其实不需要扩展ExceptionHandlerException...,默认是用来解决错误的。你只需要ControllerAdvice和ExceptionHandler,ExceptionHandlerExceptionResolver会自动扫描注解ExceptionHandler并进行处理。
-
喂——你能澄清一下吗?你是说如果我只是创建 SpringExceptionHandler 类(并且它不扩展 ExceptionHandlerExceptionResolver),那么 handleControllerException() 方法将能够成功返回 ResponseEntity 并导致我想要的响应?吉姆
-
extend ExceptionHandlerExceptionResolver 很奇怪,有时可能会导致解析器冲突...我不推荐它...顺便说一下,spring 的默认解析器会自动检测和处理注释 ExceptionHandler.. .
-
huy - 我让它工作(有点),并将使用新/最终代码更新原始帖子。您可以将您的评论更改为答案,以便我可以选择它吗?谢谢!
-
我添加了答案
标签: java spring-boot