TypechoJoeTheme

Toasobi的博客

AOP---增强日志记录功能

本文最后更新于2023年08月29日,已超过386天没有更新。如果文章内容或图片资源失效,请留言反馈,我会及时处理,谢谢!

AOP---增强日志记录功能

  1. 先定义两个注解LogAnnotation和LogAroundAnnotation

    @Target({ElementType.METHOD}) //只能运用于方法上
    @Retention(RetentionPolicy.RUNTIME) //指定该注解在运行时仍然可用,可以通过反射获取注解信息
    @Documented //该注解应包含在生成的Java文档
    public @interface LogAnnotation {
    
      /**
       * @description 增强方式
       * @author kongxiangneng
       * @time 2023/8/9 16:00
       */
      String adviceAction() default "before";
    
      /**
       * @description 操作请求
       * @author kongxiangneng
       * @time 2023/8/15 14:20
       */
      String info();
    
    }
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface LogAroundAnnotation {
    
     /**
      * @description 操作请求
      * @author kongxiangneng
      * @time 2023/8/15 14:20
      */
     String info();
    }
  2. 规范化objectMapper的mapper对象格式(objectMapper创建的objectNode可以用于被增强方法的数据存放),所有序列化的对象都按规则进行序列化和反序列化
public class LogObjectMapper {
    /**
     * 默认日期时间格式
     */
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    /**
     * 默认日期格式
     */
    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    /**
     * 默认时间格式
     */
    public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";

    private static final String REGEX_DATE_TIME = "^([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-((" +
            "(0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-" +
            "(0[1-9]|[1][0-9]|2[0-8])))\\s+([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$";

    private static final String REGEX_DATE = "^([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-((" +
            "(0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-" +
            "(0[1-9]|[1][0-9]|2[0-8])))$";

    private static final String REGEX_TIME = "^([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$";

    private static final String REGEX_TIME_STAMP_MILLI = "^\\d{13}$";

    private static final String REGEX_TIME_STAMP_SEC = "^\\d{11}$";

    private static ObjectMapper objectMapper;

    static {
        initObjectMapper();
    }

    public static ObjectMapper get() {
        return objectMapper;
    }

    private static ObjectMapper initObjectMapper() {
        objectMapper = new ObjectMapper();

        // 通过该方法对mapper对象进行设置,所有序列化的对象都将按改规则进行系列化
        // Include.Include.ALWAYS 默认
        // Include.NON_DEFAULT 属性为默认值不序列化
        // Include.NON_EMPTY 属性为 空("") 或者为 NULL 都不序列化,则返回的json是没有这个字段的
        // Include.NON_NULL 属性为NULL 不序列化
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);

        objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        // 字段保留,将null值转为""
//        objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
//            @Override
//            public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
//                    throws IOException {
//                jsonGenerator.writeString("");
//            }
//        });

        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);

        JavaTimeModule javaTimeModule = new JavaTimeModule();

        // Date序列化和反序列化
        javaTimeModule.addSerializer(Date.class, new JsonSerializer<Date>() {
            @Override
            public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
                    throws IOException {
                SimpleDateFormat formatter = new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT);
                String formattedDate = formatter.format(date);
                jsonGenerator.writeString(formattedDate);
            }
        });

        javaTimeModule.addDeserializer(Date.class, new JsonDeserializer<Date>() {
            @Override
            public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
                    throws IOException, JsonProcessingException {
                String date = jsonParser.getText();

                if (Pattern.matches(REGEX_DATE_TIME, date)) {
                    SimpleDateFormat format = new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT);
                    try {
                        return format.parse(date);
                    } catch (ParseException e) {
                        throw new RuntimeException(e);
                    }
                } else if (Pattern.matches(REGEX_DATE, date)) {
                    SimpleDateFormat format = new SimpleDateFormat(DEFAULT_DATE_FORMAT);
                    try {
                        return format.parse(date);
                    } catch (ParseException e) {
                        throw new RuntimeException(e);
                    }
                } else if (Pattern.matches(REGEX_TIME, date)) {
                    SimpleDateFormat format = new SimpleDateFormat(DEFAULT_TIME_FORMAT);
                    try {
                        return format.parse(date);
                    } catch (ParseException e) {
                        throw new RuntimeException(e);
                    }
                } else if (Pattern.matches(REGEX_TIME_STAMP_MILLI, date)) {
                    return new Date(Long.valueOf(date));
                } else if (Pattern.matches(REGEX_TIME_STAMP_SEC, date)) {
                    return new Date(Long.valueOf(date + "000"));
                } else if (StringUtils.isEmpty(date)) {
                    return null;
                } else {
                    throw new RuntimeException("时间序列化格式不支持: " + date);
                }
            }
        });

        /**
         * LocalDateTime序列化返回时间戳
         */
