青核后端
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

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("服务器内部错误");
}
}