我是春季和春季靴子的新手。在创建一个简单的REST API以对用户执行CRUD操作之后,我还创建了自定义异常处理程序来捕获应用程序中发生的任何异常。这是我写的代码
控制器类
public class UserController {
@Autowired
private IUserService userService;
@ApiOperation(value = "View list of all users", response = Iterable.class)
@RequestMapping(value = "/users", method = RequestMethod.GET)
public @ResponseBody List<User> getAll() throws EntityNotFoundException {
return userService.query();
}
@ApiOperation(value = "View a specific user", response = User.class)
@RequestMapping(value = "/users/{id}", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
public @ResponseBody List<User> getUser(@PathVariable(value = "id") String userid) throws EntityNotFoundException {
return userService.query(userid);
}
@ApiOperation(value = "create a user")
@RequestMapping(value = "/users", method = RequestMethod.POST, produces = { MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<HttpStatus> createUser(@Valid @RequestBody User user) throws Exception {
userService.add(user);
return ResponseEntity.ok(HttpStatus.OK);
}
@ApiOperation(value = "update a user")
@RequestMapping(value = "/users", method = RequestMethod.PUT, produces = { MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<User> updateUser(@Valid @RequestBody User entity) throws Exception {
User user = userService.update(entity);
if (user == null) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok(user);
}
@ApiOperation(value = "delete a user")
@RequestMapping(value = "/userid/{id}", method = RequestMethod.DELETE, produces = {
MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<HttpStatus> deleteUser(@PathVariable(value = "id") String userid) throws Exception {
String result = userService.remove(userid);
if (result.equals(null)) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok(HttpStatus.OK);
}
}
异常处理程序使用@Controlleradvice注释类
@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {
/**
* Handles javax.validation.ConstraintViolationException. Thrown
* when @Validated fails.
*
* @param ex
* the ConstraintViolationException
* @return the ApiError object
*/
@ExceptionHandler(javax.validation.ConstraintViolationException.class)
protected ResponseEntity<Object> handleConstraintViolation(javax.validation.ConstraintViolationException ex) {
ApiError apiError = new ApiError(BAD_REQUEST);
apiError.setMessage("Validation error");
return buildResponseEntity(apiError);
}
/**
* Handles EntityNotFoundException. Created to encapsulate errors with more
* detail than javax.persistence.EntityNotFoundException.
*
* @param ex
* the EntityNotFoundException
* @return the ApiError object
*/
@ExceptionHandler(EntityNotFoundException.class)
protected ResponseEntity<Object> handleEntityNotFound(EntityNotFoundException ex) {
ApiError apiError = new ApiError(NOT_FOUND);
apiError.setMessage(ex.getMessage());
return buildResponseEntity(apiError);
}
/**
* Handle Exception, handle generic Exception.class
*
* @param ex
* the Exception
* @return the ApiError object
*/
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
protected ResponseEntity<Object> handleMethodArgumentTypeMismatch(MethodArgumentTypeMismatchException ex,
WebRequest request) {
ApiError apiError = new ApiError(BAD_REQUEST);
apiError.setMessage(String.format("The parameter '%s' of value '%s' could not be converted to type '%s'",
ex.getName(), ex.getValue(), ex.getRequiredType().getSimpleName()));
apiError.setDebugMessage(ex.getMessage());
return buildResponseEntity(apiError);
}
private ResponseEntity<Object> buildResponseEntity(ApiError apiError) {
return new ResponseEntity<>(apiError, apiError.getStatus());
}
}
但是,当发生任何异常时,应用程序将重定向到/ error页面,而不是由异常处理程序类处理。任何人都可以就正确的方法提出建议。
答案 0 :(得分:0)
处理程序未捕获哪些异常?是ConstraintViolationException吗?
当您这样做:
@Valid @RequestBody User entity
您正在触发方法中的验证,因此,如果用于装饰User类的约束未得到满足,将抛出 MethodArgumentNotValidException ,而不是 ConstraintViolationException 。
在扩展 ResponseEntityExceptionHandler 时,应检查此类的代码,该代码定义了以下方法:
@ExceptionHandler({
HttpRequestMethodNotSupportedException.class,
HttpMediaTypeNotSupportedException.class,
HttpMediaTypeNotAcceptableException.class,
MissingPathVariableException.class,
MissingServletRequestParameterException.class,
ServletRequestBindingException.class,
ConversionNotSupportedException.class,
TypeMismatchException.class,
HttpMessageNotReadableException.class,
HttpMessageNotWritableException.class,
MethodArgumentNotValidException.class,
MissingServletRequestPartException.class,
BindException.class,
NoHandlerFoundException.class,
AsyncRequestTimeoutException.class
})
@Nullable
public final ResponseEntity<Object> handleException(Exception ex, WebRequest request) throws Exception {
HttpHeaders headers = new HttpHeaders();
if (ex instanceof HttpRequestMethodNotSupportedException) {
HttpStatus status = HttpStatus.METHOD_NOT_ALLOWED;
return handleHttpRequestMethodNotSupported((HttpRequestMethodNotSupportedException) ex, headers, status, request);
}
else if (ex instanceof HttpMediaTypeNotSupportedException) {
HttpStatus status = HttpStatus.UNSUPPORTED_MEDIA_TYPE;
return handleHttpMediaTypeNotSupported((HttpMediaTypeNotSupportedException) ex, headers, status, request);
}
else if (ex instanceof HttpMediaTypeNotAcceptableException) {
HttpStatus status = HttpStatus.NOT_ACCEPTABLE;
return handleHttpMediaTypeNotAcceptable((HttpMediaTypeNotAcceptableException) ex, headers, status, request);
}
else if (ex instanceof MissingPathVariableException) {
HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
return handleMissingPathVariable((MissingPathVariableException) ex, headers, status, request);
}
else if (ex instanceof MissingServletRequestParameterException) {
HttpStatus status = HttpStatus.BAD_REQUEST;
return handleMissingServletRequestParameter((MissingServletRequestParameterException) ex, headers, status, request);
}
else if (ex instanceof ServletRequestBindingException) {
HttpStatus status = HttpStatus.BAD_REQUEST;
return handleServletRequestBindingException((ServletRequestBindingException) ex, headers, status, request);
}
else if (ex instanceof ConversionNotSupportedException) {
HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
return handleConversionNotSupported((ConversionNotSupportedException) ex, headers, status, request);
}
else if (ex instanceof TypeMismatchException) {
HttpStatus status = HttpStatus.BAD_REQUEST;
return handleTypeMismatch((TypeMismatchException) ex, headers, status, request);
}
else if (ex instanceof HttpMessageNotReadableException) {
HttpStatus status = HttpStatus.BAD_REQUEST;
return handleHttpMessageNotReadable((HttpMessageNotReadableException) ex, headers, status, request);
}
else if (ex instanceof HttpMessageNotWritableException) {
HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
return handleHttpMessageNotWritable((HttpMessageNotWritableException) ex, headers, status, request);
}
else if (ex instanceof MethodArgumentNotValidException) {
HttpStatus status = HttpStatus.BAD_REQUEST;
return handleMethodArgumentNotValid((MethodArgumentNotValidException) ex, headers, status, request);
}
else if (ex instanceof MissingServletRequestPartException) {
HttpStatus status = HttpStatus.BAD_REQUEST;
return handleMissingServletRequestPart((MissingServletRequestPartException) ex, headers, status, request);
}
else if (ex instanceof BindException) {
HttpStatus status = HttpStatus.BAD_REQUEST;
return handleBindException((BindException) ex, headers, status, request);
}
else if (ex instanceof NoHandlerFoundException) {
HttpStatus status = HttpStatus.NOT_FOUND;
return handleNoHandlerFoundException((NoHandlerFoundException) ex, headers, status, request);
}
else if (ex instanceof AsyncRequestTimeoutException) {
HttpStatus status = HttpStatus.SERVICE_UNAVAILABLE;
return handleAsyncRequestTimeoutException((AsyncRequestTimeoutException) ex, headers, status, request);
}
else {
// Unknown exception, typically a wrapper with a common MVC exception as cause
// (since @ExceptionHandler type declarations also match first-level causes):
// We only deal with top-level MVC exceptions here, so let's rethrow the given
// exception for further processing through the HandlerExceptionResolver chain.
throw ex;
}
}
因此,这里捕获了MethodArgumentNotValidException,并将此类异常的处理传递给handleMethodArgumentNotValid方法。
默认的 handleMethodArgumentNotValid 只需调用:
return handleExceptionInternal(ex, null, headers, status, request);
此处更好的选择是覆盖 RestExceptionHandler
中的 handleMethodArgumentNotValid