zoukankan      html  css  js  c++  java
  • 【原】基于Feign 重写自定义编码器

    背景:

        有个spring cloud 项目需要调用php小组的接口,但是php提供的接口入参大部分是下划线命名,而Java这边是会按照驼峰编写,如果使用Fegin调用会导致php无法接收参数,例如userId传过去后,由于php那边是user_id,这样肯定无法接收,所以针对这个问题进行了如下处理,主要是通过重写fegin的默认编码器实现

    原理

    Spring Cloud Feign 的编码器、解码器和客户端都是支持自定义扩展,可以对请求以及结果和发起请求的过程进行自定义实现,Feign 默认encoder实现是SpringEncoder,默认decocer实现是ResponseEntityDecoder,另外还有一些其它的编解码器。

    Encoder/ Decoder 实现说明
    JacksonEncoder,JacksonDecoder 基于 Jackson 格式的持久化转换协议
    GsonEncoder,GsonDecoder 基于Google GSON 格式的持久化转换协议
    SaxEncoder,SaxDecoder 基于XML 格式的Sax 库持久化转换协议
    JAXBEncoder,JAXBDecoder 基于XML 格式的JAXB 库持久化转换协议
    ResponseEntityEncoder,ResponseEntityDecoder Spring MVC 基于 ResponseEntity< T > 返回格式的转换协议
    SpringEncoder,SpringDecoder 基于Spring MVC HttpMessageConverters 一套机制实现的转换协议 ,应用于Spring Cloud 体系中

    实现方案

    • 重写SpringEncoder

    **
     * 由于下游接口php是下划线命名,java是驼峰,通过fegin调用会导致下游php接收不到,所以需要针对这种问题特殊处理
     */
    public class FeignClientEncoder extends SpringEncoder {
    
        public static final char UNDERLINE = '_';
    
        public FeignClientEncoder(ObjectFactory<HttpMessageConverters> messageConverters) {
            super(messageConverters);
        }
    
        @Override
        public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException {
            try {
                super.encode(object, bodyType, template);
                if(ObjectUtils.isNotEmpty(AnnotationUtils.getAnnotation(object.getClass(), FeginCamelCase.class))){
                    final String s = JSON.toJSONString(object);
                    final Object jsonObject = JSON.parse(s);
                    Class clazz = Class.forName(bodyType.getTypeName());
                    convertToCamelCase(jsonObject,clazz);
                    template.body(JSON.toJSONString(jsonObject));
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    
        public final static void convertToCamelCase(Object json,Class clazz) throws NoSuchFieldException {
            if (json instanceof JSONArray) {
                JSONArray arr = (JSONArray) json;
                for (Object obj : arr) {
                    convertToCamelCase(obj,clazz);
                }
            } else if (json instanceof JSONObject) {
                JSONObject jo = (JSONObject) json;
                Set<String> keys = jo.keySet();
                String[] array = keys.toArray(new String[keys.size()]);
                for (String key : array) {
                    Field field = clazz.getField(key);
              //由于有些字段因为特殊原因,不想处理成下划线形式,这时候就可以通过注解的方式进行标记不进行处理
                    if(ObjectUtils.isEmpty(AnnotationUtils.getAnnotation(field,IgnoreFeginCamelCase.class))){
                        Object value = jo.get(key);
                        final String underLineKey = camelToUnderline(key,1);
                        jo.remove(key);
                        jo.put(underLineKey, value);
                        convertToCamelCase(value,clazz);
                    }
                }
            }
        }
    
        //驼峰转下划线
        public static String camelToUnderline(String param, Integer charType) {
            if (param == null || "".equals(param.trim())) {
                return "";
            }
            int len = param.length();
            StringBuilder sb = new StringBuilder(len);
            for (int i = 0; i < len; i++) {
                char c = param.charAt(i);
                if (Character.isUpperCase(c)) {
                    sb.append(UNDERLINE);
                }
                if (charType == 2) {
                    sb.append(Character.toUpperCase(c));  //统一都转大写
                } else {
                    sb.append(Character.toLowerCase(c));  //统一都转小写
                }
            }
            return sb.toString();
        }
    • 启动类指定编码器

    @EnableFeignClients(defaultConfiguration = FeignClientEncoder.class)
    

    最后

      指定编码器后,所有的Fegin请求都会走这个编码器,这样会导致原有的业务受到影响,为了不影响原有的业务,需要通过标识来区分到底什么字段能转下划线,所以在上面的代码里,我写了一个IgnoreFeginCamelCase注解,用于判断被IgnoreFeginCamelCase修饰后才进行下划线转换。

  • 相关阅读:
    nyoj112-指数运算
    nyoj51-管闲事的小明
    nyoj29-求置转换问题
    nyoj24-素数 距离问题
    nyoj22-素数求和问题
    nyoj23-取石子(一)
    nyoj4-ASCII码排序
    nyoj169-素数
    并查集:CDOJ1593-老司机破阵 (假的并查集拆除)
    线段树: CDOJ1598-加帕里公园的friends(区间合并,单点更新)
  • 原文地址:https://www.cnblogs.com/zdd-java/p/15524804.html
Copyright © 2011-2022 走看看