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;
    }

相关文章
|
Dubbo Java 数据库连接
利用FactoryBean接口实例化,来实现dubbo接口调用和mybatis接口调用
Java编程规范中声明,Java接口类是不能直接实例化的,但是我们在平时的开发中经常会遇到只声明接口就可以直接使用的。 eg: 1. Mybatis中只用使用`@MapperScan`声明要扫描的Mapper接口类就可以直接从Spring中获取使用,进行操作数据库 2. Dubbo中只要用Dubbo提供的`@Service`注解,同样可以直接从Spring中获取使用进行远程调用。
405 0
|
1月前
|
XML Java 数据格式
使用完全注解的方式进行AOP功能实现(@Aspect+@Configuration+@EnableAspectJAutoProxy+@ComponentScan)
本文介绍了如何使用Spring框架的注解方式实现AOP(面向切面编程)。当目标对象没有实现接口时,Spring会自动采用CGLIB库进行动态代理。文中详细解释了常用的AOP注解,如`@Aspect`、`@Pointcut`、`@Before`等,并提供了完整的示例代码,包括业务逻辑类`User`、配置类`SpringConfiguration`、切面类`LoggingAspect`以及测试类`TestAnnotationConfig`。通过这些示例,展示了如何在方法执行前后添加日志记录等切面逻辑。
95 2
使用完全注解的方式进行AOP功能实现(@Aspect+@Configuration+@EnableAspectJAutoProxy+@ComponentScan)
|
4月前
引入切面注解@Aspect依赖
引入切面注解@Aspect依赖
|
4月前
|
分布式计算 Java MaxCompute
详解 Java 限流接口实现问题之在Spring框架中使用AOP来实现基于注解的限流问题如何解决
详解 Java 限流接口实现问题之在Spring框架中使用AOP来实现基于注解的限流问题如何解决
|
6月前
|
Java
Springboot 使用自定义注解结合AOP方式校验接口参数
Springboot 使用自定义注解结合AOP方式校验接口参数
Springboot 使用自定义注解结合AOP方式校验接口参数
|
Java API Spring
Advice在Spring AOP中对应API
Advice在Spring AOP中对应API
33 0
|
Java Spring
Spring 如何通过反射获取controller 包下所有的类,以及类上的注解
Spring 如何通过反射获取controller 包下所有的类,以及类上的注解
306 0
|
Java Spring
Spring-AOP @AspectJ进阶之绑定连接点方法入参
Spring-AOP @AspectJ进阶之绑定连接点方法入参
105 0
|
Java Spring 容器
Feign源码分析-接口如何发现并生成代理类
Feign源码分析-接口如何发现并生成代理类
190 0
Feign源码分析-接口如何发现并生成代理类
|
Java Spring
Spring - InitializingBean扩展接口
InitializingBean扩展接口
152 0
Spring - InitializingBean扩展接口