@ControllerAdvision(및 @RestControllerAdvision) 클래스가 있는 Spring의 내장 REST Response JSON 본문을 어떻게 유지합니까?
Spring 4.x에서 다음을 사용할 경우@RestControllerAdvise
(또는)@ControllerAdvice
) 확장됩니다.ResponseEntityExceptionHandler
친절하고 유익한 JSON 응답 본문을 사용하는 기본 예외 처리는 다음과 같이 표시된 인수에 대해 더 이상 기본적으로 반환되지 않습니다.@Valid
.
사용하는 동안 기본 JSON 본문을 반환하려면 어떻게 해야 합니까?ResponseEntityExceptionHandler
기반을 둔@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 {}
다음을 제출하는 경우POST
로./cars
와 함께
{
"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
때문에 생긴 빈 몸으로.ResponseEntityExceptionHandler
방법 제공(handleMethodArgumentNotValid(..)
), 신체가 있는 곳에 반응을 구축합니다.null
.
이것을 어떻게 바꾸시겠습니까?@RestControllerAdvice
클래스는 발생하는 원래 처리를 트리거합니다. 이 클래스는 제출된 요청이 유효하지 않은 이유를 설명하는 JSON 본문을 제공합니까?
당신은 봄의 행동을 모방할 수 있습니다.@ControllerAdvice
연장의ResponseEntityExceptionHandler
:
@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
구아바가 필요합니다.
**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());
}
}
언제@Valid
실패하면 BindException이 느려집니다.이런 식으로 처리할 수 있습니다.아니면 그냥 할 수 있습니다.throw e
당신에게 아까 던져진 것과 똑같은 반응을 줄 것입니다.
한 가지 접근 방식은 확장하지 않는 것입니다.ResponseEntityExceptionHandler
결과 클래스는 다음과 같습니다.
@RestControllerAdvice
class RestExceptionHandler {
@ExceptionHandler(WhateverException.class)
@ResponseStatus(HttpStatus.EXPECTATION_FAILED)
public ResponseEntity<String> handleWhateverException(WhateverException e, HttpServletRequest httpServletRequest) {
System.out.println("Handling a WhateverException.");
return new ResponseEntity(...);
}
}
그러나 이 항목도 참조하십시오.[class org.springframework.web.bind]에 대해 매핑된 모호한 @ExceptionHandler 메서드입니다.메서드 인수 NotValidException]
저는 같은 문제에 직면했습니다. 문제를 디버깅하는 데 많은 시간을 소비한 후 잭슨이 제대로 역직렬화하지 않고 있다는 것을 발견했습니다.ErrorResponse
물건.
이는 정의된 필드에 대한 게터와 세터를 추가하지 않았기 때문입니다.ErrorResponse
물건.생성자를 사용하여 필드를 초기화하고 있었는데 해당 필드에 대해 정의된 게터와 세터가 없습니다.
솔루션(빈 차체용):
그래서 업데이트할 때ErrorResponse
에서의 반대.
import com.fasterxml.jackson.annotation.JsonRootName;
import java.util.List;
@JsonRootName("error")
public class ErrorResponse {
private String message;
private List<String> details;
public ErrorResponse(String message, List<String> details) {
this.message = message;
this.details = details;
}
}
게터와 세터가 있는 다음 사람에게.
import com.fasterxml.jackson.annotation.JsonRootName;
import java.util.List;
@JsonRootName("error")
public class ErrorResponse {
private String message;
private List<String> details;
public ErrorResponse(String message, List<String> details) {
this.message = message;
this.details = details;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public List<String> getDetails() {
return details;
}
public void setDetails(List<String> details) {
this.details = details;
}
}
잭슨은 이제 역직렬화하고 있습니다.ErrorResponse
연쇄 살인범의 시체를 찾고 있어요
언급URL : https://stackoverflow.com/questions/43153362/how-do-you-retain-springs-built-in-rest-response-json-body-with-a-controllerad
'programing' 카테고리의 다른 글
MongoDb: .gz 파일에서 덤프 데이터를 가져오는 방법은 무엇입니까? (0) | 2023.06.22 |
---|---|
TS2339: '포함' 속성이 '문자열' 유형에 없습니다. (0) | 2023.06.22 |
선택한 문에 트랜잭션을 사용하시겠습니까? (0) | 2023.06.22 |
다른 도메인의 다른 페이지에 PHP 페이지의 div 로드 (0) | 2023.06.22 |
스프링 데이터레스트 - 지원되는 작동을 제한할 수 있는 방법이 있습니까? (0) | 2023.06.22 |