fourcal/src/main/java/cn/palmte/work/config/ApplicationExceptionHandler...

178 lines
7.1 KiB
Java

package cn.palmte.work.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.http.HttpStatus;
import org.springframework.util.ObjectUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.transaction.TransactionSystemException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import cn.palmte.work.ErrorMessage;
import cn.palmte.work.ErrorMessageException;
import cn.palmte.work.Json;
import cn.palmte.work.Result;
import cn.palmte.work.ValidationError;
import cn.palmte.work.controller.backend.ProcessController;
/**
* 异常处理
*
* @author <a href="https://github.com/TAKETODAY">Harry Yang</a>
* @since 2.0 2022/12/30 15:24
*/
@RestControllerAdvice(assignableTypes = ProcessController.class)
public class ApplicationExceptionHandler {
private static final Logger log = LoggerFactory.getLogger(ApplicationExceptionHandler.class);
public static final ErrorMessage argsErrorMessage = ErrorMessage.failed("参数错误");
public static final ErrorMessage sizeExceeded = ErrorMessage.failed("上传文件大小超出限制");
public static final ErrorMessage methodNotSupported = ErrorMessage.failed("请求方式不支持");
public static final ErrorMessage internalServerError = ErrorMessage.failed("服务器内部异常");
public static final ErrorMessage notWritableError = ErrorMessage.failed("数据无法正常返回到客户端");
@ExceptionHandler(ErrorMessageException.class)
public ResponseEntity<ErrorMessage> errorMessage(ErrorMessageException errorMessage) {
HttpStatus httpStatus = errorMessage.getStatus();
return ResponseEntity.status(httpStatus)
.body(ErrorMessage.failed(errorMessage.getMessage()));
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(IllegalArgumentException.class)
public ErrorMessage badRequest(IllegalArgumentException exception) {
return ErrorMessage.failed(exception.getMessage());
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler({ MaxUploadSizeExceededException.class })
public ErrorMessage badRequest() {
return sizeExceeded;
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public ErrorMessage methodNotSupported() {
return methodNotSupported;
}
@ExceptionHandler
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ErrorMessage error(Exception exception) {
log.error("An Exception occurred", exception);
if (exception instanceof SQLException) {
return internalServerError;
}
if (exception instanceof HttpMessageNotWritableException) {
return notWritableError;
}
if (exception instanceof TransactionSystemException) {
return ErrorMessage.failed("数据库出错");
}
return ErrorMessage.failed(exception.getMessage());
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
public ErrorMessage typeMismatch(MethodArgumentTypeMismatchException mismatch) {
return ErrorMessage.failed("参数'" + mismatch.getName() + "'不能转换到对应类型");
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MissingServletRequestParameterException.class)
public ErrorMessage parameterError(MissingServletRequestParameterException e) {
return ErrorMessage.failed("缺少参数'" + e.getParameterName() + "'");
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler({
MultipartException.class,
HttpMessageNotReadableException.class,
HttpMediaTypeNotSupportedException.class
})
public ErrorMessage messageNotReadable() {
return argsErrorMessage;
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler({ BindException.class, MethodArgumentNotValidException.class })
public Result validExceptionHandler(Exception e) {
BindingResult result;
if (e instanceof MethodArgumentNotValidException) {
result = ((MethodArgumentNotValidException) e).getBindingResult();
}
else if (e instanceof BindException) {
result = (BindingResult) e;
}
else {
return ErrorMessage.failed();
}
List<ObjectError> allErrors = result.getAllErrors();
Map<String, String> model = new HashMap<>(16);
for (ObjectError error : allErrors) {
if (error instanceof FieldError) {
FieldError fieldError = (FieldError) error;
String field = fieldError.getField();
String defaultMessage = error.getDefaultMessage();
model.put(field, defaultMessage);
// log.error("[{}] -> [{}]", field, defaultMessage);
}
}
return ValidationError.failed(model);
}
@ExceptionHandler(NullPointerException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Json nullPointer(NullPointerException exception) {
log.error("An Exception occurred", exception);
final StackTraceElement[] stackTrace = exception.getStackTrace();
if (ObjectUtils.isEmpty(stackTrace)) {
return Json.failed("空指针", "暂无堆栈信息");
}
return Json.failed("空指针", stackTrace[0]);
}
@ExceptionHandler(DataAccessException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ErrorMessage dataAccessException(DataAccessException accessException) {
String message = getDataAccessMessage(accessException.getCause());
log.error(message, accessException);
return ErrorMessage.failed(message);
}
String getDataAccessMessage(Throwable cause) {
return "数据库出错";
}
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(DataAccessResourceFailureException.class)
public ErrorMessage dataAccessException(DataAccessResourceFailureException accessException) {
log.error("数据库连接出错", accessException);
return ErrorMessage.failed("数据库连接出错");
}
}