Я был вынужден снова оптимизировать код, на этот раз я избавился от лога

Java программист
Я был вынужден снова оптимизировать код, на этот раз я избавился от лога

Недавно технический отдел внезапно взорвался на некоторое времяreviewНебольшой ветерок в коде, проектная группа передала код один за другим, должно быть хорошо, чтобы другие указали на недостатки в их собственном коде, проверили недостатки и восполнили пробелы, это очень полезно для улучшения их кодирующую способность ведь легко проверить самому"陶醉"В моем собственном коде.在这里插入图片描述

Тем не менее, код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Реализуйте унифицированную печать входных параметров и возвращайте журналы результатов метода запроса, избегайте загроможденного формата печати журнала и сократите объем бизнес-кода.

1. Пользовательские аннотации

Пользовательская аннотация аспекта@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();
    }
}

3. Применение

Нам нужно распечатать входные параметры и вернуть метод журнала результатов, плюс@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Взгляните на эффект, он четкий и понятный.在这里插入图片描述 Demo GitHubАдрес: https://github.com/chengxy-nds/Springboot-Notebook/tree/master/springboot-aop-unifiedlog

Оригинальность не так проста, сжигание волос на выходе, если есть потеря, пожалуйста, дайте лайк, чтобы поощрить это!

Разобраны и розданы друзьям сотни различных технических электронных книг. Подпишитесь на официальный аккаунт, чтобы ответить [666], чтобы получить его самостоятельно. Мы создали группу технического обмена с друзьями, чтобы обсуждать технологии и делиться технической информацией, стремясь вместе учиться и развиваться. Если вам интересно, присоединяйтесь к нам!