pet*_*erl 12 java spring spring-mvc spring-boot
在Spring 4.x中,如果使用扩展的@RestControllerAdvise(或@ControllerAdvice),ResponseEntityExceptionHandler默认情况下,对于标记为的参数,不再返回具有良好且信息丰富的JSON响应主体的默认异常处理@Valid.
如何在使用ResponseEntityExceptionHandler基础时返回默认的JSON实体@RestControllerAdvice?
以下是描述此问题的简单但完整的示例.使用这些类:
@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 {}
Run Code Online (Sandbox Code Playgroud)
如果提交POST到/cars与
{
"make": "BMW"
}
Run Code Online (Sandbox Code Playgroud)
它响应a 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"
}
Run Code Online (Sandbox Code Playgroud)
但是,如果将异常处理方法移动到它自己标记的类@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.");
}
}
Run Code Online (Sandbox Code Playgroud)
你会得到一个400与空体,这是造成ResponseEntityExceptionHandler提供的方法(handleMethodArgumentNotValid(..)),它建立在身体是一个响应null.
你如何改变这个@RestControllerAdvice类来触发发生的原始处理,它提供了一个JSON主体来描述提交的请求无效的原因?
您可以在扩展中模拟spring 的行为:@ControllerAdviceResponseEntityExceptionHandler
@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);
}
Run Code Online (Sandbox Code Playgroud)
*ImmutableMap需要番石榴。
**LocalDateTime需要 java8。
这个怎么样?
@RestControllerAdvice
class RestExceptionHandler {
@ExceptionHandler(org.springframework.validation.BindException.class)
public ResponseEntity<String> handleBindException(org.springframework.validation.BindException e) {
return ResponseEntity.badRequest().body(e.getMessage());
}
}
Run Code Online (Sandbox Code Playgroud)
当@Valid失败时,它抛出 BindException。你可以这样处理。或者你可以这样做throw e,这会给你与之前抛出的完全相同的响应
| 归档时间: |
|
| 查看次数: |
1792 次 |
| 最近记录: |