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中获取使用进行远程调用。
403 0
|
21天前
|
XML Java 数据格式
使用完全注解的方式进行AOP功能实现(@Aspect+@Configuration+@EnableAspectJAutoProxy+@ComponentScan)
本文介绍了如何使用Spring框架的注解方式实现AOP(面向切面编程)。当目标对象没有实现接口时,Spring会自动采用CGLIB库进行动态代理。文中详细解释了常用的AOP注解,如`@Aspect`、`@Pointcut`、`@Before`等,并提供了完整的示例代码,包括业务逻辑类`User`、配置类`SpringConfiguration`、切面类`LoggingAspect`以及测试类`TestAnnotationConfig`。通过这些示例,展示了如何在方法执行前后添加日志记录等切面逻辑。
54 2
使用完全注解的方式进行AOP功能实现(@Aspect+@Configuration+@EnableAspectJAutoProxy+@ComponentScan)
|
9天前
|
前端开发 Java 测试技术
深入剖析:Spring Boot Controller中请求处理方法的访问修饰符
【10月更文挑战第21天】 在Spring Boot应用中,Controller类中的请求处理方法通常用于处理HTTP请求。这些方法的访问修饰符(private或public)对方法的行为和可访问性有着重要影响。本文将深入探讨在Controller中使用private和public修饰符的区别,以及它们对Spring MVC框架的影响。
17 8
|
2月前
|
存储 缓存 NoSQL
webFilter实现mock接口
这段代码实现了一个名为 `MockFilter` 的类,继承自 `WebFilter` 接口,用于处理 HTTP 请求和响应。它通过从 Redis 缓存中获取配置信息来决定是否使用模拟数据或缓存数据来响应请求。如果开启了生产模式或关闭了模拟和缓存功能,则直接放行请求。否则,它会检查请求体并根据配置返回相应的模拟或缓存数据。同时,该过滤器支持对响应结果进行处理,并将结果存储回 Redis 中。
|
4月前
引入切面注解@Aspect依赖
引入切面注解@Aspect依赖
|
6月前
|
Java
Springboot 使用自定义注解结合AOP方式校验接口参数
Springboot 使用自定义注解结合AOP方式校验接口参数
Springboot 使用自定义注解结合AOP方式校验接口参数
|
6月前
|
数据中心
Feign调用
Feign调用
31 0
|
Java Spring
Spring 如何通过反射获取controller 包下所有的类,以及类上的注解
Spring 如何通过反射获取controller 包下所有的类,以及类上的注解
303 0
|
Java Spring 容器
Feign源码分析-接口如何发现并生成代理类
Feign源码分析-接口如何发现并生成代理类
188 0
Feign源码分析-接口如何发现并生成代理类
|
负载均衡 Nacos
一起用feign来调用接口(有源码)
nacos很好的兼容了feign,feign默认集成了Ribbon,所以Nacos下使用Feign就默认实现了负载均衡 一、测试结果
130 0
一起用feign来调用接口(有源码)