- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
在 Spring 4.x 中,如果您使用扩展 ResponseEntityExceptionHandler
的 @RestControllerAdvise
(或 @ControllerAdvice
),则默认异常处理为漂亮且信息丰富的 JSON 响应正文,默认情况下不再为标记为 @Valid
的参数返回。
在使用基于 ResponseEntityExceptionHandler
的 @RestControllerAdvice
时如何获取要返回的默认 JSON 正文?
以下是描述此问题的简单但完整的示例。使用这些类:
@RestController
class CarsController {
@PostMapping("/cars")
public void createCar(@RequestBody @Valid Car car) {
System.out.println("Creating " + car);
throw new WhateverException();
}
@ExceptionHandler(WhateverException.class)
@ResponseStatus(HttpStatus.EXPECTATION_FAILED)
public void handleWhateverException(){
System.out.println("Handling a WhateverException.");
}
}
class Car {
@NotNull
private String make;
@NotNull
private String model;
...getter/setters omitted for brevity...
}
class WhateverException extends RuntimeException {}
如果您使用
向/cars
提交
POST
{
"make": "BMW"
}
它以 400
和以下正文响应:
{
"timestamp": 1491020374642,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.web.bind.MethodArgumentNotValidException",
"errors": [
{
"codes": [
"NotNull.car.model",
"NotNull.model",
"NotNull.java.lang.String",
"NotNull"
],
"arguments": [
{
"codes": [
"car.model",
"model"
],
"arguments": null,
"defaultMessage": "model",
"code": "model"
}
],
"defaultMessage": "may not be null",
"objectName": "car",
"field": "model",
"rejectedValue": null,
"bindingFailure": false,
"code": "NotNull"
}
],
"message": "Validation failed for object='car'. Error count: 1",
"path": "/cars"
}
但是,如果您将异常处理方法移动到它自己的标记为 @RestControllerAdvice
的类中,该类从 ResponseEntityExceptionHandler
扩展而来,如下所示:
@RestControllerAdvice
class RestExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(WhateverException.class)
@ResponseStatus(HttpStatus.EXPECTATION_FAILED)
public void handleWhateverException(WhateverException e, HttpServletRequest httpServletRequest) {
System.out.println("Handling a WhateverException.");
}
}
你会得到一个 400
和一个 empty body,这是由 ResponseEntityExceptionHandler
提供了一个方法 (handleMethodArgumentNotValid(. .)
),它会在正文为 null
的情况下构建响应。
你将如何改变这个 @RestControllerAdvice
类来触发发生的原始处理,它提供一个 JSON 正文来描述为什么提交的请求无效?
最佳答案
您可以在 @ControllerAdvice
扩展 ResponseEntityExceptionHandler
中模拟 spring 的覆盖行为:
@Override
protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body,
HttpHeaders headers, HttpStatus status, WebRequest request) {
if (body == null) {
body = ImmutableMap.builder()
.put("timestamp", LocalDateTime.now().atZone(ZoneId.systemDefault()).toEpochSecond())
.put("status", status.value())
.put("error", status.getReasonPhrase())
.put("message", ex.getMessage())
.put("exception", ex.getClass().getSimpleName()) // can show FQCN like spring with getName()
.put("path", ((ServletWebRequest)request).getRequest().getRequestURI())
.build();
}
return super.handleExceptionInternal(ex, body, headers, status, request);
}
* ImmutableMap
需要 Guava 。
**LocalDateTime
需要java8。
关于java - 如何使用 @ControllerAdvise(和 @RestControllerAdvise)类保留 Spring 的内置 REST 响应 JSON 主体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43153362/
在 Spring 4.x 中,如果您使用扩展 ResponseEntityExceptionHandler 的 @RestControllerAdvise(或 @ControllerAdvice),则
我是一名优秀的程序员,十分优秀!