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

com.emily.infrastructure.web.exception.handler.GlobalExceptionCustomizer Maven / Gradle / Ivy

The newest version!
package com.emily.infrastructure.web.exception.handler;

import com.emily.infrastructure.common.PrintExceptionUtils;
import com.emily.infrastructure.common.constant.AttributeInfo;
import com.emily.infrastructure.date.DateComputeUtils;
import com.emily.infrastructure.date.DateConvertUtils;
import com.emily.infrastructure.date.DatePatternInfo;
import com.emily.infrastructure.logback.entity.BaseLogger;
import com.emily.infrastructure.logger.utils.PrintLoggerUtils;
import com.emily.infrastructure.sensitive.SensitiveUtils;
import com.emily.infrastructure.tracing.holder.LocalContextHolder;
import com.emily.infrastructure.tracing.holder.ServletStage;
import com.emily.infrastructure.web.exception.type.AppStatusType;
import com.emily.infrastructure.web.filter.helper.ServletHelper;
import com.emily.infrastructure.web.response.annotation.ApiResponsePackIgnore;
import com.emily.infrastructure.web.response.entity.BaseResponse;
import com.emily.infrastructure.web.servlet.interceptor.ParameterInterceptor;
import com.google.common.collect.Maps;
import com.otter.infrastructure.servlet.RequestUtils;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.method.HandlerMethod;

import java.lang.reflect.Method;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;

/**
 * 异常处理基础类
 *
 * @author Emily
 * @since Created in 2022/7/8 1:43 下午
 */
public class GlobalExceptionCustomizer {


    /**
     * 对API请求异常处理,
     * 1.如果标记了ApiResponseWrapperIgnore注解,则统一去除包装
     * 2.否则添加外层包装
     *
     * @param handlerMethod  控制器方法处理对象
     * @param httpStatusType 异常状态枚举
     * @return 包装或为包装的结果
     */
    public static Object getApiResponseWrapper(HandlerMethod handlerMethod, AppStatusType httpStatusType) {
        return getApiResponseWrapper(handlerMethod, httpStatusType.getStatus(), httpStatusType.getMessage());
    }

    /**
     * 对API请求异常处理,
     * 1.如果标记了ApiResponseWrapperIgnore注解,则统一去除包装
     * 2.否则添加外层包装
     *
     * @param handlerMethod 控制器方法处理对象
     * @param status        状态码
     * @param message       异常提示消息
     * @return 包装或为包装的结果
     */
    public static Object getApiResponseWrapper(HandlerMethod handlerMethod, int status, String message) {
        if (Objects.nonNull(handlerMethod)) {
            // 获取控制器方法
            Method method = handlerMethod.getMethod();
            if (method.isAnnotationPresent(ApiResponsePackIgnore.class)) {
                return message;
            }
        }
        return BaseResponse.newBuilder().withStatus(status).withMessage(message).build();
    }

    /**
     * 记录错误日志
     * ----------------------------------------------------------------------
     * 打印错误日志的场景:
     * 1.请求阶段标识为ServletStage.BEFORE_PARAMETER,即:部分参数校验异常;
     * 2.抛出的错误异常为HttpRequestMethodNotSupportedException,此异常不会进入{@link ParameterInterceptor},即:405 Method Not Allowed
     * ----------------------------------------------------------------------
     *
     * @param ex      异常对象
     * @param request 请求对象
     */
    public static void recordErrorMsg(Throwable ex, HttpServletRequest request) {
        //----------------------前置条件判断------------------------
        if (ServletStage.BEFORE_PARAMETER != LocalContextHolder.current().getServletStage()
                || !(ex instanceof HttpRequestMethodNotSupportedException)) {
            return;
        }
        BaseLogger baseLogger = BaseLogger.newBuilder()
                //系统编号
                .withSystemNumber(LocalContextHolder.current().getSystemNumber())
                //事务唯一编号
                .withTraceId(LocalContextHolder.current().getTraceId())
                //请求URL
                .withUrl(request.getRequestURI())
                //客户端IP
                .withClientIp(RequestUtils.getClientIp())
                //服务端IP
                .withServerIp(RequestUtils.getServerIp())
                //版本类型
                .withAppType(LocalContextHolder.current().getAppType())
                //版本号
                .withAppVersion(LocalContextHolder.current().getAppVersion())
                //触发时间
                .withTriggerTime(DateConvertUtils.format(LocalDateTime.now(), DatePatternInfo.YYYY_MM_DD_HH_MM_SS_SSS))
                //请求参数
                .withRequestParams(getRequestParams(ex, request))
                //响应体
                .withBody(PrintExceptionUtils.printErrorInfo(ex))
                //耗时(未处理任何逻辑)
                .withSpentTime(DateComputeUtils.minusMillis(Instant.now(), LocalContextHolder.current().getStartTime()))
                .build();
        //API耗时
        LocalContextHolder.current().setSpentTime(baseLogger.getSpentTime());
        //记录日志到文件
        PrintLoggerUtils.printRequest(baseLogger);
        //--------------------------后通知特殊条件判断-------------------------
        if (ex instanceof HttpRequestMethodNotSupportedException) {
            LocalContextHolder.unbind(true);
        }
    }

    /**
     * 获取请求参数
     *
     * @param ex      异常对象
     * @param request servlet对象
     * @return 请求参数
     */
    private static Map getRequestParams(Throwable ex, HttpServletRequest request) {
        Map paramsMap = Collections.emptyMap();
        //请求参数
        if (ex instanceof BindException) {
            BindingResult bindingResult = ((BindException) ex).getBindingResult();
            if (Objects.nonNull(bindingResult.getTarget())) {
                paramsMap = Maps.newLinkedHashMap();
                paramsMap.put(AttributeInfo.HEADERS, RequestUtils.getHeaders(request));
                paramsMap.put(AttributeInfo.PARAMS, SensitiveUtils.acquireElseGet(bindingResult.getTarget()));
            }
        }
        if (CollectionUtils.isEmpty(paramsMap)) {
            paramsMap = ServletHelper.getApiArgs(request);
        }
        return paramsMap;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy