本文节选自《疯狂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
本书代码共享地址:https://gitee.com/yangenxiong/SpringCloud