Feign で一般的に使用されるリクエスト インターセプター

IFeignAutoConfiguration

@Configuration
@ConditionalOnClass({
    
    Feign.class})
@Order(Ordered.LOWEST_PRECEDENCE - 10000)
public class IFeignAutoConfiguration {
    
    

    private final ObjectMapper objectMapper;

    public IFeignAutoConfiguration(ObjectMapper objectMapper) {
    
    
        this.objectMapper = objectMapper;
    }

    /**
     * 用户信息传递,feign发起请求时,将当前用户信息放到请求头
     * @return RequestInterceptor
     */
    @Bean
    public RequestInterceptor headerUserFeignRequestInterceptor() {
    
    
        return new HeaderUserFeignRequestInterceptor();
    }

    /**
     * feign 不支持 GET 方法传 POJO, json body转query
     * 名为charlesRequestInterceptor的bean不存在时才装配
     * @return RequestInterceptor
     */
    @Bean
    @ConditionalOnMissingBean(name = "charlesRequestInterceptor")
    public RequestInterceptor charlesRequestInterceptor() {
    
    
        return new CharlesRequestInterceptor(objectMapper);
    }
}

CharlesRequestInterceptor


/**
 * feign 不支持 GET 方法传 POJO, json body转query
 */
public class CharlesRequestInterceptor implements RequestInterceptor {
    
    

    private static Logger log = LoggerFactory.getLogger(CharlesRequestInterceptor.class);

    private ObjectMapper objectMapper;

    public CharlesRequestInterceptor(ObjectMapper objectMapper) {
    
    
        this.objectMapper = objectMapper;
    }

    @Override
    public void apply(RequestTemplate template) {
    
    
        // feign 不支持 GET 方法传 POJO, json body转query
        if (template.method().equals("GET") && template.body() != null) {
    
    
            try {
    
    
                JsonNode jsonNode = objectMapper.readTree(template.body());
                template.body(null);

                Map<String, Collection<String>> queries = new HashMap<>();
                buildQuery(jsonNode, "", queries);
                template.queries(queries);
            } catch (IOException e) {
    
    
//                e.printStackTrace();
                log.error(e.getMessage());
            }
        }
    }

    private void buildQuery(JsonNode jsonNode, String path, Map<String, Collection<String>> queries) {
    
    
        if (!jsonNode.isContainerNode()) {
    
       // 叶子节点
            if (jsonNode.isNull()) {
    
    
                return;
            }
            Collection<String> values = queries.get(path);
            if (null == values) {
    
    
                values = new ArrayList<>();
                queries.put(path, values);
            }
            values.add(jsonNode.asText());
            return;
        }
        if (jsonNode.isArray()) {
    
       // 数组节点
            Iterator<JsonNode> it = jsonNode.elements();
            while (it.hasNext()) {
    
    
                buildQuery(it.next(), path, queries);
            }
        } else {
    
    
            Iterator<Map.Entry<String, JsonNode>> it = jsonNode.fields();
            while (it.hasNext()) {
    
    
                Map.Entry<String, JsonNode> entry = it.next();
                if (StringUtils.hasText(path)) {
    
    
                    buildQuery(entry.getValue(), path + "." + entry.getKey(), queries);
                } else {
    
      // 根节点
                    buildQuery(entry.getValue(), entry.getKey(), queries);
                }
            }
        }
    }
}

HeaderUserFeignRequestInterceptor

/**
 * 用户信息传递,feign发起请求时,将当前用户信息放到请求头
 **/
public class HeaderUserFeignRequestInterceptor implements RequestInterceptor {
    
    
    @Override
    public void apply(RequestTemplate requestTemplate) {
    
    

        String userInfo = ExtractUserInfoUtil.getUserInfoHeader();

        //feign请求时将当前的用户信息回填到request中,前提是当前请求不包含"user-info"这个header的情况下
        Map<String, Collection<String>> headers = requestTemplate.headers();
        if(!headers.containsKey(ExtractUserInfoUtil.USER_INFO_HEADER) || CollectionUtils.isEmpty(headers.get(ExtractUserInfoUtil.USER_INFO_HEADER))) {
    
    
            //填充请求头
            requestTemplate.header(ExtractUserInfoUtil.USER_INFO_HEADER, userInfo);
        }
    }
}

質問を残しておきます。上記のリクエストインターセプタを特定の指定された偽のクライアントインターフェイスメソッド(注釈でマークされた)に適用する必要があるとします(つまり、それらをグローバルに適用せず、呼び出し時にのみ適用します)。特定のメソッドは、インターセプターを使用しますか?)
sub-SpringMvcContract を継承し、解析メソッドを再利用して書き直すことができます; @RequestHeader アノテーションを使用します (これを試す必要があります)

おすすめ

転載: blog.csdn.net/qq_16992475/article/details/132836592