123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- package com.simuwang.deploy.components;
- import cn.hutool.core.exceptions.ExceptionUtil;
- import cn.hutool.core.util.StrUtil;
- import com.simuwang.base.common.exception.APIException;
- import com.simuwang.base.common.exception.ErrorInfo;
- import com.smppw.common.pojo.enums.status.ResultCode;
- import jakarta.servlet.ServletException;
- import jakarta.servlet.http.HttpServletRequest;
- import jakarta.servlet.http.HttpServletResponse;
- import jakarta.validation.ConstraintViolationException;
- import org.apache.commons.lang3.StringUtils;
- import org.apache.shiro.authc.AuthenticationException;
- import org.apache.shiro.authc.IncorrectCredentialsException;
- import org.apache.shiro.authc.UnknownAccountException;
- import org.apache.shiro.authz.UnauthenticatedException;
- import org.apache.shiro.authz.UnauthorizedException;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.boot.context.properties.bind.validation.BindValidationException;
- import org.springframework.core.Ordered;
- import org.springframework.http.HttpStatus;
- import org.springframework.http.converter.HttpMessageNotReadableException;
- import org.springframework.lang.Nullable;
- import org.springframework.stereotype.Component;
- import org.springframework.validation.BindException;
- import org.springframework.validation.ObjectError;
- import org.springframework.web.servlet.HandlerExceptionResolver;
- import org.springframework.web.servlet.ModelAndView;
- import org.springframework.web.servlet.resource.NoResourceFoundException;
- import org.springframework.web.util.WebUtils;
- import java.time.LocalDateTime;
- import java.util.List;
- /**
- * @author wangzaijun
- * @date 2023/8/12 16:23
- * @description 错误信息构造工具
- */
- @Component
- public class ErrorInfoBuilder implements HandlerExceptionResolver, Ordered {
- /**
- * 错误KEY
- */
- private final static String ERROR_NAME = "simuwang.error";
- private final Logger logger = LoggerFactory.getLogger(this.getClass());
- // /**
- // * 错误配置(ErrorConfiguration)
- // */
- // private final ErrorProperties errorProperties;
- //
- // /**
- // * 错误构造器 (Constructor) 传递配置属性:server.xx -> server.error.xx
- // */
- // public ErrorInfoBuilder(ServerProperties serverProperties) {
- // this.errorProperties = serverProperties.getError();
- // }
- /**
- * 构建错误信息.(ErrorInfo)
- */
- public ErrorInfo getErrorInfo(HttpServletRequest request) {
- return getErrorInfo(request, getError(request));
- }
- /**
- * 构建错误信息.(ErrorInfo)
- */
- public ErrorInfo getErrorInfo(HttpServletRequest request, Throwable error) {
- String url = request.getAttribute(WebUtils.ERROR_REQUEST_URI_ATTRIBUTE).toString();
- ErrorInfo errorInfo = new ErrorInfo();
- errorInfo.setTime(LocalDateTime.now().toString());
- errorInfo.setUrl(url);
- String msg;
- int code = getHttpStatus(request).value();
- if (error instanceof NoResourceFoundException) {
- msg = "请求资源找不到";
- } else if (error instanceof UnauthorizedException) {
- msg = "没有对应接口的权限";
- } else if (error instanceof UnknownAccountException || error instanceof IncorrectCredentialsException) {
- msg = ResultCode.AUTH_FAILD.getMsg();
- } else if (error instanceof AuthenticationException) {
- code = HttpStatus.UNAUTHORIZED.value();
- msg = "登录认证失败";
- } else if (error instanceof APIException e) {
- msg = e.getMsg();
- code = e.getCode();
- } else if (error instanceof UnauthenticatedException e) {
- msg = e.getMessage();
- } else if (error instanceof HttpMessageNotReadableException || error instanceof BindValidationException) {
- msg = "请求参数错误";
- } else if (error instanceof BindException e) {
- // 参数绑定或校验错误
- List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
- msg = allErrors.get(0).getDefaultMessage();
- } else if (error instanceof ConstraintViolationException e) {
- // 约束验证错误
- msg = e.getMessage();
- } else {
- msg = "未知的错误";
- }
- errorInfo.setError(msg);
- errorInfo.setStatusCode(code);
- errorInfo.setReasonPhrase(getHttpStatus(request).getReasonPhrase());
- errorInfo.setStackTrace(ExceptionUtil.stacktraceToString(error));
- logger.error(StrUtil.format("{} 接口请求错误:{}", url, errorInfo.getStackTrace()));
- return errorInfo;
- }
- /**
- * 获取错误.(Error/Exception)
- *
- * @see org.springframework.boot.web.servlet.error.DefaultErrorAttributes #addErrorDetails
- */
- public Throwable getError(HttpServletRequest request) {
- //根据HandlerExceptionResolver接口方法来获取错误.
- Throwable error = (Throwable) request.getAttribute(ERROR_NAME);
- //根据Request对象获取错误.
- if (error == null) {
- error = (Throwable) request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE);
- }
- //当获取错误非空,取出RootCause.
- if (error != null) {
- while (error instanceof ServletException && error.getCause() != null) {
- error = error.getCause();
- }
- } else {
- //当获取错误为null,此时我们设置错误信息即可.
- String message = (String) request.getAttribute(WebUtils.ERROR_MESSAGE_ATTRIBUTE);
- if (StringUtils.isEmpty(message)) {
- HttpStatus status = getHttpStatus(request);
- message = "Unknown Exception But " + status.value() + " " + status.getReasonPhrase();
- }
- error = new Exception(message);
- }
- return error;
- }
- /**
- * 获取通信状态(HttpStatus)
- *
- * @see org.springframework.boot.autoconfigure.web.servlet.error.AbstractErrorController #getStatus
- */
- public HttpStatus getHttpStatus(HttpServletRequest request) {
- Integer statusCode = (Integer) request.getAttribute(WebUtils.ERROR_STATUS_CODE_ATTRIBUTE);
- try {
- return statusCode != null ? HttpStatus.valueOf(statusCode) : HttpStatus.INTERNAL_SERVER_ERROR;
- } catch (Exception ex) {
- return HttpStatus.INTERNAL_SERVER_ERROR;
- }
- }
- // /**
- // * 获取堆栈轨迹(StackTrace)
- // *
- // * @see org.springframework.boot.web.servlet.error.DefaultErrorAttributes #addStackTrace
- // */
- // public String getStackTraceInfo(Throwable error, boolean flag) {
- // if (!flag) {
- // return "omitted";
- // }
- // StringWriter stackTrace = new StringWriter();
- // error.printStackTrace(new PrintWriter(stackTrace));
- // stackTrace.flush();
- // return stackTrace.toString();
- // }
- // /**
- // * 判断是否包含堆栈轨迹.(isIncludeStackTrace)
- // *
- // * @see org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController #isIncludeStackTrace
- // */
- // public boolean isIncludeStackTrace(HttpServletRequest request) {
- //
- // //读取错误配置(server.error.include-stacktrace=NEVER)
- // ErrorProperties.IncludeAttribute includeStacktrace = errorProperties.getIncludeStacktrace();
- //
- // //情况1:若IncludeStacktrace为ALWAYS
- // if (includeStacktrace == ErrorProperties.IncludeAttribute.ALWAYS) {
- // return true;
- // }
- // //情况2:若请求参数含有trace
- // if (includeStacktrace == ErrorProperties.IncludeAttribute.ON_PARAM) {
- // String parameter = request.getParameter("trace");
- // return parameter != null && !"false".equalsIgnoreCase(parameter);
- // }
- // //情况3:其它情况
- // return false;
- // }
- /**
- * 保存错误/异常.
- *
- * @see org.springframework.web.servlet.DispatcherServlet #processHandlerException 进行选举HandlerExceptionResolver
- */
- @Override
- public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) {
- request.setAttribute(ERROR_NAME, ex);
- return null;
- }
- /**
- * 提供优先级 或用于排序
- */
- @Override
- public int getOrder() {
- return HIGHEST_PRECEDENCE;
- }
- }
|