aspect实现mock-feign接口

简介: 该代码为一个用于Feign接口的模拟(Mock)实现类`FeignMockAspect`,通过切面编程方式对带有`@FeignClient`注解的接口提供模拟响应。在非生产环境中,根据特定配置从Redis中获取Mock数据并转换为对应类型的对象返回,以减少对外部系统的依赖和提高测试效率。使用Hutool工具类和Spring Data Redis进行数据处理与存储操作。

package com.ph.sp.integration.advice;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

/**

  • feign接口mock
    */
    @Component
    @Aspect
    @Order(-1)
    @Slf4j
    public class FeignMockAspect {

    @Pointcut("@within(org.springframework.cloud.openfeign.FeignClient)")
    public void typeCut() {
    }

    @Around("typeCut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {

     if (isPrd) {
         return pjp.proceed();
     }
     Pair<Boolean, String> mockConfig = getMockConfig(pjp);
     Boolean haveConfig = mockConfig.getKey();
     String mockResp = mockConfig.getValue();
     if (!haveConfig || mockResp == null) {
         return pjp.proceed();
     }
     return transMockResp2Obj(pjp, mockResp);
    

    }

    private Object transMockResp2Obj(ProceedingJoinPoint pjp, String mockResp) {

     Method method = ((MethodSignature) pjp.getSignature()).getMethod();
     try {
         Type returnType = method.getGenericReturnType();
         return JsonUtil.json2obj(mockResp, returnType);
     } catch (Exception e) {
         log.warn("trans GenericReturnType error~", e);
         Type returnType = method.getReturnType();
         return JsonUtil.json2obj(mockResp, returnType);
     }
    

    }

    private Pair getMockConfig(ProceedingJoinPoint pjp) {

     String body = JsonUtil.writeValueToString(pjp.getArgs());
     String uri = getUri(pjp);
     HashOperations<String, String, String> operation = hashTemplate.opsForHash();
     Map<String, String> mockConfig = operation.entries("A_MOCK_" + uri);
     if (CollUtil.isEmpty(mockConfig)) {
         return new Pair<>(false, null);
     }
     return new Pair<>(true, getMockResp(body, mockConfig));
    

    }

    private String getMockResp(String body, Map mockConfig) {

     Set<Map.Entry<String, String>> entries = mockConfig.entrySet();
     for (Map.Entry<String, String> entry : entries) {
         if (StrUtil.contains(body, entry.getKey())) {
             log.info("命中入参,返回mock数据 reqPattern:{}", entry.getKey());
             return Base64Utils.decode(entry.getValue());
         }
     }
     log.info("未命中入参,请求真实数据");
     return null;
    

    }

    private static String getUri(ProceedingJoinPoint pjp) {

     Method method = ((MethodSignature) pjp.getSignature()).getMethod();
     return Optional.ofNullable(method.getAnnotation(PostMapping.class)).map(PostMapping::value).map(e -> e[0])
             .orElseGet(() -> Optional.ofNullable(method.getAnnotation(GetMapping.class))
                     .map(GetMapping::value).map(e -> e[0]).orElse(""));
    

    }

    @Resource
    private RedisTemplate> hashTemplate;
    }

相关文章
|
设计模式 监控 前端开发
SpringBoot拦截器和动态代理有什么区别?
SpringBoot拦截器和动态代理有什么区别?
80 0
|
4月前
|
缓存 Java Sentinel
Springboot 中使用 Redisson+AOP+自定义注解 实现访问限流与黑名单拦截
Springboot 中使用 Redisson+AOP+自定义注解 实现访问限流与黑名单拦截
|
Dubbo Java 数据库连接
利用FactoryBean接口实例化,来实现dubbo接口调用和mybatis接口调用
Java编程规范中声明,Java接口类是不能直接实例化的,但是我们在平时的开发中经常会遇到只声明接口就可以直接使用的。 eg: 1. Mybatis中只用使用`@MapperScan`声明要扫描的Mapper接口类就可以直接从Spring中获取使用,进行操作数据库 2. Dubbo中只要用Dubbo提供的`@Service`注解,同样可以直接从Spring中获取使用进行远程调用。
383 0
|
12月前
|
Java
springboot实现自定义注解限流
springboot实现自定义注解限流
130 1
|
2月前
引入切面注解@Aspect依赖
引入切面注解@Aspect依赖
|
4月前
|
Java
Springboot 使用自定义注解结合AOP方式校验接口参数
Springboot 使用自定义注解结合AOP方式校验接口参数
Springboot 使用自定义注解结合AOP方式校验接口参数
|
4月前
|
数据中心
Feign调用
Feign调用
28 0
|
11月前
|
Java API Spring
Advice在Spring AOP中对应API
Advice在Spring AOP中对应API
26 0
springBoot feign请求日志切面
springBoot feign请求日志切面
|
Java Spring
Spring 如何通过反射获取controller 包下所有的类,以及类上的注解
Spring 如何通过反射获取controller 包下所有的类,以及类上的注解
288 0