Feign是一個很優雅的REST客戶端,在Spring Cloud中我們可以像使用本地Service bean一樣使用FeignClient,這樣的好處是代碼更加簡單優雅 通俗易懂。
但是也有不好的,我們不太方便加入自己的元素進去,似乎Feign將很多東西封裝好了,我們按照那個套路寫就完事了,但有些情況下,不得不改裝一下了。
有很多Spring Cloud微服務使用的是OAuth2認證方式,加入認證之后,微服務之間調用也需要認證,這樣光簡單請求就連不通了。先想個問題,微服務之間可否有很簡單高效的方法去認證?
一般情況下,一個微服務調用另一個微服務的時候,肯定會伴隨一個客戶端請求,客戶端請求微服務A,微服務A調用微服務B,很少有A無緣無故去調用B。我們假設微服務A B都有OAuth2認證,那么他們的ResourceId肯定是同一個,因為都是一個項目,並且客戶端在請求A的時候,肯定是先拿到了access token,才能請求進來的。所以,我們在A call B的時候,可以直接將access token進行傳遞,直接用客戶端發送過來的access token 放到請求Headers中去請求B,這樣就能連通了。那么如何在不改變現有Feign的結構的情況下設置這個access token呢?看下面:
第一步:加入一個配置類,實現Feign的RequestInterceptor,有一個apply方法,可以在這個方法里面去DIY request template,可以加參數,加headers, 改body 改url都行。
@Configuration
public class FeignOAuth2RequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String accessToken = request == null ? StringUtils.EMPTY : request.getHeader(HttpHeaders.AUTHORIZATION);
System.out.println("=================Feign Interceptor AccessToken: " + accessToken);
requestTemplate.header(HttpHeaders.AUTHORIZATION, accessToken);
}
}
第二步: 在FeignClient 里面引入第一步的配置
@FeignClient(name = "test", configuration = FeignOAuth2RequestInterceptor.class)
public interface MailService {
@RequestMapping(value = "/api/email/v1/sendmail", method = RequestMethod.POST)
SimpleMailResponse sendMail(@RequestBody MailVO mailVO);
}
好了,啟動Spring Cloud項目再試試