使用Feign调用注解组件(实现字段赋值功能)

作者:qq_42152947 时间:2023-01-06 15:19:59 

使用注解的形式,装配在id字段,自动调用fegin赋值给目标字段。

使用效果

1.先给vo类中字段添加注解 

使用Feign调用注解组件(实现字段赋值功能)

2.调用feignDataSetUtils.setData 方法  将vo类放入 比如我的

feignDataSetUtils.setData(Stream.of(vo).collect(Collectors.toList()));

调用前

使用Feign调用注解组件(实现字段赋值功能)

 调用后 产生赋值。

使用Feign调用注解组件(实现字段赋值功能)

利用类字段注解的形式配置好对应的fegin关系,达到自动调用fegin的效果。

优点

1.省略大部分代码,只需配置注解,和编写fegin所需方法。

2.无其他重依赖,适应性强。

3.随意装配,不需要vo类或者fegin类继承任何接口。

如何装配

加入所有工具类后,只需两步。

先加入 以下类

ApplicationContextProvider:


import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
* @Version 1.0
* @Author:yanch
* @Date:2021-9-28
* @Content:
*/

@Component
public class ApplicationContextProvider implements ApplicationContextAware {
   private static ApplicationContext applicationContextSpring;

@Override
   public synchronized void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
       applicationContextSpring = applicationContext;
   }

/**
    * 通过class 获取Bean
    */
   public static <T> T getBean(Class<T> clazz) {
       return applicationContextSpring.getBean(clazz);
   }
}

FeignColum:


import java.lang.annotation.*;

/**
* @Version 1.0
* @Author:yanch
* @Date:2021-9-27
* @Content:
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FeignColum {
   /**
    * 目标字段 当前vo类的想要赋值的字段名称
    *
    */
   String targetFieldName();

/**
    *  当前字段如果是string类型且是用“,”分割的话就可以使用这个属性 可以设置为“,”,该字段将会被“,”分割
    *
    */
   String split() default "";

/**
    *  使用的feignType枚举类型
    *
    */
   FeignType feignType();
}

FeignDataSetUtils:


