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

org.rx.util.SpringControllerInterceptor Maven / Gradle / Ivy

package org.rx.util;

import com.google.common.base.Stopwatch;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;
import org.rx.core.*;
import org.rx.core.StringBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

import static org.rx.core.Contract.toJsonString;
import static org.rx.core.SystemException.DefaultMessage;

@Slf4j
//@Aspect
//@Component
//@Order(0)
//@ControllerAdvice
public class SpringControllerInterceptor {
    public interface IRequireSignIn {
        boolean isSignIn(String methodName, Object[] args);
    }

    private static final NQuery skipMethods = NQuery.of("setServletRequest", "setServletResponse");
    protected String notSignInMsg = "Not sign in";

    public Object onAround(ProceedingJoinPoint joinPoint) throws Throwable {
        // 1 先过滤出有RequestMapping的方法
        final Signature signature = joinPoint.getSignature();
        if (!(signature instanceof MethodSignature) || skipMethods.any(p -> p.equals(signature.getName()))) {
            return joinPoint.proceed();
        }

        org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(signature.getDeclaringType());
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        StringBuilder logContent = new StringBuilder().appendLine();

        // 2.2 获取接口的类及方法名
        logContent.appendLine(String.format("Class:\t%s.%s", method.getDeclaringClass().getName(), method.getName()));

        // 2.3 拼装接口URL
        // 2.3.1 获取Class上的FeignURL
        String url = "";
        Function reqMappingFunc = p -> String.join(",", ArrayUtils.isNotEmpty(p.value()) ? p.value() : p.path());
        Class parentType = method.getDeclaringClass(), feignType = NQuery.of(parentType).firstOrDefault();
        if (feignType != null) {
            parentType = feignType;
        }
        RequestMapping baseMapping = (RequestMapping) parentType.getAnnotation(RequestMapping.class);
        if (baseMapping != null) {
            url += reqMappingFunc.apply(baseMapping);
        }

        Method feignMethod = parentType.getDeclaredMethod(method.getName(), method.getParameterTypes());
        // 2.3.2 获取Class RequestMapping URL
        RequestMapping methodReqMapping = feignMethod.getAnnotation(RequestMapping.class);
        if (methodReqMapping != null) {
            url += reqMappingFunc.apply(methodReqMapping);
        }

        logContent.appendLine(String.format("Url:\t%s", url));
        logContent.append(String.format("Request:\t%s", onToString(joinPoint.getArgs(), method)));
        Object returnValue = null;
        try {
            Stopwatch watcher = Stopwatch.createStarted();
            if (joinPoint.getTarget() instanceof IRequireSignIn) {
                if (!((IRequireSignIn) joinPoint.getTarget()).isSignIn(method.getName(), joinPoint.getArgs())) {
                    throw new InvalidOperationException(notSignInMsg);
                }
            }
            returnValue = joinPoint.proceed();
            long ms = watcher.elapsed(TimeUnit.MILLISECONDS);
            logContent.appendLine(String.format("\tElapsed = %sms", ms));
        } catch (Exception ex) {
            logContent.append(String.format("Error:\t%s", ex.getMessage()));
            returnValue = onException(ex, method);
        } finally {
            logContent.appendLine(String.format("Response:\t%s", toJsonString(returnValue)));
            log.info(logContent.toString());
        }
        return returnValue;
    }

    protected String onToString(Object[] args, Method method) {
        if (ArrayUtils.isEmpty(args)) {
            return "NULL";
        }
        return toJsonString(NQuery.of(args).select(p -> {
            if (p instanceof MultipartFile) {
                return "[FileStream]";
            }
            if (p instanceof String) {
                String s = (String) p;
                if (App.isBase64String(s)) {
                    return "[Base64String]";
                }
            }
            return p;
        }).asCollection());
    }

    protected Object onException(Exception e, Method method) throws Throwable {
        org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(method.getDeclaringClass());
        log.error("ControllerError", e);
        throw e;
    }

    //    @ResponseStatus(HttpStatus.OK)
//    @ExceptionHandler({Exception.class})
    public ResponseEntity handleException(Exception e, HttpServletRequest request) {
        String msg = DefaultMessage, debugMsg = null;
        Exception logEx = e;
        if (e instanceof ValidateException || handleInfoLogExceptions().distinct().any(p -> Reflects.isInstance(e, p))) {
            //参数校验错误 ignore log
            msg = e.getMessage();
            logEx = null;
        } else if (e instanceof SystemException) {
            msg = ((SystemException) e).getFriendlyMessage();
            debugMsg = e.getMessage();
        }
        if (logEx != null) {
            log.error("HttpError {}", request.getRequestURL().toString(), logEx);
        }

        return ResponseEntity.ok(handleExceptionResponse(msg, debugMsg));
    }

    protected NQuery handleInfoLogExceptions() {
        return NQuery.of();
    }

    protected Object handleExceptionResponse(String msg, String debugMsg) {
        return msg + "\n" + debugMsg;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy