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());
}
}
全局异常拦截
最新推荐文章于 2023-10-02 17:13:17 发布