背景
Springboot項(xiàng)目集成Feign,Ribbon(由于項(xiàng)目部署在K8S集群中霹娄,所以未使用Eureka)嘉抒,因此FeignClient使用url來(lái)調(diào)用其他服務(wù)姿鸿,配置如下:
@FeignClient(name = "user", url = "${user.url}", configuration = {FeignExceptionDecoder.class})
此時(shí)url是的值是占位符,讀取的配置文件站削,項(xiàng)目運(yùn)行沒(méi)有問(wèn)題
問(wèn)題
1. 執(zhí)行單元測(cè)試時(shí)坊萝,BaseTest報(bào)錯(cuò)
無(wú)法初始化feignClient,因?yàn)檎嘉环?code>http://${user.url}替換不了
第一反應(yīng)是配置文件讀取失敗许起,要不然占位符已經(jīng)被成功替換了十偶,而不是拼上http://
,于是去檢查配置园细,配置沒(méi)有問(wèn)題
很奇怪扯键,于是去看EnableFeignClients
注解,點(diǎn)到FeignClientsRegistrar.Class
珊肃,搜索url發(fā)現(xiàn)了getUrl()
方法(如下)荣刑,看到里面用的是#{}
而不是${}
去判斷,于是突發(fā)奇想伦乔,把所有的FeignClient里的url都使用#{}
厉亏,執(zhí)行單元測(cè)試,不報(bào)這個(gè)錯(cuò)了
static String getUrl(String url) {
if (StringUtils.hasText(url) && (!url.startsWith("#{") || !url.contains("}"))) {
if (!url.contains("://")) {
url = "http://" + url;
}
try {
new URL(url);
} catch (MalformedURLException var2) {
throw new IllegalArgumentException(url + " is malformed", var2);
}
}
return url;
}
2. 繼續(xù)執(zhí)行單元測(cè)試烈和,拋出異常NoSuchBeanDefinitionException
如果在此時(shí)運(yùn)行項(xiàng)目爱只,會(huì)發(fā)現(xiàn)FeignClient的bean都無(wú)法注入了,但是當(dāng)時(shí)博主已被自己的機(jī)智迷昏了頭腦恬试,沒(méi)發(fā)現(xiàn)這個(gè)問(wèn)題
這時(shí)候,網(wǎng)上各種搜索這個(gè)報(bào)錯(cuò)哑舒,發(fā)現(xiàn)看下來(lái)有以下幾個(gè)解決方法:
- BaseTest啟動(dòng)類加上注解
@EnableFeignClients
但是博主已經(jīng)加了的洗鸵,所以這個(gè)對(duì)博主無(wú)用
- BaseTest啟動(dòng)類加上注解
@ImportAutoConfiguration({RibbonAutoConfiguration.class, FeignRibbonClientAutoConfiguration.class, FeignAutoConfiguration.class})
加上試了無(wú)用,還是一樣的報(bào)錯(cuò)
- BaseTest啟動(dòng)類加上注解
@EnableFeignClients(basePackages = "com.xxx")
剛試完加上單元測(cè)試還是報(bào)錯(cuò)火邓,突然發(fā)現(xiàn)項(xiàng)目跑不起來(lái)了贡翘,而且代碼是push過(guò)的(因?yàn)樽屃硪粋€(gè)同事幫忙一起看下)鸣驱,此時(shí)博主開始慌了踊东,趕緊把FeignClient里url的占位符#再改回$刚操,項(xiàng)目跑起來(lái)了菊霜,謝天謝地鉴逞。
這時(shí)候博主突然奇想构捡,會(huì)不會(huì)是因?yàn)榕渲玫腷asePackages范圍太大了(博主的項(xiàng)目是多模塊分層的勾徽,所有的FeignClient都放在Service模塊的第x層包下,而此時(shí)就只配到第2層而已)咒钟,所以修改basePackages朱嘴,配置到FeignClient所在的包目錄
驚奇的發(fā)現(xiàn)级乍!單元測(cè)試跑起來(lái)了玫荣!依賴注入也都有值
總結(jié)
其實(shí)最開始的占位符http://${user.url}
替換不了捅厂,以及后面的NoSuchBeanDefinitionException
,都應(yīng)該想到撵割,是因?yàn)閟pringboot掃包沒(méi)掃到引起的啡彬,貼上博主可行的配置
@RunWith(SpringRunner.class)
@SpringBootTest
@EnableFeignClients(basePackages = "com.xxxx.xxxx.xxxx.xxxx")
public class BaseTest extends AbstractTransactionalTestNGSpringContextTests {
}
收工庶灿!