문자열을 반환하는 Spring MVC @Response Body 메서드에서 HTTP 400 오류로 응답하는 방법
MVC를 Spring MVC는 Spring MVC로 되어 있습니다.@ResponseBody직접 생산하는 레이어가 이미 .(JSON은 JSON을 직접 생산하는 서비스 입니다.)
@RequestMapping(value = "/matches/{matchId}", produces = "application/json")
@ResponseBody
public String match(@PathVariable String matchId) {
String json = matchService.getMatchJson(matchId);
if (json == null) {
// TODO: how to respond with e.g. 400 "bad request"?
}
return json;
}
문제는 주어진 시나리오에서 HTTP 400 오류에 대응하는 가장 간단하고 깨끗한 방법은 무엇입니까?
나는 다음과 같은 접근방식을 발견했다.
return new ResponseEntity(HttpStatus.BAD_REQUEST);
그러나 메서드의 반환 유형이 ResponseEntity가 아닌 String이기 때문에 여기서는 사용할 수 없습니다.
을 반반반 change로 변경하다ResponseEntity<> 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
및 올바른 요청을 위해
return new ResponseEntity<>(json,HttpStatus.OK);
업데이트 1
스프링 4.1 이후 ResponseEntity에는 도우미 메서드가 있습니다.
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
그리고.
return ResponseEntity.ok(json);
다음과 같은 방법이 작동해야 합니다. 더 간단한 방법이 있는지 잘 모르겠습니다.
@RequestMapping(value = "/matches/{matchId}", produces = "application/json")
@ResponseBody
public String match(@PathVariable String matchId, @RequestBody String body,
HttpServletRequest request, HttpServletResponse response) {
String json = matchService.getMatchJson(matchId);
if (json == null) {
response.setStatus( HttpServletResponse.SC_BAD_REQUEST );
}
return json;
}
가장 컴팩트한 방법이라고는 할 수 없지만 매우 깨끗한 IMO
if(json == null) {
throw new BadThingException();
}
...
@ExceptionHandler(BadThingException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public @ResponseBody MyError handleException(BadThingException e) {
return new MyError("That doesnt work");
}
3.1+ 를 하고 있는 으로 @를 할 수 않은 경우는 Spring 3.1+ 를 합니다.@ResponseBody 를 사용합니다.ModelAndView아, 아, 아, 아, 아, 아, 아, 아, 아.
https://jira.springsource.org/browse/SPR-6902
구현을 약간 변경합니다.
'I'를 .UnknownMatchException
@ResponseStatus(HttpStatus.NOT_FOUND)
public class UnknownMatchException extends RuntimeException {
public UnknownMatchException(String matchId) {
super("Unknown match: " + matchId);
}
}
@ResponseStatus의 사용에 주의해 주십시오.이것은 스프링의ResponseStatusExceptionResolver, 코드를 (로 도 실례했습니다404 - Not Found이 사용 사례에 더 적합하다고 생각합니다만, 계속 사용하세요.HttpStatus.BAD_REQUEST괜찮으시다면).
다음, 음음음 the the는 the the the the the the the next next next next?MatchService하다
interface MatchService {
public Match findMatch(String matchId);
}
하고 Spring Spring's Spring'에 위임합니다.MappingJackson2HttpMessageConverter하고 JSON을 됩니다).@EnableWebMvc ★★★★★★★★★★★★★★★★★」<mvc:annotation-driven />참조 문서를 참조해 주세요).
@RequestMapping(value = "/matches/{matchId}", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public Match match(@PathVariable String matchId) {
// throws an UnknownMatchException if the matchId is not known
return matchService.findMatch(matchId);
}
도메인 오브젝트를 뷰 오브젝트 또는 DTO 오브젝트에서 분리하는 것은 매우 일반적입니다.이것은, 시리얼 가능한 JSON 오브젝트를 반환하는 소규모의 DTO 팩토리를 추가하는 것으로 간단하게 실현할 수 있습니다.
@RequestMapping(value = "/matches/{matchId}", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public MatchDTO match(@PathVariable String matchId) {
Match match = matchService.findMatch(matchId);
return MatchDtoFactory.createDTO(match);
}
여기 다른 방법이 있습니다. 「」을 합니다.Exception'어느 정도'라는 주석이 붙어 .@ResponseStatus예를 들면 다음과 같습니다.
@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "Not Found")
public class NotFoundException extends Exception {
public NotFoundException() {
}
}
그리고 필요할 때 던져라.
@RequestMapping(value = "/matches/{matchId}", produces = "application/json")
@ResponseBody
public String match(@PathVariable String matchId) {
String json = matchService.getMatchJson(matchId);
if (json == null) {
throw new NotFoundException();
}
return json;
}
스프링 매뉴얼은 http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/ #mvc-ann-discuptions-exceptions를 참조하십시오.
입니다.ResponseStatusException
@RequestMapping(value = "/matches/{matchId}", produces = "application/json")
@ResponseBody
public String match(@PathVariable String matchId, @RequestBody String body) {
String json = matchService.getMatchJson(matchId);
if (json == null) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND);
}
return json;
}
일부 답변에서 설명한 바와 같이 반환하는 HTTP 상태별로 예외 클래스를 만들 수 있습니다.각 프로젝트에 대해 상태별로 클래스를 만들어야 한다는 생각은 마음에 들지 않습니다.내가 대신 생각해낸 건 이거야.
- HTTP 상태를 받아들이는 일반 예외 만들기
- 컨트롤러 어드바이스 예외 핸들러를 만듭니다.
코드로 들어가자
package com.javaninja.cam.exception;
import org.springframework.http.HttpStatus;
/**
* The exception used to return a status and a message to the calling system.
* @author norrisshelton
*/
@SuppressWarnings("ClassWithoutNoArgConstructor")
public class ResourceException extends RuntimeException {
private HttpStatus httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
/**
* Gets the HTTP status code to be returned to the calling system.
* @return http status code. Defaults to HttpStatus.INTERNAL_SERVER_ERROR (500).
* @see HttpStatus
*/
public HttpStatus getHttpStatus() {
return httpStatus;
}
/**
* Constructs a new runtime exception with the specified HttpStatus code and detail message.
* The cause is not initialized, and may subsequently be initialized by a call to {@link #initCause}.
* @param httpStatus the http status. The detail message is saved for later retrieval by the {@link
* #getHttpStatus()} method.
* @param message the detail message. The detail message is saved for later retrieval by the {@link
* #getMessage()} method.
* @see HttpStatus
*/
public ResourceException(HttpStatus httpStatus, String message) {
super(message);
this.httpStatus = httpStatus;
}
}
그런 다음 컨트롤러 어드바이스 클래스를 만듭니다.
package com.javaninja.cam.spring;
import com.javaninja.cam.exception.ResourceException;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
/**
* Exception handler advice class for all SpringMVC controllers.
* @author norrisshelton
* @see org.springframework.web.bind.annotation.ControllerAdvice
*/
@org.springframework.web.bind.annotation.ControllerAdvice
public class ControllerAdvice {
/**
* Handles ResourceExceptions for the SpringMVC controllers.
* @param e SpringMVC controller exception.
* @return http response entity
* @see ExceptionHandler
*/
@ExceptionHandler(ResourceException.class)
public ResponseEntity handleException(ResourceException e) {
return ResponseEntity.status(e.getHttpStatus()).body(e.getMessage());
}
}
사용하기 위해서
throw new ResourceException(HttpStatus.BAD_REQUEST, "My message");
http://javaninja.net/2016/06/throwing-exceptions-messages-spring-mvc-controller/
스프링 부트 어플리케이션에서 사용하고 있습니다.
@RequestMapping(value = "/matches/{matchId}", produces = "application/json")
@ResponseBody
public ResponseEntity<?> match(@PathVariable String matchId, @RequestBody String body,
HttpServletRequest request, HttpServletResponse response) {
Product p;
try {
p = service.getProduct(request.getProductId());
} catch(Exception ex) {
return new ResponseEntity<String>(HttpStatus.BAD_REQUEST);
}
return new ResponseEntity(p, HttpStatus.OK);
}
왜 Boot를 )./error)@ResponseBody.@ExceptionHandler가 없었습니다 ), 는 、 그 、 그 、 그 、 ), 、 ), 、 ), 、 ), ), ), ), ), ), ),
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(IllegalArgumentException.class)
public ErrorMessage handleIllegalArguments(HttpServletRequest httpServletRequest, IllegalArgumentException e) {
log.error("Illegal arguments received.", e);
ErrorMessage errorMessage = new ErrorMessage();
errorMessage.code = 400;
errorMessage.message = e.getMessage();
return errorMessage;
}
요청 속성으로 정의된 프로덕션 미디어 유형이 없기 때문에 여전히 예외가 발생했습니다.
// AbstractMessageConverterMethodProcessor
@SuppressWarnings("unchecked")
protected <T> void writeWithMessageConverters(T value, MethodParameter returnType,
ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage)
throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
Class<?> valueType = getReturnValueType(value, returnType);
Type declaredType = getGenericType(returnType);
HttpServletRequest request = inputMessage.getServletRequest();
List<MediaType> requestedMediaTypes = getAcceptableMediaTypes(request);
List<MediaType> producibleMediaTypes = getProducibleMediaTypes(request, valueType, declaredType);
if (value != null && producibleMediaTypes.isEmpty()) {
throw new IllegalArgumentException("No converter found for return value of type: " + valueType); // <-- throws
}
// ....
@SuppressWarnings("unchecked")
protected List<MediaType> getProducibleMediaTypes(HttpServletRequest request, Class<?> valueClass, Type declaredType) {
Set<MediaType> mediaTypes = (Set<MediaType>) request.getAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
if (!CollectionUtils.isEmpty(mediaTypes)) {
return new ArrayList<MediaType>(mediaTypes);
그래서 넣었어요.
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(IllegalArgumentException.class)
public ErrorMessage handleIllegalArguments(HttpServletRequest httpServletRequest, IllegalArgumentException e) {
Set<MediaType> mediaTypes = new HashSet<>();
mediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
httpServletRequest.setAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE, mediaTypes);
log.error("Illegal arguments received.", e);
ErrorMessage errorMessage = new ErrorMessage();
errorMessage.code = 400;
errorMessage.message = e.getMessage();
return errorMessage;
}
되고 있는 호환 타입을 할 수 , 「호환 미디어 타입」은 기능하지 않았기 때문입니다. 하지만 여전히 작동하지 않았습니다.ErrorMessage장애가 있었습니다.
public class ErrorMessage {
int code;
String message;
}
는 "에 getters, Jackson Mapper도 "getters/setters"를했습니다.@JsonProperty
public class ErrorMessage {
@JsonProperty("code")
private int code;
@JsonProperty("message")
private String message;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
그리고 나는 의도한 대로 내 메시지를 받았다.
{"code":400,"message":"An \"url\" parameter must be defined."}
하나의 은 '보다 낫다'입니다.@ExceptionHandler@ControllerAdvice모든 핸들러를 같은 클래스에 집중시키려면 예외를 관리하는 모든 컨트롤러에 핸들러 메서드를 삽입해야 합니다.
핸들러 클래스:
@ControllerAdvice
public class MyExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(MyBadRequestException.class)
public ResponseEntity<MyError> handleException(MyBadRequestException e) {
return ResponseEntity
.badRequest()
.body(new MyError(HttpStatus.BAD_REQUEST, e.getDescription()));
}
}
커스텀 예외:
public class MyBadRequestException extends RuntimeException {
private String description;
public MyBadRequestException(String description) {
this.description = description;
}
public String getDescription() {
return this.description;
}
}
이것으로, 임의의 컨트롤러로부터 예외를 슬로우 할 수 있게 되어 어드바이스 클래스내에 다른 핸들러를 정의할 수 있게 되었습니다.
또한 Spring의 기본 오류 처리 기능을 활용할 수도 있습니다.
그러나 이러한 기본 오류와 마찬가지로 응답 본문은 설정되지 않습니다.
이러한 요구는 보다 심층적인 커스텀 검증과 그 기준에 따라 요구가 거부되었다는 사실을 모호하게 하기 때문에 수작업으로 이루어졌을 뿐이며 잠재적으로 악의적인 의도를 나타낼 수 있는 요구를 거부할 때 유용합니다.
Hth, dtk
의 으로 반환하지 할 수 가장 ResponseEntity그냥 더하는 것이다.@ExceptionHandler방법들.
Spring Boot 2.0.3을 사용한 스니펫의 예릴리즈:
// Prefer static import of HttpStatus constants as it's cleaner IMHO
// Handle with no content returned
@ExceptionHandler(IllegalArgumentException.class)
@ResponseStatus(BAD_REQUEST)
void onIllegalArgumentException() {}
// Return 404 when JdbcTemplate does not return a single row
@ExceptionHandler(IncorrectResultSizeDataAccessException.class)
@ResponseStatus(NOT_FOUND)
void onIncorrectResultSizeDataAccessException() {}
// Catch all handler with the exception as content
@ExceptionHandler(Exception.class)
@ResponseStatus(I_AM_A_TEAPOT)
@ResponseBody Exception onException(Exception e) {
return e;
}
여백으로서:
- 모든 컨텍스트/사용방법에서
matchService.getMatchJson(matchId) == null무효입니다. 그러면 제 제안은getMatchJson예를 들어 예외를 설정합니다.IllegalArgumentException돌아오는 대신null컨트롤러에 거품이 일게 합니다.@ExceptionHandler. - 한다면
null다른 조건을 테스트하기 위해 사용됩니다.그러면 구체적인 방법이 있습니다.matchService.hasMatchJson(matchId)일반적으로, 나는 피한다.null하면 예기치 않은 위해NullPointerException
이 스레드는 Spring이 제공하는 JSON 무술 도구를 희생하지 않는 가장 쉽고 깨끗한 솔루션을 제공합니다.
https://stackoverflow.com/a/16986372/1278921
상태 코드가 있는 사용자 지정 응답
다음과 같이 합니다.
class Response<T>(
val timestamp: String = DateTimeFormatter
.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS")
.withZone(ZoneOffset.UTC)
.format(Instant.now()),
val code: Int = ResultCode.SUCCESS.code,
val message: String? = ResultCode.SUCCESS.message,
val status: HttpStatus = HttpStatus.OK,
val error: String? = "",
val token: String? = null,
val data: T? = null
) : : ResponseEntity<Response.CustomResponseBody>(status) {
data class CustomResponseBody(
val timestamp: String = DateTimeFormatter
.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS")
.withZone(ZoneOffset.UTC)
.format(Instant.now()),
val code: Int = ResultCode.SUCCESS.code,
val message: String? = ResultCode.SUCCESS.message,
val error: String? = "",
val token: String? = null,
val data: Any? = null
)
override fun getBody(): CustomResponseBody? = CustomResponseBody(timestamp, code, message, error, token, data)
언급URL : https://stackoverflow.com/questions/16232833/how-to-respond-with-http-400-error-in-a-spring-mvc-responsebody-method-returnin
'programing' 카테고리의 다른 글
| Android Get Current 타임스탬프? (0) | 2022.07.08 |
|---|---|
| Vue.js - 로컬 파일에 JSON 개체를 씁니다. (0) | 2022.07.08 |
| 계산된 속성 내의 $el에 액세스합니다. (0) | 2022.07.08 |
| 스프링 JPA 특정 컬럼 선택 (0) | 2022.07.08 |
| 부동 소수점이 아닌 정수를 포함하는 경우 이중 변수 선택 (0) | 2022.07.07 |