Jas*_*ues 3 java spring jackson kotlin spring-boot
鉴于以下有效负载:
data public class CandidateDetailDTO(val id: String,
val stageName: String,
val artists: Iterable<ArtistDTO>,
val instruments: Iterable<InstrumentDTO>,
val genres: Iterable<GenreDTO>,
val discoverable: Boolean,
val gender: Gender,
val involvement: Involvement,
val biography: String,
var photoURLs: List<URL>,
var birthday: Date? = null,
var customGenre: String? = null)
Run Code Online (Sandbox Code Playgroud)
..如图所示,某些字段允许为空,其他字段不允许.
使用Spring Boot调用请求时,如果缺少预期字段,则返回400 - Bad Request.这是不太令人期待的,我期望相关的控制器建议适用:
@ControllerAdvice
public class SomeExceptionHandler : ResponseEntityExceptionHandler()
{
@ExceptionHandler(Throwable::class)
@ResponseBody
public fun onException(ex: Throwable): ResponseEntity<ErrorResponse>
{
val responseCode = ex.responseCode()
val errorResponse = ErrorResponse(response = ResponseHeader(responseCode, ex.message))
return ResponseEntity(errorResponse, responseCode.httpStatus());
}
}
Run Code Online (Sandbox Code Playgroud)
..如果它有,它也会返回400,以及一些关于出了什么问题的额外信息.
是否可以将Spring Boot配置为如上所述?
Jay*_*ard 11
默认情况下,如果不干扰异常处理,Spring Boot将在响应正文中以JSON形式返回完整的错误信息.但它不允许您reasonString
在HTTP标头中设置状态代码.
@ControllerAdvice
public class BadExceptionHandler: ResponseEntityExceptionHandler()
{
@ExceptionHandler(Throwable::class)
@ResponseBody
public fun onException(ex: Throwable): ResponseEntity<ErrorResponse>
{
val responseCode = ex.responseCode()
val errorResponse = ErrorResponse(response = ResponseHeader(responseCode, ex.message))
return ResponseEntity(errorResponse, responseCode.httpStatus());
}
}
Run Code Online (Sandbox Code Playgroud)
在此示例中,您是子类,ResponseEntityExceptionHandler
但不要覆盖其任何方法.相反,你添加一个@ExceptionHandler
用于Throwable
将不会执行.更明确的基类注册@ExceptionHandler
将赢得,因为它按具有优先级的特定类型注册每个异常类.
并且意外地让它ResponseEntityExceptionHandler
做默认行为(将主体设置为null
),您也丢失了自定义错误消息JSON响应.正确使用ResponseEntityExceptionHandler
是将其子类化然后覆盖其中一个错误方法:
当覆盖这些方法时,您更难设置HTTP状态,reasonString
因为响应实体会收到一个HttpStatusCode
永远不允许您更改reasonString
其中一个预定义值的响应实体.您可以使用完整的错误信息返回一个正文,并让状态代码保持通用.
第一个选项是完全删除自定义错误处理程序,它干扰了您已经想要的默认行为.
第二个选项,如果你使用ResponseEntityExceptionHandler
那么你需要覆盖正确的方法,你可以在响应的主体中返回一个带有你的消息的实体(参见:Spring Boot REST服务异常处理)...这篇文章涵盖了很多你的无论如何问题.一定要设置一个身体,而不是将null
身体传递给身体handleExceptionInternal()
.
第三个选项是删除ResponseEntityExceptionHandler
和保留与您的问题类似的代码:
data class ErrorResponse(val statusCode: Int, val statusMessage: String, val message: String)
@ControllerAdvice
public class SomeExceptionHandler
{
@ExceptionHandler(Throwable::class)
@ResponseBody
public fun onException(ex: Throwable): ResponseEntity<ErrorResponse>
{
val httpError = HttpStatus.BAD_REQUEST
val errorResponse = ErrorResponse(httpError.value(), httpError.reasonPhrase, ex.message ?: "Bad Thing")
return ResponseEntity(errorResponse, httpError);
}
}
Run Code Online (Sandbox Code Playgroud)
这会产生类似于:
{
"response": {
"code": "VAMPServiceError",
"message": "Could not read document: No suitable constructor found for type [simple type, class vampr.api.service.profile.payload.CandidateUpdateDTO]"
}
}
Run Code Online (Sandbox Code Playgroud)
第四个选项是创建一个不同形式的异常处理程序,该异常处理程序调用response.sendError()
发回JSON错误,这是Spring Boot的正常默认值,但允许您执行其他逻辑.这看起来像:
@ControllerAdvice
public class UniversalExceptionHandler
{
@ExceptionHandler(SomeException::class)
fun handleBadRequests(ex: Throwable, response: HttpServletResponse){
// .. some logic
response.sendError(HttpStatus.BAD_REQUEST.value(), ex.message)
}
}
Run Code Online (Sandbox Code Playgroud)
这会产生:
{
"timestamp": 1452730838233,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.web.bind.MissingServletRequestParameterException",
"message": "Required String parameter 'name' is not present",
"path": "/greeting"
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4302 次 |
最近记录: |