首页 > 其他分享 >SpringCloud OpenFeign配置

SpringCloud OpenFeign配置

时间:2022-12-15 21:34:37浏览次数:66  
标签:wf String OpenFeign SpringCloud 配置 import com public

前言

  • 原生OpenFeignSpringCloud OpenFeign在配置上有些区别,主要关注点在Contract、Encoder、Decoder的不同,而Contract最主要作用是对feignClient接口与方法上注解的解析(例如原生OpenFeign使用@RequestLine,而SpringCloud OpenFeign则是使用@RequestMapping),如果配置混了就会造成一些问题
  • 原生OpenFeign都是默认的:Contract.Default、Encoder.Default、Decoder.Default
  • SpringCloud OpenFeign则是:SpringMvcContract、SpringEncoder、SpringDecoder
  • 本文主要关注于SpringCloud OpenFeign的配置,对于原生OpenFeign的配置,请看笔者另一篇文章原生Feign进行HTTP调用

依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <version>2.1.3.RELEASE</version>
</dependency>
<!--因为使用的是jackson自定义反序列化,所以引入此包-->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-jackson</artifactId>
    <version>10.10.1</version>
</dependency>

配置

application.yml

feign:
  hystrix: 
    enabled: true #开启hystrix
  httpclient:
    enabled: true #使用httpclient客户端
  client:
    config:
      default:
        connectTimeout: 3000 #连接超时
        readTimeout: 10000 #返回超时
hystrix:
  threadpool:
    default:
      coreSize: 50
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 9000 #fallback超时时间

FeignClient

  • 因为公共路径和公共headers,接口上使用了@RequestMapping注解,所以不能使用FallBackImpl实现接口的fallback,否则会报错

    java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'com.wf.itao.auth.core.client.AspClient' method...
    
  • @RequestMappingheaders设置需要使用=连接,而不能使用:,这点在org.springframework.cloud.openfeign.support.SpringMvcContract#parseHeaders方法中体现

  • headers中可以使用变量形式,从配置中获取值

  • @RequestHeader注解支持动态传入header

package com.wf.itao.auth.core.client;

import com.wf.itao.auth.core.client.fallback.AspClientFallbackFactory;
import com.wf.itao.auth.core.common.util.AspResponseDecoder;
import com.wf.itao.auth.core.entity.Role;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

/**
 * @author wf
 * @date 2022年09月23日 11:14
 * @description
 */
@RequestMapping(value = "dev", headers = {"systemKey=${sysKey}"})
@FeignClient(name = "asp", url = "${gwUrl}", decode404 = true, configuration = {AspResponseDecoder.class}, fallbackFactory = AspClientFallbackFactory.class)
public interface AspClient {

    String QUERY_ROLES_URI = "/queryRoles";

    String QUERY_BTNS = "/queryBtns";

    /**
     * 查询角色
     *
     * @param userId
     * @return
     */
    @GetMapping(value = QUERY_ROLES_URI)
    List<Role> queryRoles(@RequestHeader("sgs-userid") String userId);

    @GetMapping(value = QUERY_BTNS)
    List<String> queryBtns(@RequestHeader("sgs-userid") String userId, @RequestParam("moduleId") Long moduleId, @RequestParam("roleId") Long roleId, @RequestParam("time") Long time);

FallbackFactory

package com.wf.itao.auth.core.client.fallback;

import com.wf.itao.auth.core.client.AspClient;
import com.wf.itao.auth.core.entity.Role;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
import org.testng.collections.Lists;

import java.util.List;

/**
 * @author wf
 * @date 2022年09月23日 11:14
 * @description
 */
@Component
public class AspClientFallbackFactory implements FallbackFactory<AspClient> {

    @Override
    public AspClient create(Throwable cause) {
        return new AspClient() {
            @Override
            public List<Role> queryRoles(String userId) {
                return Lists.newArrayList();
            }

            @Override
            public List<String> queryBtns(String userId, Long moduleId, Long roleId, Long time) {
                return Lists.newArrayList();
            }
        };
    }
}

自定义Response

package com.wf.itao.auth.core.common.asp;

/**
 * @author wf
 * @date 2021年04月27日 14:28
 * @description
 */
public class AspResponse<T> {

    private String msg;
    private String succ;
    private T result;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public String getSucc() {
        return succ;
    }

    public void setSucc(String succ) {
        this.succ = succ;
    }

    public T getResult() {
        return result;
    }

