You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
5.1 KiB
116 lines
5.1 KiB
package com.campus.common;
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
|
|
import org.springframework.http.converter.HttpMessageNotReadableException;
|
|
import org.springframework.http.HttpStatus;
|
|
import org.springframework.validation.BindException;
|
|
import org.springframework.validation.FieldError;
|
|
import org.springframework.web.bind.MethodArgumentNotValidException;
|
|
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.multipart.MaxUploadSizeExceededException;
|
|
import org.springframework.web.multipart.MultipartException;
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
@Slf4j
|
|
@RestControllerAdvice
|
|
public class GlobalExceptionHandler {
|
|
|
|
@ExceptionHandler(HttpMessageNotReadableException.class)
|
|
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
|
public Result<Void> handleMessageNotReadableException(HttpMessageNotReadableException ex) {
|
|
// 不输出请求原文,避免将个人资料或其他敏感参数写入日志。
|
|
Throwable cause = ex;
|
|
while (cause != null) {
|
|
if (cause instanceof InvalidFormatException) {
|
|
InvalidFormatException invalid = (InvalidFormatException) cause;
|
|
if (java.util.Date.class.equals(invalid.getTargetType())
|
|
&& !invalid.getPath().isEmpty()
|
|
&& "birthday".equals(invalid.getPath().get(invalid.getPath().size() - 1).getFieldName())) {
|
|
return Result.error(400, "生日格式不正确,请使用 yyyy-MM-dd(例如 2000-06-01)");
|
|
}
|
|
}
|
|
cause = cause.getCause();
|
|
}
|
|
return Result.error(400, "请求体格式不正确,请检查参数类型和 JSON 格式");
|
|
}
|
|
|
|
@ExceptionHandler(MethodArgumentNotValidException.class)
|
|
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
|
public Result<Void> handleValidationException(MethodArgumentNotValidException ex) {
|
|
String message = ex.getBindingResult().getFieldErrors().stream()
|
|
.map(FieldError::getDefaultMessage)
|
|
.collect(Collectors.joining("; "));
|
|
log.warn("Validation failed: {}", message);
|
|
return Result.error(400, message);
|
|
}
|
|
|
|
@ExceptionHandler(BindException.class)
|
|
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
|
public Result<Void> handleBindException(BindException ex) {
|
|
String message = ex.getFieldErrors().stream()
|
|
.map(FieldError::getDefaultMessage)
|
|
.collect(Collectors.joining("; "));
|
|
log.warn("Binding failed: {}", message);
|
|
return Result.error(400, message);
|
|
}
|
|
|
|
@ExceptionHandler(MaxUploadSizeExceededException.class)
|
|
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
|
public Result<Void> handleMaxUploadSizeExceededException(MaxUploadSizeExceededException ex) {
|
|
log.warn("File size exceeded: {}", ex.getMessage());
|
|
return Result.error(400, "文件大小超过限制,请压缩后重新上传(最大100MB)");
|
|
}
|
|
|
|
@ExceptionHandler(MultipartException.class)
|
|
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
|
public Result<Void> handleMultipartException(MultipartException ex) {
|
|
log.error("Multipart parsing failed: {}", ex.getMessage());
|
|
return Result.error(400, "文件上传失败,请检查网络连接或文件格式后重试");
|
|
}
|
|
|
|
@ExceptionHandler(BusinessException.class)
|
|
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
|
public Result<Void> handleBusinessException(BusinessException ex) {
|
|
log.warn("Business exception: {}", ex.getMessage());
|
|
return Result.error(400, ex.getMessage());
|
|
}
|
|
|
|
@ExceptionHandler(ForbiddenException.class)
|
|
@ResponseStatus(HttpStatus.FORBIDDEN)
|
|
public Result<Void> handleForbiddenException(ForbiddenException ex) {
|
|
log.warn("Forbidden operation: {}", ex.getMessage());
|
|
return Result.error(403, ex.getMessage());
|
|
}
|
|
|
|
@ExceptionHandler(ServiceUnavailableException.class)
|
|
@ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE)
|
|
public Result<Void> handleServiceUnavailableException(ServiceUnavailableException ex) {
|
|
log.error("Service unavailable: {}", ex.getMessage());
|
|
return Result.error(503, ex.getMessage());
|
|
}
|
|
|
|
@ExceptionHandler(TooManyRequestsException.class)
|
|
@ResponseStatus(HttpStatus.TOO_MANY_REQUESTS)
|
|
public Result<Void> handleTooManyRequestsException(TooManyRequestsException ex) {
|
|
log.warn("Too many requests: {}", ex.getMessage());
|
|
return Result.error(429, ex.getMessage());
|
|
}
|
|
|
|
@ExceptionHandler(RuntimeException.class)
|
|
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
|
public Result<Void> handleRuntimeException(RuntimeException ex) {
|
|
log.error("Runtime exception: ", ex);
|
|
return Result.error(500, "服务器内部错误");
|
|
}
|
|
|
|
@ExceptionHandler(Exception.class)
|
|
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
|
public Result<Void> handleException(Exception ex) {
|
|
log.error("Unexpected exception: ", ex);
|
|
return Result.error("服务器内部错误");
|
|
}
|
|
}
|
|
|