import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
* @Version 1.0
* @Author:yanch
* @Date:2021-9-28
* @Content:
*/
@Component
public class FeignDataSetUtils {

//    @Value("${appId}")
   private String appId;  

/**
    * 补充User数据
    *
    * @param voList
    * @return
    */
   public List setData(List voList) {
       if (CollectionUtils.isEmpty(voList)) {
           return voList;
       }
       Object object = voList.get(0);
       Class objectClass = object.getClass();
       // 获得feign的class为key Field集合为value的map
       Map<FeignType, List<Field>> feignFieldsMap = getFieldsAnnotationMap(objectClass);
       // 获得数据dataMap 后面用来发送给feign
       Map<FeignType, List<Object>> idDataMap = buildDataMap(feignFieldsMap.keySet());
       // 遍历所有注解
       // 遍历所有携带注解的字段-获得id集合
       putIdDataMap(feignFieldsMap, voList, idDataMap);

// Feign返回结果集合
       Map<FeignType, Map<Object, Object>> feignResultMap = getFeignResultMap(idDataMap);
       // 遍历所有
       // 遍历所有携带注解的字段-添加集合
       putDataMap(feignFieldsMap, objectClass, voList, feignResultMap);
       return voList;
   }

/**
    * 添加Feign的Result数据
    * @return
    */
   private Map<FeignType, Map<Object, Object>> getFeignResultMap(Map<FeignType, List<Object>> idDataMap) {
       // 初始化Feign返回结果集合
       Map<FeignType, Map<Object, Object>> feignResultMap = new HashMap();

Map<FeignType, IFeignFunction> feignFunctionMap = FeignFunctionMap.getFeignFunctionMap();
       idDataMap.keySet().forEach(feignType -> {
           IFeignFunction feignFunction = feignFunctionMap.get(feignType);
           Optional.ofNullable(feignFunction).ifPresent(m -> {
               m.setAppId(appId);
               m.setFeign(ApplicationContextProvider.getBean(feignType.getFeignClass()));
               Optional.ofNullable(idDataMap.get(feignType)).ifPresent(idList ->
                               feignResultMap.put(feignType, m.getBatch(idList))
                       );
           });
       });

//        // 获得用户集合
//        Map<String, Object> userVoMap= Optional.ofNullable(idDataMap.get(FeignType.UserInfoFeign.getFeignClass())).map(m->userInfoFeign.getBatch(m,appId).stream().collect(Collectors.toMap(UserVo::getId, my->(Object)my))).orElse(null) ;
//        Optional.ofNullable(userVoMap).ifPresent(p->
//                        feignResultMap.put(FeignType.UserInfoFeign.getFeignClass(),p)
//                );

return feignResultMap;
   }

/**
    * 遍历所有携带注解的字段-获得id集合
    *
    * @return
    */
   private void putIdDataMap(Map<FeignType, List<Field>> feignFieldsMap, List voList, Map<FeignType, List<Object>> idDataMap) {
       //遍历所有数据
       voList.stream().forEach(entry -> {
           feignFieldsMap.keySet().stream().forEach(feignClass -> {
               feignFieldsMap.get(feignClass).stream().forEach(field -> {
                   FeignColum colum = field.getAnnotation(FeignColum.class);
                   field.setAccessible(true);
                   // 开始添加id数据
                   try {
                       if (StringUtils.isEmpty(colum.split())) {
                           Optional.ofNullable(field.get(entry)).filter(f -> !ObjectUtils.isEmpty(f)).ifPresent(
                                   fieldValue -> idDataMap.get(colum.feignType()).add(fieldValue));
                       } else {
                           Optional.ofNullable(field.get(entry)).map(m -> (String) m).filter(f -> StringUtils.isNotEmpty(f)).ifPresent(
                                   fieldValue -> idDataMap.get(colum.feignType()).addAll(Arrays.stream(fieldValue.split(colum.split())).collect(Collectors.toList())));
                       }
                   } catch (IllegalAccessException e) {
                       e.printStackTrace();
                   }
               });
           });
       });
       // 删除没有的数据
       idDataMap.values().removeIf(value -> CollectionUtils.isEmpty(value));
   }

/**
    * 遍历所有携带注解的字段-添加集合
    *
    * @return
    */
   private void putDataMap(Map<FeignType, List<Field>> feignFieldsMap, Class objectClass, List voList, Map<FeignType, Map<Object, Object>> resultMap) {
       if (CollectionUtils.isEmpty(feignFieldsMap) || CollectionUtils.isEmpty(resultMap)) {
           return;
       }
       voList.stream().forEach(entry -> {
           feignFieldsMap.keySet().stream().forEach(feignType -> {
               Map<Object, Object> voMap = resultMap.get(feignType);
               feignFieldsMap.get(feignType).stream().forEach(field -> {
                   try {
                       FeignColum colum = field.getAnnotation(FeignColum.class);
                       String targetFieldName = colum.targetFieldName();
                       // 目标字段
                       Field targetField = objectClass.getDeclaredField(targetFieldName);
                       targetField.setAccessible(true);
                       // 开始添加用户数据
                       if (StringUtils.isEmpty(colum.split())) {
                           Optional.ofNullable(field.get(entry)).filter(f -> !ObjectUtils.isEmpty(f)).ifPresent(
                                   fieldValue -> {
                                       Object object = voMap.get(fieldValue);
                                       try {
                                           targetField.set(entry, object);
                                       } catch (IllegalAccessException e) {
                                           e.printStackTrace();
                                       }
                                   });
                       } else {
                           Optional.ofNullable(field.get(entry)).map(m -> (String) m).filter(f -> StringUtils.isNotEmpty(f)).ifPresent(
                                   fieldValue -> {
                                       try {
                                           Object object = Arrays.stream(fieldValue.split(colum.split())).map(m -> {
                                               return voMap.get(m);
                                           }).collect(Collectors.toList());
                                           targetField.set(entry, object);
                                       } catch (Exception e) {
                                           e.printStackTrace();
                                       }
                                   });
                       }
                   } catch (NoSuchFieldException | IllegalAccessException e) {
                       e.printStackTrace();
                   }
               });
           });
       });
   }

/**
    * 获得需要的注解字段
    *
    * @param cls
    * @return
    */
   private Map<FeignType, List<Field>> getFieldsAnnotationMap(Class cls) {
       // 注解集合对象
       Map<FeignType, List<Field>> feignMap = buildAnnotationMap();
       // 字段遍历
       Arrays.stream(cls.getDeclaredFields()).forEach(field -> {
           feignMap.keySet().stream().forEach(feignClass -> {
               if (field.isAnnotationPresent(FeignColum.class)) {
                   FeignColum colum = field.getAnnotation(FeignColum.class);
                   if(colum.feignType()!=feignClass){
                       return;
                   }
                   feignMap.get(colum.feignType()).add(field);
               }
           });
       });
       // 删除没有的字段注解
       feignMap.values().removeIf(value -> CollectionUtils.isEmpty(value));
       return feignMap;
   }

/**
    * 初始化注解map
    *
    * @return
    */
   private Map<FeignType, List<Field>> buildAnnotationMap() {
       return Arrays.stream(FeignType.values()).collect(Collectors.toMap(my -> my, my -> new ArrayList()));
   }

/**
    * 初始化字段数据map
    *
    * @return
    */
   private Map<FeignType, List<Object>> buildDataMap(Collection<FeignType> collection) {
       return collection.stream().collect(Collectors.toMap(my -> my, my -> new ArrayList()));
   }
}

