天天看點

又被逼着優化代碼,這次我幹掉了出入參 Log日志

本文收錄在個人部落格: www.chengxy-nds.top ,技術資源共享。

最近技術部突然刮起一陣

review

代碼的小風,挨個項目組過代碼,按理說這應該是件挺好的事,讓别人指出自己代碼中的不足,查缺補漏,對提升自身編碼能力有很大幫助,畢竟自己審查很容易“

陶醉

”在自己寫的代碼裡。

又被逼着優化代碼,這次我幹掉了出入參 Log日志

不過,代碼

review

的詳細程度令人發指,一行一行的分析,簡直就是個教育訓練班啊。不誇張的說,如果我村裡僅有縣重點國小學曆的四大爺,來聽上一個月後,保證能上手開發,666~

既然組内氣氛到這了,咱也得行動起來,要不哪天評審到我的代碼,讓人家指指點點的心裡多少有點不舒服,與其被動優化代碼不如主動出擊~

選優化代碼的方向,方法入參和傳回結果日志首當其沖,每個方法都會有這兩個日志,一大堆備援的代碼,而且什麼樣的列印格式都有,非常的雜亂。

public OrderDTO getOrder(OrderVO orderVO, String name) {

        log.info("訂單詳情入參:orderVO={},name={}", JSON.toJSONString(orderVO), name);

        OrderDTO orderInfo = orderService.getOrderInfo(orderVO);

        log.info("訂單詳情結果:orderInfo={}", JSON.toJSONString(orderInfo));

        return orderInfo;
}           

下邊我們利用

AOP

實作請求方法的入參、傳回結果日志統一列印,避免日志列印格式雜亂,同時減少業務代碼量。

一、自定義注解

自定義切面注解

@PrintlnLog

用來輸出日志,注解權限

@Target({ElementType.METHOD})

限制隻在方法上使用,注解中隻有一個參數

description

,用來自定義方法輸出日志的描述。

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface PrintlnLog {

    /**
     * 自定義日志描述資訊文案
     *
     * @return
     */
    String description() default "";
}           

二、切面類

接下來編寫

@PrintlnLog

注解對應的切面實作,

doBefore()

中輸出方法的自定義描述、入參、請求方式、請求url、被調用方法的位置等資訊,

doAround()

中列印方法傳回結果。

注意:

如何想指定切面在哪個環境執行,可以用

@Profile

注解,隻列印某個環境的日志。

@Slf4j
@Aspect
@Component
//@Profile({"dev"}) //隻對某個環境列印日志
public class LogAspect {

    private static final String LINE_SEPARATOR = System.lineSeparator();

    /**
     * 以自定義 @PrintlnLog 注解作為切面入口
     */
    @Pointcut("@annotation(com.chengxy.unifiedlog.config.PrintlnLog)")
    public void PrintlnLog() {
    }

    /**
     * @param joinPoint
     * @author fu
     * @description 切面方法入參日志列印
     * @date 2020/7/15 10:30
     */
    @Before("PrintlnLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        String methodDetailDescription = this.getAspectMethodLogDescJP(joinPoint);

        log.info("------------------------------- start --------------------------");
        /**
         * 列印自定義方法描述
         */
        log.info("Method detail Description: {}", methodDetailDescription);
        /**
         * 列印請求入參
         */
        log.info("Request Args: {}", JSON.toJSONString(joinPoint.getArgs()));
        /**
         * 列印請求方式
         */
        log.info("Request method: {}", request.getMethod());
        /**
         * 列印請求 url
         */
        log.info("Request URL: {}", request.getRequestURL().toString());

        /**
         * 列印調用方法全路徑以及執行方法
         */
        log.info("Request Class and Method: {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
    }

    /**
     * @param proceedingJoinPoint
     * @author xiaofu
     * @description 切面方法傳回結果日志列印
     * @date 2020/7/15 10:32
     */
    @Around("PrintlnLog()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

        String aspectMethodLogDescPJ = getAspectMethodLogDescPJ(proceedingJoinPoint);

        long startTime = System.currentTimeMillis();

        Object result = proceedingJoinPoint.proceed();
        /**
         * 輸出結果
         */
        log.info("{},Response result  : {}", aspectMethodLogDescPJ, JSON.toJSONString(result));

        /**
         * 方法執行耗時
         */
        log.info("Time Consuming: {} ms", System.currentTimeMillis() - startTime);

        return result;
    }

    /**
     * @author xiaofu
     * @description 切面方法執行後執行
     * @date 2020/7/15 10:31
     */
    @After("PrintlnLog()")
    public void doAfter(JoinPoint joinPoint) throws Throwable {
        log.info("------------------------------- End --------------------------" + LINE_SEPARATOR);
    }

    /**
     * @param joinPoint
     * @author xiaofu
     * @description @PrintlnLog 注解作用的切面方法詳細細資訊
     * @date 2020/7/15 10:34
     */
    public String getAspectMethodLogDescJP(JoinPoint joinPoint) throws Exception {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        return getAspectMethodLogDesc(targetName, methodName, arguments);
    }

    /**
     * @param proceedingJoinPoint
     * @author xiaofu
     * @description @PrintlnLog 注解作用的切面方法詳細細資訊
     * @date 2020/7/15 10:34
     */
    public String getAspectMethodLogDescPJ(ProceedingJoinPoint proceedingJoinPoint) throws Exception {
        String targetName = proceedingJoinPoint.getTarget().getClass().getName();
        String methodName = proceedingJoinPoint.getSignature().getName();
        Object[] arguments = proceedingJoinPoint.getArgs();
        return getAspectMethodLogDesc(targetName, methodName, arguments);
    }

    /**
     * @param targetName
     * @param methodName
     * @param arguments
     * @author xiaofu
     * @description 自定義注解參數
     * @date 2020/7/15 11:51
     */
    public String getAspectMethodLogDesc(String targetName, String methodName, Object[] arguments) throws Exception {
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        StringBuilder description = new StringBuilder("");
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
                    description.append(method.getAnnotation(PrintlnLog.class).description());
                    break;
                }
            }
        }
        return description.toString();
    }
}           

三、應用

我們在需要列印入參和傳回結果日志的方法,加上

@PrintlnLog

注解,并添加自定義方法描述。

@RestController
@RequestMapping
public class OrderController {

    @Autowired
    private OrderService orderService;

    @PrintlnLog(description = "訂單詳情Controller")
    @RequestMapping("/order")
    public OrderDTO getOrder(OrderVO orderVO, String name) {

        OrderDTO orderInfo = orderService.getOrderInfo(orderVO);

        return orderInfo;
    }
}           

代碼裡去掉

log.info

日志列印,加上

@PrintlnLog

看一下效果,清晰明了。

又被逼着優化代碼,這次我幹掉了出入參 Log日志

Demo

GitHub

位址:

https://github.com/chengxy-nds/Springboot-Notebook/tree/master/springboot-aop-unifiedlog

原創不易,燃燒秀發輸出内容,如果有一丢丢收獲,點個贊鼓勵一下吧!

整理了幾百本各類技術電子書,送給小夥伴們。關注公号回複【666】自行領取。和一些小夥伴們建了一個技術交流群,一起探讨技術、分享技術資料,旨在共同學習進步,如果感興趣就加入我們吧!

繼續閱讀