Controller全局异常处理

全局异常统一处理

package com.frank.config;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
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.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.servlet.http.HttpServletRequest;

@Log4j2
@RestControllerAdvice
public class GlobalExceptionHandler {

    @Autowired
    private ObjectMapper mapper;

	// 参数类型错误
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public <T> Api<T> methodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request) {
        log.error("接口参数类型异常,路径:{},参数名:{},参数类型:{},参数值:{}",
                request.getRequestURI(),
                e.getName(),
                e.getRequiredType().getSimpleName(),
                e.getValue(), e);
        return Api.error("参数错误");
    }
    
	// @Validated参数校验失败
    @ExceptionHandler(BindException.class)
    public <T> Api<T> bindExceptionHandler(BindException e, HttpServletRequest request) throws JsonProcessingException {
        FieldError fieldError = e.getBindingResult().getFieldError();
        log.error("接口参数校验异常,路径:{},入参:{},参数名:{},参数值:{},信息:{}",
                request.getRequestURI(),
                mapper.writeValueAsString(e.getBindingResult().getTarget()),
                fieldError.getField(),
                fieldError.getRejectedValue(),
                fieldError.getDefaultMessage(), e);
        return Api.error(e.getBindingResult().getFieldError().getDefaultMessage());
    }

	// @RequestBody @Validated参数校验失败
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public <T> Api<T> methodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) throws JsonProcessingException {
        FieldError fieldError = e.getBindingResult().getFieldError();
        log.error("接口参数校验异常,路径:{},入参:{},参数名:{},参数值:{},信息:{}",
                request.getRequestURI(),
                mapper.writeValueAsString(e.getBindingResult().getTarget()),
                fieldError.getField(),
                fieldError.getRejectedValue(),
                fieldError.getDefaultMessage(), e);
        return Api.error(fieldError.getDefaultMessage());
    }

	// @RequestParam参数缺失异常
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public <T> Api<T> exception(MissingServletRequestParameterException e, HttpServletRequest request) {
        log.error("接口参数缺少异常,路径:{},参数名:{},参数类型:{}",
                request.getRequestURI(),
                e.getParameterName(),
                e.getParameterType(), e);
        return Api.error("参数错误");
    }

    @ExceptionHandler(Exception.class)
    public <T> Api<T> exception(Exception e, HttpServletRequest request) {
        log.error("接口异常,路径:{}", request.getRequestURI(), e);
        return Api.error("系统错误");
    }
}

校验快速失败设置

    @Bean
    public Validator validator() {
        ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
                .configure()
                //failFast的意思只要出现校验失败的情况,就立即结束校验,不再进行后续的校验。
                .failFast(true)
                .buildValidatorFactory();

        return validatorFactory.getValidator();
    }

参考链接:https://www.cnblogs.com/panchanggui/p/11758242.html

### 如何在控制器中实现全局异常处理 #### 定义统一响应体 为了确保返回给客户端的信息一致性和标准化,定义一个统一的响应体是非常重要的。这有助于使API更加易于理解和维护。 ```java public class ApiResponse<T> { private boolean success; private String message; private T data; public ApiResponse(boolean success, String message, T data) { this.success = success; this.message = message; this.data = data; } // Getters and Setters... } ``` #### 实现全局异常处理 创建一个带有`@ControllerAdvice`注解的类作为全局异常处理器,它可以拦截整个应用程序中的任何未被捕获的异常,并对其进行适当处理[^1]。 ```java @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(ResourceNotFoundException.class) protected ResponseEntity<ApiResponse<?>> handleResourceNotFound(final ResourceNotFoundException ex) { final ErrorResponse errorResponse = new ErrorResponse(ex.getMessage()); return new ResponseEntity<>(new ApiResponse<>(false, "Not Found", errorResponse), HttpStatus.NOT_FOUND); } @ExceptionHandler(Exception.class) protected ResponseEntity<ApiResponse<?>> handleException(final Exception ex) { final ErrorResponse errorResponse = new ErrorResponse("An unexpected error occurred"); return new ResponseEntity<>(new ApiResponse<>(false, "Error", errorResponse), HttpStatus.INTERNAL_SERVER_ERROR); } } ``` 这里展示了两种类型的异常处理方法:一种专门针对特定业务场景下的资源找不到的情况;另一种则是更为宽泛的一般性错误捕捉器,适用于所有其他未知情况。 #### 自定义异常类 对于某些特殊需求,还可以创建自己的异常类型以便更好地描述问题所在。下面是一个简单的例子: ```java public class ResourceNotFoundException extends RuntimeException { public ResourceNotFoundException(String message) { super(message); } } ``` 当某个服务端操作未能找到预期的数据时就可以抛出此类异常,而无需每次都编写相同的逻辑来构建HTTP响应消息[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值