All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mobaijun.web.handler.GlobalExceptionHandler Maven / Gradle / Ivy

/*
 * Copyright (C) 2022 [www.mobaijun.com]
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.mobaijun.web.handler;

import com.mobaijun.common.enums.http.HttpStatus;
import com.mobaijun.common.result.R;
import com.mobaijun.core.exception.ServiceException;
import com.mobaijun.core.exception.base.BaseException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import java.io.IOException;
import java.nio.file.AccessDeniedException;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
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.servlet.NoHandlerFoundException;

/**
 * Description: 全局异常处理器,用于捕获和处理不同类型的异常,并返回适当的响应信息。
 * Author: [mobaijun]
 * Date: [2024/8/13 18:06]
 * IntelliJ IDEA Version: [IntelliJ IDEA 2023.1.4]
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 处理 HTTP 请求方式不支持异常
     * 

* 当客户端使用不支持的 HTTP 请求方法访问资源时,Spring 会抛出 {@link HttpRequestMethodNotSupportedException} 异常。 * 本方法捕获此异常,并返回相应的错误信息。 * * @param e 捕获到的 {@link HttpRequestMethodNotSupportedException} 异常对象 * @param request 当前的 HTTP 请求对象 * @return 封装的响应结果,包含 HTTP 状态码 405 (Method Not Allowed) 和异常信息 */ @ExceptionHandler(HttpRequestMethodNotSupportedException.class) public R handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e, HttpServletRequest request) { log.error("请求地址 '{}' 不支持 '{}' 请求方法", request.getRequestURI(), e.getMethod()); return buildErrorResponse(HttpStatus.METHOD_NOT_ALLOWED, e.getMessage()); } /** * 处理请求路径中缺少必需的路径变量异常 * * @param e 捕获到的 {@link MissingPathVariableException} 异常对象 * @param request 当前的 HTTP 请求对象 * @return 封装的响应结果,包含缺少的路径变量信息 */ @ExceptionHandler(MissingPathVariableException.class) public R handleMissingPathVariableException(MissingPathVariableException e, HttpServletRequest request) { log.error("请求路径'{}'中缺少必需的路径变量'{}',发生系统异常.", request.getRequestURI(), e.getVariableName()); return buildErrorResponse(HttpStatus.INVALID_ARGUMENT, String.format("请求路径中缺少必需的路径变量 [%s]", e.getVariableName())); } /** * 处理请求参数类型不匹配异常 * * @param e 捕获到的 {@link MethodArgumentTypeMismatchException} 异常对象 * @param request 当前的 HTTP 请求对象 * @return 封装的响应结果,包含参数名、要求的类型和输入值 */ @ExceptionHandler(MethodArgumentTypeMismatchException.class) public R handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request) { log.error("请求路径 '{}' 的参数 '{}' 类型不匹配", request.getRequestURI(), e.getName()); String errorMessage = String.format("请求参数类型不匹配,参数 [%s] 要求类型为:'%s',但输入值为:'%s'", e.getName(), Objects.requireNonNull(e.getRequiredType()).getName(), e.getValue()); return buildErrorResponse(HttpStatus.INVALID_ARGUMENT, errorMessage); } /** * 处理找不到路由异常 * * @param e 捕获到的 {@link NoHandlerFoundException} 异常对象 * @param request 当前的 HTTP 请求对象 * @return 封装的响应结果,包含 404 状态码和错误信息 */ @ExceptionHandler(NoHandlerFoundException.class) @ResponseStatus(org.springframework.http.HttpStatus.NOT_FOUND) public R handleNoHandlerFoundException(NoHandlerFoundException e, HttpServletRequest request) { log.error("请求地址 '{}' 不存在", request.getRequestURI()); return buildErrorResponse(HttpStatus.NOT_FOUND, e.getMessage()); } /** * 处理访问拒绝异常 * * @param e 捕获到的 {@link java.nio.file.AccessDeniedException} 异常对象 * @param request 当前的 HTTP 请求对象 * @return 封装的响应结果,包含 403 状态码和错误信息 */ @ExceptionHandler(AccessDeniedException.class) @ResponseStatus(org.springframework.http.HttpStatus.FORBIDDEN) public R handleAccessDeniedException(AccessDeniedException e, HttpServletRequest request) { log.error("请求地址 '{}' 无权限访问", request.getRequestURI(), e); return buildErrorResponse(HttpStatus.UNAUTHENTICATED, "无权限访问该资源"); } /** * 处理文件上传大小超限异常 * * @param e 捕获到的 {@link org.springframework.web.multipart.MaxUploadSizeExceededException} 异常对象 * @return 封装的响应结果,包含文件上传大小超限的错误信息 */ @ExceptionHandler(MaxUploadSizeExceededException.class) @ResponseStatus(org.springframework.http.HttpStatus.PAYLOAD_TOO_LARGE) public R handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) { log.error("文件上传大小超限", e); return buildErrorResponse(HttpStatus.PAYLOAD_TOO_LARGE, "文件大小超限"); } /** * 处理文件读取异常 * * @param e 捕获到的 {@link java.io.IOException} 异常对象 * @return 封装的响应结果,包含文件读取异常的信息 */ @ExceptionHandler(IOException.class) public R handleIOException(IOException e) { log.error("文件操作异常", e); return buildErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, "文件操作失败"); } /** * 处理未知的运行时异常 * * @param e 捕获到的 {@link RuntimeException} 异常对象 * @param request 当前的 HTTP 请求对象 * @return 封装的响应结果,包含异常信息 */ @ExceptionHandler(RuntimeException.class) public R handleRuntimeException(RuntimeException e, HttpServletRequest request) { log.error("请求地址 '{}' 发生未知异常", request.getRequestURI(), e); return buildErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage()); } /** * 处理系统异常 * * @param e 捕获到的 {@link Exception} 异常对象 * @param request 当前的 HTTP 请求对象 * @return 封装的响应结果,包含异常信息 */ @ExceptionHandler(Exception.class) public R handleException(Exception e, HttpServletRequest request) { log.error("请求地址 '{}' 发生系统异常", request.getRequestURI(), e); return buildErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage()); } /** * 处理自定义验证异常(绑定异常) * * @param e 捕获到的 {@link BindException} 异常对象 * @return 封装的响应结果,包含所有验证错误信息 */ @ExceptionHandler(BindException.class) public R handleBindException(BindException e) { log.error("参数绑定异常", e); String message = e.getAllErrors().stream() .map(DefaultMessageSourceResolvable::getDefaultMessage) .collect(Collectors.joining(", ")); return buildErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, message); } /** * 处理自定义验证异常(约束违规异常) * * @param e 捕获到的 {@link ConstraintViolationException} 异常对象 * @return 封装的响应结果,包含所有约束违规错误信息 */ @ExceptionHandler(ConstraintViolationException.class) public R handleConstraintViolationException(ConstraintViolationException e) { log.error("约束违规异常", e); String message = e.getConstraintViolations().stream() .map(ConstraintViolation::getMessage) .collect(Collectors.joining(", ")); return buildErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, message); } /** * 处理自定义验证异常(方法参数无效异常) * * @param e 捕获到的 {@link MethodArgumentNotValidException} 异常对象 * @return 封装的响应结果,包含第一个字段的验证错误信息 */ @ExceptionHandler(MethodArgumentNotValidException.class) public R handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { log.error("方法参数无效异常", e); String message = Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage(); return buildErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, message); } /** * 处理空指针异常 * * @param e 捕获到的 {@link NullPointerException} 异常对象 * @param request 当前的 HTTP 请求对象 * @return 封装的响应结果,包含 500 状态码和错误信息 */ @ExceptionHandler(NullPointerException.class) @ResponseStatus(org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR) public R handleNullPointerException(NullPointerException e, HttpServletRequest request) { log.error("请求地址 '{}' 发生空指针异常", request.getRequestURI(), e); return buildErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, "系统发生错误{ %s },请稍后再试!".formatted(e.getMessage())); } /** * 处理业务异常 * * @param e 捕获到的业务异常对象 * @param request 当前的HTTP请求对象 * @return 封装的响应结果,包含错误码和错误信息 */ @ExceptionHandler(ServiceException.class) public R handleServiceException(ServiceException e, HttpServletRequest request) { log.error("业务异常发生,异常信息: {}, 请求路径: {}", e.getMessage(), request.getRequestURI()); return buildErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, "系统发生错误{ %s },请稍后再试!".formatted(e.getMessage())); } /** * 处理基础异常 * * @param e 捕获到的基础异常对象 * @param request 当前的HTTP请求对象 * @return 封装的响应结果,包含错误信息 */ @ExceptionHandler(BaseException.class) public R handleBaseException(BaseException e, HttpServletRequest request) { log.error("基础异常发生,异常信息: {}, 请求路径: {}", e.getMessage(), request.getRequestURI()); return buildErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, "系统发生错误{ %s },请稍后再试!".formatted(e.getMessage())); } /** * 统一构建错误响应的工具方法 * * @param status HTTP 状态码 * @param message 错误信息 * @return 封装的响应结果 */ private R buildErrorResponse(HttpStatus status, String message) { return R.failed(status, message); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy