Java SpringBoot通用异常处理类
适合返回合适的数据给前端AJAX API调用。
- package tacos.advisor;
- import com.fasterxml.jackson.databind.exc.InvalidFormatException;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.context.support.DefaultMessageSourceResolvable;
- import org.springframework.http.ResponseEntity;
- import org.springframework.http.converter.HttpMessageNotReadableException;
- import org.springframework.validation.BindException;
- import org.springframework.web.bind.MethodArgumentNotValidException;
- import org.springframework.web.bind.MissingPathVariableException;
- import org.springframework.web.bind.MissingServletRequestParameterException;
- import org.springframework.web.bind.annotation.ExceptionHandler;
- import org.springframework.web.bind.annotation.RestControllerAdvice;
- import tacos.model.APIResult;
- import javax.validation.ConstraintViolation;
- import javax.validation.ConstraintViolationException;
- import java.util.Optional;
- import java.util.regex.Matcher;
- import java.util.regex.Pattern;
- import java.util.stream.Collectors;
- @RestControllerAdvice
- @SuppressWarnings("unused")
- public class GlobalExceptionHandler {
- private ResponseEntity<APIResult<Object>> logObject(int code, String msg, String category) {
- Logger log = LoggerFactory.getLogger(category);
- log.error("fail: {}", msg);
- return ResponseEntity.ok().body(APIResult.fail(code, msg));
- }
- @ExceptionHandler(Exception.class)
- public ResponseEntity<APIResult<Object>> handleException(Throwable exception) {
- Logger log = LoggerFactory.getLogger(exception.getStackTrace()[0].getClassName());
- log.error("fail: {}", "", exception);
- return ResponseEntity.ok().body(APIResult.unknown(exception.getMessage()));
- }
- @ExceptionHandler(MethodArgumentNotValidException.class)
- public ResponseEntity<APIResult<Object>> handleMethodArgumentNotValidException(
- MethodArgumentNotValidException exception) {
- String msg = Optional.of(exception.getBindingResult().getFieldErrors().stream()
- .map(DefaultMessageSourceResolvable::getDefaultMessage)
- .collect(Collectors.joining("\r\n"))).orElse("Validate failed");
- return logObject(APIResult.ERROR_PARAM, msg, exception.getStackTrace()[0].getClassName());
- }
- @ExceptionHandler(MissingPathVariableException.class)
- public ResponseEntity<APIResult<Object>> handleMissingPathVariableException(MissingPathVariableException exception) {
- String msg = String.format("The %s is required", exception.getVariableName());
- return logObject(APIResult.ERROR_PARAM, msg, exception.getStackTrace()[0].getClassName());
- }
- @ExceptionHandler(MissingServletRequestParameterException.class)
- public ResponseEntity<APIResult<Object>> handleMissingServletRequestParameterException(
- MissingServletRequestParameterException exception) {
- String msg = String.format("The %s is required", exception.getParameterName());
- return logObject(APIResult.ERROR_PARAM, msg, exception.getStackTrace()[0].getClassName());
- }
- @ExceptionHandler(ConstraintViolationException.class)
- public ResponseEntity<APIResult<Object>> handleConstraintViolationException(ConstraintViolationException exception) {
- String msg = Optional.of(exception.getConstraintViolations().stream()
- .map(ConstraintViolation::getMessage)
- .collect(Collectors.joining("\r\n"))).orElse("Validate failed");
- return logObject(APIResult.ERROR_PARAM, msg, exception.getStackTrace()[0].getClassName());
- }
- private static final Pattern ENUM_MSG = Pattern.compile("values accepted for Enum class: \\[(.*?)\\];(.*)from String \\\"(.*)\\\": (.*)\\n(.*)\\[\\\"(.*)\\\"\\]\\)", Pattern.MULTILINE);
- @ExceptionHandler(HttpMessageNotReadableException.class)
- public ResponseEntity<APIResult<Object>> handleHttpMessageNotReadableException(HttpMessageNotReadableException exception) {
- if (exception.getCause() != null && exception.getCause() instanceof InvalidFormatException) {
- Matcher match = ENUM_MSG.matcher(exception.getMessage());
- if (match.find()) {
- return logObject(APIResult.ERROR_PARAM,
- String.format("%s: Invalid value '%s', possible values - [%s]", match.group(6), match.group(3), match.group(1)),
- exception.getStackTrace()[0].getClassName());
- }
- }
- return logObject(APIResult.ERROR_UNKNOWN, exception.getMessage(), exception.getStackTrace()[0].getClassName());
- }
- @ExceptionHandler(BindException.class)
- public ResponseEntity<APIResult<Object>> handleBindException(BindException exception) {
- String msg = Optional.of(exception.getBindingResult().getFieldErrors().stream().map(e -> e.getField() + ": " + e.getDefaultMessage())
- .collect(Collectors.joining("\r\n"))).orElse("Validate failed");
- return logObject(APIResult.ERROR_PARAM, msg, exception.getStackTrace()[0].getClassName());
- }
- }