Fegin根据配置项请求不同的地址实现方法

在项目过程中,可能会遇到比较奇葩的需求,比如:使用@FeginClient注解的接口只能配置一个url,但我又想根据不同的配置项决定我使用哪个url,当然,前提是这两个url属于同一个项目的不同的部署环境。

众所周知,feign只是个声明式调用,没有决策机制,所以想通过feign自己来实现是不可能了。

我的实现方式:

1.这两个FeignClient继承同一个接口,因为所有的方法都相同,把方法都写到这个父类接口中,两个子类接口body体为空即可。

2.配置文件中增加一个配置项,如果这个配置项等于某个值,就调用一个FeignClient,否则,调用另一个。

下面上代码:

公共接口(不需要加@Service和@FeginClient注解):


public interface AssetService {
   
    @PostMapping(value = "/v2/model/nodes/{namespace}/access")
    public Response getNodeById( @PathVariable("namespace") String namespace,
            @RequestBody AccessNodeParam accessNodeParam);

    @PostMapping("/opcua/getNodesByBrowsePath")
    public @ResponseBody
    Response getNodesByBrowsePath(@RequestBody List<OPCUABrowsePath> opcuaBrowsePaths);
}

两个子类接口(需要加@FeginClient和@Service注解):

接口1:

@Service
@FeignClient(name = "MS-ASSET", url="${assetSrv.url1}")
public interface AssetQueryServiceOfDevice extends AssetService{}

接口2:

@Service
@FeignClient(name = "MS-ASSET", url="${assetSrv.url2}")
public interface AssetQueryServiceOfProject extends AssetService{}

使用这两个FeginClient:

在Controller中使用这两个FeginClient的方法:

(1)给Controller的增加构造方法

(2)在Controller的构造方法中将@Value获取的变量和这两个FeginClient注入进去,这里要注意:不能直接使用@Value获取配置文件中的配置项,然后直接在AggQueryController 的构造方法中使用,因为:构造器的执行要早于@Value和@Autowired,构造方法执行时所有的@Value或@Autowired注解的对象此时都还为空,导致他们一直为空!

所以要把@Value获取的配置项通过一个配置类获取,然后将这个配置类通过构造方法注入到AggQueryController !

@RequestMapping("/query")
@RequestController
public class AggQueryController {
    private static final Logger logger = LoggerFactory.getLogger(AggQueryController.class);

    private String assetRequestFlag;

    private AssetService assetService;

    /**
     * 将配置信息通过一个配置类获取,然后在构造器中注入;
否则,因为构造器的执行要早于@Value和@Autowired,会导致所有的对象都为空
     * @param config
     */
    public AggQueryController(AggQueryConfig config){
        this.assetRequestFlag= config.getAssetRequest();
        
        assetService = config.getAssetService();
    }
}

(3)配置类(用@Configuration注解的好处是能保证实例化优先级比较高):

@Configuration
public class AggQueryConfig {
    @Value("${assetSrv.requestFlag}")
    private String assetRequest;

    @Autowired
    private AssetQueryService assetQueryService;

    @Autowired
    private AssetQueryServiceOfProject assetQueryServiceOfProject;

    @Autowired
    private TimeSeriesService timeSeriesService;

    public AssetService getAssetService(){
        if(StringUtils.equalsIgnoreCase("device", assetRequest)){
            return assetQueryService;
        }
        return assetQueryServiceOfProject;
    }
}

这样,在AggQueryController中的其他方法中就可以使用assetService了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值