programing

Spring ResponseStatusException이 이유를 반환하지 않음

newsource 2023. 3. 1. 11:13

Spring ResponseStatusException이 이유를 반환하지 않음

나는 아주 간단한 것이 있다.@RestController커스텀 에러 메시지를 설정하려고 합니다.하지만 어떤 이유에선지message에러가 표시되지 않기 때문입니다.

이것은 내 컨트롤러입니다.

@RestController
@RequestMapping("openPharmacy")
public class OpenPharmacyController {


    @PostMapping
    public String findNumberOfSurgeries(@RequestBody String skuLockRequest) {
        throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "This postcode is not valid");
    }

}

다음은 제가 받은 답변입니다.

{
    "timestamp": "2020-06-24T17:44:20.194+00:00",
    "status": 400,
    "error": "Bad Request",
    "message": "",
    "path": "/openPharmacy/"
}

JSON을 전달하고 있는데 아무것도 검증하지 않고 커스텀메시지를 설정하려고 합니다.상태 코드를 변경하면 응답에 표시됩니다만,message항상 비어 있습니다.

왜 이게 예상대로 안 되는 거죠?이것은 매우 간단한 예이기 때문에 무엇이 누락되어 있는지 알 수 없습니다.코드를 디버깅하면 오류 메시지에 모든 필드가 설정되어 있음을 알 수 있습니다.그러나 어떤 이유로 메시지가 응답으로 설정되지 않습니다.

이 답변은 사용자 Hassan이 원래 질문에 대한 코멘트로 제공했습니다.시야를 더 좋게 하기 위해 답글을 올리는 거예요.

기본적으로, 당신이 해야 할 일은,server.error.include-message=alwaysapplication.properties 파일에 저장되며 메시지 필드가 채워집니다.

이 동작은 Spring Boot 2.3에서 변경되었습니다.이것에 대해서는, https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3-Release-Notes#changes-to-the-default-error-pages-content 를 참조해 주세요.

저도 같은 문제가 있어요.이 구문을 사용하면

throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Error in update");

내 메시지가 다음 경유로 클라이언트에 전달JSON나한텐 그걸 돌 수 있는 유일한 방법은GlobalExceptionHandler학급

package mypackage;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import java.util.Date;

@ControllerAdvice
public class GlobalExceptionHandler {
  @ExceptionHandler(NotFoundException.class)
  public ResponseEntity<ErrorDTO> generateNotFoundException(NotFoundException ex) {
    ErrorDTO errorDTO = new ErrorDTO();
    errorDTO.setMessage(ex.getMessage());
    errorDTO.setStatus(String.valueOf(ex.getStatus().value()));
    errorDTO.setTime(new Date().toString());

    return new ResponseEntity<ErrorDTO>(errorDTO, ex.getStatus());
  }
}

나 또한 내 자신의 것을 만들었다.Exception유형

package mypackage;

import org.springframework.http.HttpStatus;

public class NotFoundException extends RuntimeException {

  public NotFoundException(String message) {
    super(message);
  }

  public HttpStatus getStatus() {
    return HttpStatus.NOT_FOUND;
  }
}

이를 통해 컨트롤러에서 예외를 발생시킬 수 있으며 적절한 결과를 얻을 수 있습니다.JSON- 보고 싶은 메시지

@PutMapping("/data/{id}")
public DataEntity updateData(@RequestBody DataEntity data, @PathVariable int id) {
  throw new NotFoundException("Element not found");
}

제가 소개를 해야 되는데ErrorDTO뿐만 아니라.

package mypackage;

public class ErrorDTO {
  public String status;
  public String message;
  public String time;

  ...
  ...
  // getters and setters are here 
  ...
  ...
}

갱신하다

@Hassan과 @cunhaf(원래 질문 아래의 코멘트)에서 언급한 바와 같이,

server.error.include-message=always

와 완벽하게 잘 어울린다ResponseStatusException그래도 솔루션에는GlobalExceptionHandler예외로 더 많은 정보를 전달하려는 경우 더 좋을 수 있습니다.

