@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구아바가 필요합니다.
**LocalDateTimeJava8이 필요합니다.
이건 어때?
@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 |