IFeignFunction:


import lombok.Data;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

/**
* @Version 1.0
* @Author:yanch
* @Date:2021-9-28
* @Content:
*/
@Data
public abstract class IFeignFunction<T,E> {
   Class<T> clazz;
   T feign;
   String appId;
   public IFeignFunction(){
       doGetClass();
   }
   public abstract Map<E, Object> getBatch(List<E> idList);

public void doGetClass() {
       Type genType = this.getClass().getGenericSuperclass();
       Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
       this.clazz = (Class<T>) params[0];
   }
}

剩下的两块代码需要自己加东西

  • FeignType:这个是用来给注解配置Feign的枚举选项,也就是你想要什么Feign就需要在FeignType中添加一次。

使用Feign调用注解组件(实现字段赋值功能)

例如我的:


/**
* @Version 1.0
* @Author:yanch
* @Date:2021-9-27
* @Content:
*/
public enum FeignType {
   /**
    *手工配置1   UserInfoFeign 是选项名称 用来给注解配置使用
    */
   UserInfoFeign(),
   /**
    *手工配置2   UserInfoFeign2 是选项名称 用来给注解配置使用
    */
   UserInfoFeign2();
}
  • FeignFunctionMap:它的作用是用来绑定FeignType和IFeignFunction(Feign的方法)的关系。

  • 具体可以查看代码理解。比如代码里面的put(FeignType.UserInfoFeign 。。。。和put(FeignType.UserInfoFeign2.。。。。


import com.xxx.xxx.sdk.feign.UserInfoFeign;
import com.xxx.xxx.sdk.vo.UserVo;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @Version 1.0
* @Author:yanch
* @Date:2021-9-28
* @Content:
*/
public class FeignFunctionMap {
   private static Map<FeignType, IFeignFunction> feignFunctionMap = new HashMap();
   static {
       /**
        * 用来绑定FeignType.UserInfoFeign 和Feign方法的关系(IFeignFunction)
        *手工配置1
        * IFeignFunction的第一个泛型是Feign的类,第二个是字段参数类型。 比如我用的是String 存储的id,这里就用String
        */
       // 用户Feign
       put(FeignType.UserInfoFeign,new IFeignFunction<UserInfoFeign,String>() {
           @Override
           public  Map<String, Object> getBatch(List<String> idList) {
               // feign对象相当于UserInfoFeign的实例化对象,appid你们可以不用管,这个是我的feign必须要携带的一个常量。
               // 为什么要返回一个Map<String, Object> ?  因为这将要用来做成字典,key是id,value是这个feign根据这个id调用来的值
               return feign.getBatch(idList, appId).stream().collect(Collectors.toMap(UserVo::getId, my -> (Object) my));
           }
       });
       /**
        * 用来绑定FeignType.UserInfoFeign2 和Feign方法的关系(IFeignFunction)
        *手工配置2
        * IFeignFunction的第一个泛型是Feign的类,第二个是字段参数类型。 比如我用的是Long 存储的id,这里就用Long
        */
       put(FeignType.UserInfoFeign2,new IFeignFunction<UserInfoFeign,Long>() {
           @Override
           public  Map<Long, Object> getBatch(List<Long> idList) {
               return feign.getBatch(idList.stream().map(m->String.valueOf(m)).collect(Collectors.toList()), appId).stream().collect(Collectors.toMap( my ->Long.valueOf(my.getId()), my -> (Object) my));
           }

});  
   }  

/**
    *--------------------------以下无需配置
    */
   /**
    *@param feignType FeignType名称
    *@param iFeignFunction feign方法实现方式
    */
   public  static void put(FeignType feignType,IFeignFunction iFeignFunction){
       feignFunctionMap.put(feignType,iFeignFunction);
   }

public static Map<FeignType, IFeignFunction> getFeignFunctionMap() {
       return feignFunctionMap;
   }  
}

如果把自己的FeignType和FeignFunctionMap配置完成后就可以在自己的类中加入注解了。

比如下面是我的vo类。

使用Feign调用注解组件(实现字段赋值功能)

之后放入feignDataSetUtils.setData(Stream.of(vo).collect(Collectors.toList()))当中就能够赋值了。

使用Feign调用注解组件(实现字段赋值功能)

上面的代码没有必要放出来所以我就已图片的形式展示出来了。

FeignColum注解类的三个属性用意:

  • targetFieldName:用来记录目标赋值的字段名称     

  • split:用来切割字符串的分割符号,比如我的 字段是allUserId的值是 "1;2"  那我就需要配置        split = ";",且目标字段也必须是List接收。

  • feignType:用来绑定使用的feginType的枚举类型。

特殊需求

1.假如我的feign的方法每次请求除了携带id还需要携带一个常量参数访问该怎么办?

这个可以是用全局搜索参看 appId的使用方式。

使用Feign调用注解组件(实现字段赋值功能)

来源:https://blog.csdn.net/qq_42152947/article/details/120601199

标签:Feign,注解,组件,字段赋值
0
投稿

猜你喜欢

  • C#实现复杂XML的序列化与反序列化

    2023-12-19 05:09:45
  • C#多线程中的异常处理操作示例

    2023-07-16 06:10:10
  • java:无法访问org.springframework.boot.SpringApplication的解决方法

    2022-07-14 05:24:29
  • Java实现微信公众号发送模版消息

    2021-07-16 17:03:35
  • Java使用DFA算法实现敏感词过滤的示例代码

    2022-10-21 00:56:13
  • 安卓(Android)开发之自定义饼状图

    2022-04-06 11:13:11
  • Java 访问剪切板(复制,粘贴)的示例

    2023-11-10 12:26:13
  • Java集合TreeSet用法详解

    2023-11-10 22:53:34
  • ES结合java代码聚合查询详细示例

    2022-08-31 01:23:29
  • C#难点逐个击破(3):params数组参数

    2022-01-17 14:40:22
  • SpringSecurity rememberme功能实现过程解析

    2021-12-20 05:22:08
  • android获取手机唯一标识的方法

    2022-09-16 15:55:39
  • Android中GPS定位的用法实例

    2021-07-26 23:26:29
  • C# Dynamic关键字之:dynamic为什么比反射快的详解

    2021-06-24 04:22:35
  • logback中显示mybatis查询日志文件并写入的方法示例

    2023-11-03 03:01:48
  • 浅谈关于Mybatis的mapper-locations配置问题

    2023-09-24 06:06:16
  • 解决@RequestBody使用不能class类型匹配的问题

    2023-04-20 19:28:10
  • C#实现软件监控外部程序运行状态的方法

    2023-12-04 20:46:15
  • C#中sleep和wait的区别分析

    2021-09-11 08:31:25
  • java导出Excel通用方法的实例详解

    2022-06-25 14:28:25
  • asp之家 软件编程 m.aspxhome.com