本文節選自《瘋狂Spring Cloud微服務架構實戰》html
京東購買地址:https://item.jd.com/12256011.htmljava
噹噹網購買地址:http://product.dangdang.com/25201393.htmlgit
Spring Cloud教學視頻:https://my.oschina.net/JavaLaw/blog/1552993github
Spring Cloud電子書:https://my.oschina.net/JavaLaw/blog/1570383api
根據前面章節可知,經過註解修改的接口方法,可讓接口方法得到訪問服務的能力。除了Feign自帶的方法外,還可使用第三方的註解。若是想使用JAXRS規範的註解,可使用Feign的「feign-jaxrs」模塊,在pom.xml中加入如下依賴便可:架構
<!-- Feign對JAXRS的支持 --> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-jaxrs</artifactId> <version>9.5.0</version> </dependency> <!-- JAXRS --> <dependency> <groupId>javax.ws.rs</groupId> <artifactId>jsr311-api</artifactId> <version>1.1.1</version> </dependency>
在使用註解修飾接口時,能夠直接使用@GET、@Path等註解,例如想要使用GET方法調用「/hello」服務,能夠定義如下接口:app
@GET @Path("/hello") String rsHello();
以上修飾接口的,實際上就等價於「@RequestLine("GET /hello")」。爲了讓Feign知道這些註解的做用,須要在建立服務客戶端時,調用contract方法來設置JAXRS註解的解析類,請見如下代碼:ide
RSClient rsClient = Feign.builder() .contract(new JAXRSContract()) .target(RSClient.class, "http://localhost:8080/");
設置了JAXRSContract類後,Feign就知道如何處理JAXRS的相關注解,下一小節,將講解Feign是如何處理第三方註解的。微服務
根據前一小節可知,設置了JAXRSContract後,Feign就知道如何處理接口中的JAXRS註解。JAXRSContract繼承了BaseContract類,BaseContract類實現了Contract接口,簡單的說,一個Contract就至關於一個翻譯器,Feign自己並不知道這些第三方註解的含義,而經過實現一個翻譯器(Contract)來告訴Feign,這些註解是作什麼的。學習
爲了讓讀者可以瞭解其中的原理,本小節將使用一個自定義註解,而且翻譯給Feign,讓其去使用。代碼清單5-15爲自定義註解以及客戶端接口的代碼。
代碼清單5-15:
codes\05\5.2\feign-use\src\main\java\org\crazyit\feign\contract\MyUrl.java
codes\05\5.2\feign-use\src\main\java\org\crazyit\feign\contract\HelloClient.java
@Target(METHOD) @Retention(RUNTIME) public @interface MyUrl { // 定義url與method屬性 String url(); String method(); } public interface HelloClient { @MyUrl(method = "GET", url = "/hello") String myHello(); }
接下來,就要將MyRrl註解的做用告訴Feign,新建Contract繼承BaseContract類,實現請見代碼清單5-16。
代碼清單5-16:
codes\05\5.2\feign-use\src\main\java\org\crazyit\feign\contract\MyContract.java
public class MyContract extends Contract.BaseContract { @Override protected void processAnnotationOnClass(MethodMetadata data, Class<?> clz) { } /** * 用於處理方法級的註解 */ protected void processAnnotationOnMethod(MethodMetadata data, Annotation annotation, Method method) { // 是MyUrl註解才進行處理 if(MyUrl.class.isInstance(annotation)) { // 獲取註解的實例 MyUrl myUrlAnn = method.getAnnotation(MyUrl.class); // 獲取配置的HTTP方法 String httpMethod = myUrlAnn.method(); // 獲取服務的url String url = myUrlAnn.url(); // 將值設置到模板中 data.template().method(httpMethod); data.template().append(url); } } @Override protected boolean processAnnotationsOnParameter(MethodMetadata data, Annotation[] annotations, int paramIndex) { return false; } }
在MyContract類中,須要實現三個方法,分別是處理類註解、處理方法註解、處理參數註解的方法,因爲咱們只定了一個方法註解@MyRul,所以實現processAnnotationOnMethod便可。
在processAnnotationOnMethod方法中,經過Method的getAnnotation獲取MyUrl的實例,將MyUrl的url、method屬性分別設置到Feign的模板中。在建立客戶端時,再調用contract方法便可,請見代碼清單5-17。
代碼清單5-17:
codes\05\5.2\feign-use\src\main\java\org\crazyit\feign\contract\ContractTest.java
public class ContractTest { public static void main(String[] args) { // 獲取服務接口 HelloClient helloClient = Feign.builder() .contract(new MyContract()) .target(HelloClient.class, "http://localhost:8080/"); // 請求Hello World接口 String result = helloClient.myHello(); System.out.println(" 接口響應內容:" + result); } }
運行代碼清單5-18,可看到控制檯輸出以下:
接口響應內容:Hello World
由本例可知,一個Contract實際上承擔的是一個翻譯的做用,將第三方(或者自定義)註解的做用告訴Feign。在Spring Cloud中,也實現了Spring的Contract,能夠在接口中使用@RequestMapping註解,讀者在學習Spring Cloud整合Feign時,見到使用@RequestMapping修飾的接口,就能夠明白其中的原理。
本文節選自《瘋狂Spring Cloud微服務架構實戰》
Spring Cloud教學視頻:https://my.oschina.net/JavaLaw/blog/1552993
Spring Cloud電子書:https://my.oschina.net/JavaLaw/blog/1570383