@Slf4j
@Order(1)
@RestControllerAdvice
@ConditionalOnProperty(name="unified.exception.enabled", havingValue = "true", matchIfMissing = true)
public class DefaultResponseEntityExceptionControllerAdvice extends ResponseEntityExceptionHandler {
/**
* @param request
* @param e
* @return com.lemon.web.dto.BaseResponse
* @description
* @author lemon
* @date 2020-07-06 08:50
*/
@ExceptionHandler(value = BussinessException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public BaseResponse bussinessExceptionHandler(HttpServletRequest request, BussinessException e) {
log.error(e.getMessage(), e);
return new BaseResponse(String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value()), e.getMessage(), null);
}
/**
* @param req
* @param e
* @return com.lemon.web.dto.BaseResponse
* @description
* @author lemon
* @date 2020-07-06 08:50
*/
@ExceptionHandler(value = ResourceNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
@ResponseBody
public BaseResponse resourceNotFoundExceptionHandler(HttpServletRequest req, ResourceNotFoundException e) {
String err = String.format("%s not found", req.getRequestURI());
log.debug(err, e);
return new BaseResponse(String.valueOf(HttpStatus.NOT_FOUND.value()), err, null);
}
/**
* @param request
* @param e
* @return com.lemon.web.dto.BaseResponse
* @description
* @author lemon
* @date 2020-07-06 08:50
*/
@ExceptionHandler(value = IllegalArgumentException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public BaseResponse illegalArugmentExceptionHandler(HttpServletRequest request, IllegalArgumentException e) {
log.warn(e.getMessage(), e);
return new BaseResponse(String.valueOf(HttpStatus.BAD_REQUEST.value()), e.getMessage(), null);
}
/**
* @param request
* @param e
* @return com.lemon.web.dto.BaseResponse
* @description
* @author lemon
* @date 2020-07-06 08:50
*/
@ExceptionHandler(value = IllegalStateException.class)
@ResponseStatus(HttpStatus.FORBIDDEN)
@ResponseBody
public BaseResponse illegalStateExceptionHandler(HttpServletRequest request, IllegalStateException e) {
log.warn(e.getMessage(), e);
return new BaseResponse(String.valueOf(HttpStatus.FORBIDDEN.value()), e.getMessage(), null);
}
/**
* @param req
* @param e
* @return com.lemon.web.dto.BaseResponse
* @description
* @author lemon
* @date 2020-07-06 08:49
*/
@ExceptionHandler(value = ConstraintViolationException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
@ResponseBody
public BaseResponse constraintViolationExceptionHandler(HttpServletRequest req, ConstraintViolationException e) {
Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
String errorMsg = violations.stream()
.map((violation) -> String.format("%s: %s", violation.getPropertyPath(), violation.getMessage()))
.collect(Collectors.joining("\n"));
log.debug(errorMsg, e);
return new BaseResponse(String.valueOf(HttpStatus.BAD_REQUEST.value()), errorMsg, null);
}
/**
* @param request
* @param e
* @return com.lemon.web.dto.BaseResponse
* @description
* @author lemon
* @date 2020-07-06 08:49
*/
@ExceptionHandler(value = Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public BaseResponse exceptionHandler(HttpServletRequest request, Exception e) {
log.error(e.getMessage(), e);
return new BaseResponse(String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value()), e.getMessage(), null);
}
/**
* @param request
* @param e
* @return com.lemon.web.dto.BaseResponse
* @description 参数格式和 @RequestParam 不符
* @author lemon
* @date 2020-07-06 08:45
*/
@ExceptionHandler(value = MethodArgumentTypeMismatchException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public BaseResponse methodArgumentTypeMismatchExceptionHandler(HttpServletRequest request, MethodArgumentTypeMismatchException e) {
String err = String.format("field: %s. %s", e.getName(), e.getMessage());
log.warn(err, e);
return new BaseResponse(String.valueOf(HttpStatus.BAD_REQUEST.value()), err, null);
}
/**
* Customize the response for HttpMessageNotReadableException.
* <p>This method delegates to {@link #handleExceptionInternal}.
*
* @param ex the exception
* @param headers the headers to be written to the response
* @param status the selected response status
* @param request the current request
* @return a {@code ResponseEntity} instance
*/
@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(
HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
String message = "Required request body is missing";
log.debug(message, ex);
return handleExceptionInternal(ex, message, headers, status, request);
}
/**
* Customize the response for MethodArgumentNotValidException.
* <p>This method delegates to {@link #handleExceptionInternal}.
* <p>@RequestBody 校验违反约束
*
* @param ex the exception
* @param headers the headers to be written to the response
* @param status the selected response status
* @param request the current request
* @return a {@code ResponseEntity} instance
*/
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
String errorFieldMessage = ResponseUtil.getErrorFieldMessage(ex, ex.getBindingResult().getAllErrors());
log.debug(errorFieldMessage, ex);
return handleExceptionInternal(ex, errorFieldMessage, headers, status, request);
}
/**
* Customize the response for BindException.
* <p>This method delegates to {@link #handleExceptionInternal}.
* <p>表单对象校验
*
* @param ex the exception
* @param headers the headers to be written to the response
* @param status the selected response status
* @param request the current request
* @return a {@code ResponseEntity} instance
*/
@Override
protected ResponseEntity<Object> handleBindException(
BindException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
String errorFieldMessage = ResponseUtil.getErrorFieldMessage(ex, ex.getBindingResult().getAllErrors());
log.debug(errorFieldMessage, ex);
return handleExceptionInternal(ex, errorFieldMessage, headers, status, request);
}
/**
* A single place to customize the response body of all exception types.
* <p>The default implementation sets the {@link WebUtils#ERROR_EXCEPTION_ATTRIBUTE}
* request attribute and creates a {@link ResponseEntity} from the given
* body, headers, and status.
*
* @param ex the exception
* @param body the body for the response
* @param headers the headers for the response
* @param status the response status
* @param request the current request
*/
@Override
protected ResponseEntity<Object> handleExceptionInternal(
Exception ex, @Nullable Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) {
request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, WebRequest.SCOPE_REQUEST);
}
String message = ex.getMessage();
if (body != null) {
message = body.toString();
}
log.error(String.format("exception:%s, message:%s, class:%s", ex.getMessage(), message, ex.getClass()), ex);
BaseResponse responseBody = new BaseResponse(String.valueOf(status.value()), message, null);
return new ResponseEntity<>(responseBody, headers, status);
}
}
@Slf4j
public class ResponseUtil {
public static Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
Class selectedConverterType, ServerHttpRequest request,
ServerHttpResponse response, List<String> ignoreUrls) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest servletRequest = attributes.getRequest();
String requestUri = servletRequest.getRequestURI();
if (StringUtils.isEmpty(requestUri)) {
requestUri = request.getURI().getPath();
}
if (!ignoreUrls.isEmpty() && ignoreUrls.contains(requestUri.toLowerCase())) {
log.debug("requestUri ignore:{}", requestUri);
return body;
}
if (!(body instanceof BaseResponse)) {
BaseResponse baseResponse = new BaseResponse(body);
// 因为handler处理类的返回类型是String,为了保证数据类型一致性,这里需要将 ResponseResult 转回去
if (body instanceof String) {
Gson gson = new Gson();
return gson.toJson(baseResponse);
}
return baseResponse;
}
return body;
}
/**
* @param ex
* @param allErrors
* @return java.lang.String
* @description 参数 字段 校验错误信息
* @author lemon
* @date 2020-07-02 14:35
*/
public static String getErrorFieldMessage(Exception ex, List<ObjectError> allErrors) {
List<String> msgs = Lists.newLinkedList();
for (ObjectError error : allErrors) {
if (error instanceof FieldError) {
FieldError fieldError = (FieldError) error;
msgs.add(String.format("%s %s", fieldError.getField(), fieldError.getDefaultMessage()));
} else {
msgs.add(ex.getMessage());
}
}
return Joiner.on(";").join(msgs);
}
}