//        javaTimeModule.addSerializer(LocalDateTime.class, new JsonSerializer<LocalDateTime>() {
//            @Override
//            public void serialize(LocalDateTime arg0, JsonGenerator arg1, SerializerProvider arg2) throws IOException {
//                arg1.writeString(String.valueOf(arg0.toInstant(ZoneOffset.of("+8")).toEpochMilli()));
//            }
//        });

        javaTimeModule.addSerializer(LocalDateTime.class,
                new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));

        javaTimeModule.addSerializer(LocalDate.class,
                new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));

        javaTimeModule.addSerializer(LocalTime.class,
                new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));

        javaTimeModule.addDeserializer(LocalDateTime.class,
                new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));

        javaTimeModule.addDeserializer(LocalDate.class,
                new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));

        javaTimeModule.addDeserializer(LocalTime.class,
                new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));

        objectMapper.registerModule(javaTimeModule).registerModule(new ParameterNamesModule())
                .registerModule(new Jdk8Module());

        return objectMapper;
    }
}
  1. 测试案例的返回格式定义

    SpringBeanUtil
    package com.summit.util;
    
    import org.springframework.beans.BeansException;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.stereotype.Component;
    
    /**
     * @author kongxiangneng
     * @time 2023/8/15 11:30
     */
    @Component
    public class SpringBeanUtil implements ApplicationContextAware {
     private static ApplicationContext applicationContext;
    
     @Override
     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
         SpringBeanUtil.applicationContext = applicationContext;
     }
    
     public static <T> T getBean(Class<T> clazz) {
         return applicationContext.getBean(clazz);
     }
    }
JsonUtil
package com.summit.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.type.TypeFactory;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;


public class JsonUtil {
    public static ObjectMapper objectMapper = SpringBeanUtil.getBean(ObjectMapper.class);