소스 코드

샘플은 글로벌 예외 핸들러에서 찾을 수 있습니다.

이상하게도 Spring Boot 2.6.x에 의해 이 동작이 다시 변경되어 에러 메시지가 설정되었습니다.ResponseStatusException는 반환되지 않습니다.문제를 해결하기 위해 2.5.6으로 다운그레이드해야 했습니다.결국 나는 다음과 같은 것을 얻었다.

 @DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.OK)  
public MessageResponse deleteById(@PathVariable(value = "id") Integer id) {
    try {
        userService.deleteById(id); 
        
    } catch (Exception e) {
        throw new ResponseStatusException(HttpStatus.EXPECTATION_FAILED, "Error deleting user. User has dependencies", e);
    }
}

2.3 버전부터는 Spring Boot 기본 오류 페이지에 오류 메시지가 표시되지 않습니다.그 이유는 클라이언트에 대한 정보 유출 위험을 줄이기 위해서입니다.

동작을 하려면 , 「」를 합니다.server.error.include-message★★★★★★★★★★★★★★★★★★.

커스텀 메시지를 포함하도록 덮어쓸 수 있는 빈이 있습니다.

부트: " " " " " :org.springframework.boot.web.servlet.error.ErrorAttributes

프 spring spring spring spring spring spring spring spring spring spring spring spring spring spring spring spring:org.springframework.boot.web.reactive.error.ErrorAttributes


은 「」입니다.DefaultErrorAttributes.

덮어쓸 수 있습니다.public Map<String, Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions options) {

message가 원하는 것


내 경우 내부 서버 오류일 경우 메시지를 제거하는 데코레이터를 만들었습니다.

public class CustomErrorAttributesDecorator implements ErrorAttributes {

    private final ErrorAttributes errorAttributes;
    
    CustomErrorAttributesDecorator(ErrorAttributes errorAttributes){
        this.errorAttributes = errorAttributes;
    }

    @Override
    public Map<String, Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions options) {
        Map<String, Object> errorAttributesMap = this.errorAttributes.getErrorAttributes(request, options);
        if(HttpStatus.INTERNAL_SERVER_ERROR.value() == (int) errorAttributesMap.get("status")){
            errorAttributesMap.remove("message");
        }
        return errorAttributesMap;
    }

...
}

그리고 다음과 같이 @Bean을 만들었습니다.

        @Bean
        ErrorAttributes customErrorAttributes(){
            return new CustomErrorAttributesDecorator(new DefaultErrorAttributes());
        }

REST API를 만드는 경우 예외 처리를 위해 zalando 문제를 살펴봅니다. 문제 스프링

Evry 예외는 @ExceptionHandler에 의해 캐치되며 Zalando Builder를 사용하여 문제 개체를 반환해야 합니다.

public class ResourceNotFoundException extends Exception {
    // ...
}

@ControllerAdvice
public class MyExceptionHandler implements ProblemHandling {

    @ExceptionHandler(ResourceNotFoundException.class)
    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    public ResponseEntity<Problem> handleResourceNotFoundException(final ResourceNotFoundException exception, final NativeWebRequest request) {
        Problem problem = Problem.builder()//
            .withType(URI.create("https://example.com/problem/not-found"))//
            .withTitle("Resource not found")//
            .withStatus(Status.NOT_FOUND)//
            .withDetail(exception.getMessage()).build();
    }
        
 ...
}

, application.properties에서 할 수 있는 .server.error.include-message★★★★★★★★★★★★★★★★★★.

★★server.error.include-message=always에는 예외 발생 시 이유가 항상 포함됩니다.그 이유로 인해 어플리케이션에 대한 기밀 정보가 노출될 가능성이 있는 경우에도 마찬가지입니다.

에 더 은 " " " 입니다.server.error.include-message=on-param 「메시지」를 개입시켜 됩니다.ResponseStatusException:

if (requestBody.someField == null) {
   throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "someField is required.");
}

언급URL : https://stackoverflow.com/questions/62561211/spring-responsestatusexception-does-not-return-reason