全局异常拦截

package com.test.common.core.handle;

import com.alibaba.csp.sentinel.Tracer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 全局异常处理器 
 * R 全局返回实体 R.failed(message) 构建请求失败返回实体 根据实际项目变更
 */
@Slf4j
@RestController
@RestControllerAdvice
public class GlobalExceptionHandler {
   
   /**
    * 处理Exception
    *
    * @param e Exception
    * @return R 全局返回实体 R.failed(message) 构建请求失败返回实体
    */
   @ExceptionHandler(Exception.class)
   @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
   public R<String> handleGlobalException(Exception e) {
      log.error("全局异常信息 ex={}", e.getMessage(), e);
      // 可以结合sentinel,业务异常交由 sentinel 记录
      // Tracer.trace(e);
      return R.failed(e.getLocalizedMessage());
   }
   
   /**
    * 处理AccessDeniedException
    *
    * @param e AccessDeniedException
    * @return R
    */
   @ExceptionHandler(AccessDeniedException.class)
   @ResponseStatus(HttpStatus.FORBIDDEN)
   public R<String> handleAccessDeniedException(AccessDeniedException e) {
      log.error("拒绝授权异常信息 ex={}", e.getMessage());
      return R.failed("权限不足,不允许访问");
   }
   
   /**
    * 处理MethodArgumentNotValidException
    * 请求参数实体被@RequestBody标记,内部属性校验失败后会抛出该异常
    *
    * @param exception MethodArgumentNotValidException
    * @return R
    */
   @ExceptionHandler({MethodArgumentNotValidException.class})
   @ResponseStatus(HttpStatus.BAD_REQUEST)
   public R<String> handleBodyValidException(MethodArgumentNotValidException exception) {
      log.error(exception.getMessage(), exception);
		String message = exception.getBindingResult()
				.getFieldErrors()
				.stream()
				.map(FieldError::getDefaultMessage)
				.collect(Collectors.joining(";"));
		return R.failed(message);
   }
   
   /**
    * 处理BindException
    * Get请求且请求参数为实体且未被@RequestBody标记,内部属性校验失败后会抛出该异常
    *
    * @param exception BindException
    * @return R
    */
   @ExceptionHandler({BindException.class})
   @ResponseStatus(HttpStatus.BAD_REQUEST)
   public R<String> bindExceptionHandler(BindException exception) {
      log.error(exception.getMessage(), exception);
      String message = exception.getBindingResult()
            .getAllErrors()
            .stream()
            .map(ObjectError::getDefaultMessage)
            .collect(Collectors.joining(";"));
      return R.failed(message);
   }
   
   /**
    * 处理ConstraintViolationException
    * 请求参数被@RequestParam、@PathVariable标记,该属性校验失败后会抛出该异常
    *
    * @param exception ConstraintViolationException
    * @return R
    */
   @ExceptionHandler({ConstraintViolationException.class})
   @ResponseStatus(HttpStatus.BAD_REQUEST)
   public R<String> exceptionHandler(ConstraintViolationException exception) {
      log.error(exception.getMessage(), exception);
      String message = exception.getConstraintViolations()
            .stream().map(ConstraintViolation::getMessage)
            .collect(Collectors.joining(";"));
      return R.failed(message);
   }
   
   /**
    * 避免 404 重定向到 /error 导致NPE ,ignore-url 需要配置对应端点
    *
    * @return R
    */
   @DeleteMapping("/error")
   @ResponseStatus(HttpStatus.NOT_FOUND)
   public R<String> noHandlerFoundException() {
      return R.failed(HttpStatus.NOT_FOUND.getReasonPhrase());
   }
   
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值