    /**
     * json字符串转Json对象,如果字符串为null,返回空的Json对象
     *
     * @param json
     * @return
     */
    public static ObjectNode toJson(String json) {
        if (json == null) {
            return objectMapper.createObjectNode();
        }

        try {
            return objectMapper.readValue(json, ObjectNode.class);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T toObject(String json, Class<T> clazz) {
        if (json == null) {
            return null;
        }

        try {
            return objectMapper.readValue(json, clazz);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T toObject(String json, TypeReference<T> valueTypeRef) {
        if (json == null) {
            return null;
        }

        try {
            return objectMapper.readValue(json, valueTypeRef);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 对象转json字符串,如果对象为null,返回null
     *
     * @param o
     * @return
     */
    public static String toJsonString(Object o) {
        if (o == null) {
            return null;
        }

        try {
            return objectMapper.writeValueAsString(o);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T toObject(ObjectNode objectNode, Class<T> clazz) {
        if (objectNode == null || clazz == null) {
            return null;
        }

        try {
            return objectMapper.treeToValue(objectNode, clazz);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 对象转json对象,如果对象为null,返回空的json对象
     *
     * @param o
     * @return
     */
    public static ObjectNode toJson(Object o) {
        if (o == null) {
            return objectMapper.createObjectNode();
        }

        return objectMapper.valueToTree(o);
    }

    /**
     * json字符串转json数组对象,如果字符串为null,返回空的json数组对象
     *
     * @param json
     * @return
     */
    public static ArrayNode toJsonArray(String json) {
        if (json == null) {
            return objectMapper.createArrayNode();
        }

        try {
            return objectMapper.readValue(json, ArrayNode.class);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }


    public static <T> T toObject(String jsonStr, Type targetType) {
        try {
            JavaType javaType = TypeFactory.defaultInstance().constructType(targetType);
            return objectMapper.readValue(jsonStr, javaType);
        } catch (IOException e) {
            throw new IllegalArgumentException("将JSON转换为对象时发生错误:" + jsonStr, e);
        }
    }

    public static <T> List<T> toList(String text, Class<T> valueType) {
        try {
            JavaType javaType = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, valueType);
            return objectMapper.readValue(text, javaType);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
ResultCodeEnum
package com.summit.common;

import java.util.HashMap;
import java.util.Map;

public enum ResultCodeEnum {
    SUCCESS(0, "success");

    /**
     * 处理结果返回编码
     */
    private Integer code;

    /**
     * 处理结果描述
     */
    private String desc;

    ResultCodeEnum(Integer code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public static boolean isFail(Result result){
        return !result.getCode().equals(SUCCESS.getCode());
    }

    public static void main(String[] args) {
        Map map = new HashMap<>();
        for (ResultCodeEnum ret : ResultCodeEnum.values()) {
//            if(map.get(ret.code) != null){
//                System.out.println(ret);
//            }else{
//                map.put(ret,ret.getCode());
//            }

            // 输出js数组格式
//            map.put("[" +ret.getCode()+"]", ret);
            // 输出国际化语言数组
//            map.put(ret, ret.getDesc());

//            System.out.println(ret.code);
//            System.out.println(ret.getDesc());

//            System.out.println("[" + ret.getCode() + "]: " + "\'" + ret  + "\',");
//            System.out.println("\"" + ret + "\": " + "\"" + ret.getDesc() + "\",");

        }


    }
}
Result
package com.summit.common;

import com.summit.util.JsonUtil;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Collection;

@Data
@NoArgsConstructor
public class Result<T> {
    /**
     * 处理结果返回编码
     */
    private Integer code;

    /**
     * 处理结果描述
     */
    private String desc;

    /**
     * 处理结果
     */
    private T data;

    public Result(Integer code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    public Result(Integer code, String desc, T data) {
        this.code = code;
        this.desc = desc;
        this.data = data;
    }

    public Result(ResultCodeEnum resultCodeEnum) {
        this(resultCodeEnum.getCode(), resultCodeEnum.getDesc());
    }

    public Result(ResultCodeEnum resultCodeEnum, T data) {
        this(resultCodeEnum.getCode(), resultCodeEnum.getDesc(), data);
    }

    public static Result success() {
        return new Result(ResultCodeEnum.SUCCESS);
    }

    public static <T> Result success(T data) {
        return new Result(ResultCodeEnum.SUCCESS, data);
    }

    public static <T> Result success(Collection<T> collection) {
        return new Result(ResultCodeEnum.SUCCESS, collection);
    }

    public static Result error(ApiException exception) {
        return new Result(exception.getCode(), exception.getDesc());
    }

    public static Result error(ResultCodeEnum resultCodeEnum) {
        return new Result(resultCodeEnum);
    }

    public static Result error(Throwable cause){
        return Result.error((ApiException)cause);
    }

    public String toJsonString(){
        return JsonUtil.toJsonString(this);
    }
}
  1. 使用Spring AOP 和 AspectJ 两个方案实现AOP-对注解方法进行增强
Spring AOP实现 ---> ApiLogAspect
@Aspect
@Component
public class ApiLogAspect { //使用 Spring AOP 实现的日志切面(ApiLogAspect),用于记录 API 请求的相关信息
    private static final Logger log = LoggerFactory.getLogger(ApiLogAspect.class);

    private ObjectMapper objectMapper = LogObjectMapper.get();

    @Pointcut("@within(org.springframework.web.bind.annotation.RestController) " +
            "|| @within(org.springframework.stereotype.Controller)")  //切入点匹配标有 @RestController 或 @Controller 注解的类
//    @Pointcut("execution(* com.summit.util.JsonUtil.*(..))")
    public void controllerLog() {
    }


    @Around("controllerLog()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { //一个环绕通知,会在切入点方法执行前后进行拦截和处理

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = attributes.getRequest();

        long startTime = System.nanoTime(); //获取当前请求的 HttpServletRequest 对象和开始时间
        Object result;
        boolean isException = false;
        Throwable exception = null;
        //是否404
        boolean isNotFound = false;
        try {
            result = proceedingJoinPoint.proceed(); //执行切入点方法

            if (result instanceof ResponseEntity && ((ResponseEntity) result).getStatusCode().value() == HttpStatus.NOT_FOUND.value()) {
                isNotFound = true;
            }

        } catch (Throwable throwable) {
            isException = true;
            exception = throwable;
            throw throwable;
        } finally {
            ObjectNode node = objectMapper.createObjectNode();
            node.put("logType", "apiReqLog");
            node.put("url", request.getRequestURL().toString());
            node.put("method", request.getMethod());

            String xForwardedFor = request.getHeader("x-forwarded-for");
            if (xForwardedFor == null) {
                node.put("ip", request.getRemoteAddr());
            } else {
                node.put("ip", request.getHeader("x-forwarded-for"));
            }

            if (ServletFileUpload.isMultipartContent(request)) {
                Object[] args = proceedingJoinPoint.getArgs();

                if (!isNotFound) {
                    if (args.length == 0) {
                        node.set("reqParam", null);
                    } else {
                        for (Object item : args) {
                            if (item instanceof MultipartFile) {
                                continue;
                            }

                            if (item instanceof MultipartFile[]) {
                                continue;
                            }

                            node.set("reqParam", JsonUtil.toJson(item));
                        }
                    }
                }

            } else {
                Object[] args = proceedingJoinPoint.getArgs();

                if (!isNotFound) {
                    if (args.length == 0) {
                        node.set("reqParam", null);
                    } else {
                        try {
                            node.set("reqParam", JsonUtil.toJson(args[0]));
                        } catch (Exception e) {
                            //非json不处理
                        }
                    }
                }
            }

            if (isException) {
                if (exception instanceof ApiException) {
                    node.put("exception", exception.toString() + "|"
                            + ((ApiException) exception).getCode() + "|" + ((ApiException) exception).getDesc());
                } else {
                    node.put("exception", exception.toString() + "|" + exception.getMessage());

                    node.put("stack", ExceptionUtil.stacktraceToString(exception));
                }

                node.put("isSuccess", false);
            } else {
                node.put("isSuccess", true);
            }

            if (isNotFound) {
                node.put("isSuccess", false);
                node.put("exception", "Not Found");
            }

            node.put("execTime", (System.nanoTime() - startTime) / 1000000);

            log.info(node.toPrettyString());
        }
        return result;
    }
}
AspectJ ---> LogAspect
@Aspect
@Component
public class LogAspect { //使用 AspectJ 实现的 AOP 方式
    private static final Logger log = LoggerFactory.getLogger(LogAspect.class);

    private ObjectMapper objectMapper = LogObjectMapper.get();

    private static final String ACTION_BEFORE = "before";
    private static final String ACTION_AFTER = "after";
    private static final String ACTION_AROUND = "around";
    private static final String ACTION_AFTER_RETURNING = "afterReturning";
    private static final String ACTION_AFTER_THROWING = "afterThrowing";

    /**
     * @description 声明一个公用的切入点,满足此条件都会被植入增强-使用AspectAnnotation注解修饰的方法都将进入此方法
     * @author 
     * @time 2023/8/8 16:36
     */
    @Pointcut("@annotation(com.summit.annotation.LogAnnotation)")
    private void pointCut(){}

    /**
     * @description 环绕增强
     * @author 
     * @time 2023/8/9 17:35
     */
    @Pointcut("@annotation(com.summit.annotation.LogAroundAnnotation)")
    private void aroundPointCut(){}


    /**
     * @description 前置增强
     * @author 
     * @time 2023/8/8 16:33
     */
    @Before("pointCut() && @annotation(annotation)")
    public void before(JoinPoint joinPoint, LogAnnotation annotation){
        // 获取注解属性
        String action = annotation.adviceAction();
        if (action.equals(ACTION_BEFORE)){
            long startTime = System.nanoTime();
            ObjectNode node = initNode(joinPoint, annotation);
            // 操作时间
            node.put("execTime", (System.nanoTime() - startTime) / 1000000);

            log.info(node.toPrettyString());
        }
    }

    /**
     * @description 后置增强-无论是否异常
     * @author 
     * @time 2023/8/8 16:33
     */
    @After("pointCut() && @annotation(annotation)")
    public void after(JoinPoint joinPoint, LogAnnotation annotation){
        // 获取注解属性
        String action = annotation.adviceAction();
        if (action.equals(ACTION_AFTER)){
            long startTime = System.nanoTime();
            ObjectNode node = initNode(joinPoint, annotation);
            // 操作时间
            node.put("execTime", (System.nanoTime() - startTime) / 1000000);

            log.info(node.toPrettyString());
        }
    }

    /**
     * @description 环绕增强
     * @author 
     * @time 2023/8/8 16:33
     */
    @Around("aroundPointCut() && @annotation(logger)")
    public Object around(ProceedingJoinPoint joinPoint, LogAroundAnnotation logger) throws Throwable { //只有LogAroundAnnotation 会拦截
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = attributes.getRequest();
        Result result = Result.success();
        long startTime = System.nanoTime();
        ObjectNode before = objectMapper.createObjectNode();
        ObjectNode after = objectMapper.createObjectNode();
        try {
            // 请求URL
            before.put("url", request.getRequestURL().toString());
            // 请求方法
            before.put("method", request.getMethod());
            // 操作请求-注解
            before.put("info",logger.info());
            // 请求IP
            before.put("operatorIp",request.getRemoteAddr());
            // 类名
            before.put("className",joinPoint.getTarget().getClass().getName());
            // 类方法名
            before.put("methodName",joinPoint.getSignature().getName());
            // 前置增强
            log.info(before.toPrettyString());

            // 核心代码
            result = (Result)joinPoint.proceed();

        } catch (Throwable throwable) {
            after.put("exception",throwable.toString());
            after.put("exceptionMsg",throwable.getMessage());
            throw throwable;
        } finally {
            after.put("returnCode",result.getCode());
            after.put("returnMsg",result.getDesc());
            after.put("execTime", (System.nanoTime() - startTime) / 1000000);
            // 后置增强
            log.info(after.toPrettyString());
        }

        return result;
    }

    /**
     * @description 在目标正常执行返回前增强
     * @author 
     * @time 2023/8/8 16:33
     */
    @AfterReturning(value = "pointCut() && @annotation(annotation)",returning = "returning")
    public void afterReturning(JoinPoint joinPoint, LogAnnotation annotation, Result returning){
        // 获取注解属性
        String action = annotation.adviceAction();
        if (action.equals(ACTION_AFTER_RETURNING)){
            long startTime = System.nanoTime();
            ObjectNode node = initNode(joinPoint, annotation);
            // 操作时间
            node.put("execTime", (System.nanoTime() - startTime) / 1000000);
            if (!ObjectUtils.isEmpty(returning)){
                node.put("returnCode",returning.getCode());
                node.put("returnMsg",returning.getDesc());
            }
            log.info(node.toPrettyString());
        }
    }

    /**
     * @description 异常增强处理,在目标方法抛异常后植入增强
     * @author kongxiangneng
     * @time 2023/8/8 16:34
     */
    @AfterThrowing(value = "pointCut() && @annotation(annotation)",throwing = "exception")
    public void afterThrowing(JoinPoint joinPoint,LogAnnotation annotation,Exception exception){
        // 获取注解属性
        String action = annotation.adviceAction();
        if (action.equals(ACTION_AFTER_THROWING)){
            long startTime = System.nanoTime();
            ObjectNode node = initNode(joinPoint, annotation);
            // 操作时间
            node.put("execTime", (System.nanoTime() - startTime) / 1000000);
            if (!ObjectUtils.isEmpty(exception)){
                node.put("exception",exception.toString());
                node.put("exceptionMsg",exception.getMessage());
            }
            log.info(node.toPrettyString());
        }
    }


    private ObjectNode initNode(JoinPoint joinPoint,LogAnnotation logger){
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = attributes.getRequest();

        ObjectNode node = objectMapper.createObjectNode();
        // 请求URL
        node.put("url", request.getRequestURL().toString());
        // 请求方法
        node.put("method", request.getMethod());
        // 操作请求-注解
        node.put("info",logger.info());
        // 请求IP
        node.put("operatorIp",request.getRemoteAddr());
        // 类名
        node.put("className",joinPoint.getTarget().getClass().getName());
        // 类方法名
        node.put("methodName",joinPoint.getSignature().getName());

        return node;
    }

}
  1. 测试可行性

    @RestController
    @RequestMapping("/v1/aop/test")
    public class TestController {
    
     @LogAnnotation(adviceAction = "before",info = "前置增强")
     @GetMapping("before")
     public Result before(){
         System.out.println("before controller");
         return Result.success();
     }
    
     @LogAnnotation(adviceAction = "after",info = "后置增强")
     @GetMapping("after")
     public Result after(){
         System.out.println("after controller");
         return Result.success();
     }
    
     @LogAroundAnnotation(info = "环绕增强")
     @GetMapping("around")
     public Result around(){
         System.out.println("around controller");
         return Result.success();
     }
    
     @LogAnnotation(adviceAction = "afterReturning",info = "正常后置增强")
     @GetMapping("afterReturning")
     public Result afterReturning(){
         System.out.println("afterReturning controller");
         return Result.success();
     }
    
     @LogAnnotation(adviceAction = "afterThrowing",info = "异常后置增强")
     @GetMapping("afterThrowing")
     public Result afterThrowing(){
         int a = 1 / 0;
         System.out.println("afterThrowing controller");
         return Result.success();
     }
    
    }
朗读
赞(0)
评论 (0)