    public void setResult(T result) {
        this.result = result;
    }
}

自定义Decoder

package com.wf.itao.auth.core.common.util;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wf.boot.base.exception.BusinessException;
import com.wf.itao.auth.core.common.asp.AspResponse;
import feign.FeignException;
import feign.Response;
import feign.jackson.JacksonDecoder;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpStatus;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Map;

/**
 * @author wf
 * @date 2021年04月27日 14:10
 * @description
 */
@Slf4j
public class AspResponseDecoder extends JacksonDecoder {

    private static final String OK = "ok";

    private static final ObjectMapper MAPPER = new ObjectMapper();

    static {
        MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    @Override
    public Object decode(Response response, Type type) throws IOException {
        Type decodeType = ParameterizedTypeImpl.make(AspResponse.class, new Type[]{Object.class}, null);
        Object decodeObj = super.decode(response, decodeType);
        if (decodeObj != null && decodeObj instanceof AspResponse) {
            AspResponse aspResponse = (AspResponse) decodeObj;
            if (!OK.equals(aspResponse.getSucc())) {
                log.error("接口返回失败 url : {}, msg : {}", response.request().url(), aspResponse.getMsg());
                throw FeignException.errorStatus("接口返回失败 url :" + response.request().url(), response);
            }
            if (aspResponse.getResult() == null) {
                JavaType javaType = MAPPER.constructType(type);
                Class<?> rawClass = javaType.getRawClass();
                if (Collection.class.isAssignableFrom(rawClass) ||
                        Map.class.isAssignableFrom(rawClass)) {
                    try {
                        return rawClass.newInstance();
                    } catch (Exception e) {
                        log.error("实例化aspResponse异常", e);
                    }
                }
            }
            return MAPPER.convertValue(aspResponse.getResult(), MAPPER.constructType(type));
        }
        throw new BusinessException(JSON.toJSONString(decodeObj));
    }
}

Application

  • @EnableFeignClients开启Feign

总结

  • SpringCloud OpenFeign是在原生OpenFeign的基础上构建起来,更加易用
  • SpringCloud OpenFeign不支持@Headers注解,@Headers原生OpenFeign支持,在Contract.Default中解析

参考

标签:wf,String,OpenFeign,SpringCloud,配置,import,com,public
From: https://www.cnblogs.com/wftop1/p/16986049.html

相关文章

  • 开发篇-加载测试专用属性&配置
           ......
  • STL之空间配置器
    空间配置器allocator只是基层内存配置/释放行为的一层薄薄的包装,没有任何效率上的强化。一般而言,C++内存配置操作和释放操作如下:classFoo{...};Foo*pf=newFoo;......
  • mysql 主从docker-compose 配置
    version:'3'services:#主从mysql配置mysql-master:image:mysql:8.0.24restart:alwayscontainer_name:mysql-masterenvironment:M......
  • opencv在Xcode中的配置方式
    今天想把一个以前小时候玩过的游戏用UE4作成3D的,发现这个游戏每一个地图是16X14的地图块组成的,因为自已不想一张地图一张地图的去照着以前的地图拼出所有的地图数据,作为一......
  • 【Dubbo】快速入门案例以及配置详情
    文章目录​​1、Dubbo的前世今生​​​​2、Dubbo的快速入门​​​​2.1、Dubbo的基本架构​​​​2.2、Nacos​​​​2.3、管理后台​​​​2.4、入门案例​​​​2.5、代......
  • react 配置代理
    //配置代理项目中自带(http-proxy-middleware)constproxy=require('http-proxy-middleware')module.exports=function(app){  app.use(    proxy......
  • silence 主题配置说明
    silence代码开源地址1.基础设置2.css样式注意:要禁用默认CSS@mediaonlyscreenand(max-width:1365px){.github-corner{display:none}}@mediaonlyscreenand(......
  • MySQL5.7.21开启Gtid配置主从复制
    mysql5.7.21开启Gtid配置主从复制一、环境:mysql主库master:10.0.0.101172.168.1.101mysql从库slave:10.0.0.103172.168.1.103mysql-5.7.21-linux-glibc2.12-x86_64.tar.gz......
  • Rocky Linux9.1 手动配置静态IP
    #修改网络的配置文件[root@zabbix~]#vim/etc/NetworkManager/system-connections/ens192.nmconnection[connection]id=ens192uuid=0572911c-bd45-33c3-9442-c896e0320......
  • binlog及审计配置
    实现方案[binlog+init-connect],binlog可以审计到所有数据记录及表结构变更相关的记录,但,不记录连接的信息,要通过额外的手段来记录,比如showfullprocesslist;是可得出......