Feign第三方註解與請求攔截器
1、使用第三方直接
1.1、引入依賴
- 如果想使用JAXRS規範來註解,可以使用Feign的“feign-jaxrs”模塊
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jaxrs</artifactId>
<version>9.5.0</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>1.1.1</version>
</dependency>
1.2、修改客戶端接口
package com.atm.cloud;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import feign.RequestLine;
public interface HelloClient {
@GET
@Path("/hello")
public String sayHello();
}
1.3、請求測試
package com.atm.cloud;
import feign.Feign;
import feign.gson.GsonEncoder;
import feign.jaxrs.JAXRSContract;
public class HelloClient {
public static void main(String[] args) {
HelloClient helloClient = Feign.builder().contract(new JAXRSContract())
.target(HelloClient.class, "http://localhost:8080/");
String result = helloClient.sayHello();
System.out.println("接口響應內容:" + result);
}
}
2、Feign解析第三方註解原理
- 設置了 JAXRSContract 類,Feign 就知道如何處理 JAXRS 的相關注解
- JAXRSContract繼承了BaseContract類,BaseContract類實現了Contract接口
- 簡單來說,一個Contract就相當於一個翻譯器
- Feign本身並不知道第三方註解的含義,而是通過實現一個翻譯器(Contract)來告訴Feign
- 下面,我們首先將自定義註解告訴Feign,然後Feign通過翻譯器解析我們自定義的註解
2.1、自定義註解
package com.atm.cloud
import java.lang.annotation.ElementType
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
import java.lang.annotation.Target
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnott {
// 定義url和method屬性
String url()
String method()
}
2.2、修改客戶端接口
package com.atm.cloud;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import feign.RequestLine;
public interface HelloClient {
@MyAnnott(method="GET",url="/hello")
public String sayHello();
}
2.3、自定義翻譯器
package com.atm.cloud;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import feign.Contract.BaseContract;
import feign.MethodMetadata;
public class MyContract extends BaseContract {
@Override
protected void processAnnotationOnClass(MethodMetadata metadata,
Class<?> arg1) {
}
@Override
protected void processAnnotationOnMethod(MethodMetadata metadata,
Annotation annotation, Method method) {
if(MyAnnott.class.isInstance(annotation)){
MyAnnott myAnnott = method.getAnnotation(MyAnnott.class);
String url = myAnnott.url();
String httpMethod = myAnnott.method();
metadata.template().method(httpMethod);
metadata.template().append(url);
}
}
@Override
protected boolean processAnnotationsOnParameter(MethodMetadata metadata,
Annotation[] annotations, int i) {
return false;
}
}
- 在 MyContract 類中,需要實現三個方法,分別是處理類註解、處理方法註解、處理參數註解的方法
- 我們只定了一個方法註解@MyRul,因此實現processAnnotationOnMethod 即可
- 通過 Method 的 getAnnotation 獲取 MyUrl的實例,將 MyUrl 的 url、method 屬性分別設置到 Feign 的模板中
2.4、請求測試
package com.atm.cloud;
import feign.Feign;
import feign.gson.GsonEncoder;
import feign.jaxrs.JAXRSContract;
public class HelloMain {
public static void main(String[] args) {
HelloClient helloClient = Feign.builder().contract(new MyContract())
.target(HelloClient.class, "http://localhost:8080/");
String result = helloClient.sayHello();
System.out.println(" 接口響應內容:" + result);
}
}
- Contract 實際上承擔的是一個翻譯的作用,將第三方(或者自定義)註解的作用告訴 Feign
3、請求攔截器
- 在發送請求的時候需要設置公共信息(權限、請求類型等)
3.1、編寫請求攔截器
package com.atm.cloud.interceptor;
import feign.RequestInterceptor;
import feign.RequestTemplate;
public class MyInterceptor implements RequestInterceptor {
public void apply(RequestTemplate template) {
System.out.println(" --->>> 這是自定義攔截器 <<<--- ");
}
}
3.2、運行測試
package com.atm.cloud.interceptor
import com.atm.cloud.HelloClient
import feign.Feign
public class InterceptorMain {
public static void main(String[] args) {
HelloClient helloClient = Feign.builder()
.requestInterceptor(new MyInterceptor())
.target(HelloClient.class, "http://localhost:8080/")
String result=helloClient.sayHello()
System.out.println(result)
}
}
4、接口日誌
- 默認情況下,接口不會記錄接口日誌
- 如果想要了解接口的調用情況,可以配置接口日誌
4.1、運行測試
package com.atm.cloud.log;
import com.atm.cloud.HelloClient;
import feign.Feign;
import feign.Logger;
public class LogMain {
public static void main(String[] args) {
/**
* NONE: 默認值,不記錄日誌
* BASIC: 記錄請求方法、URL、響應狀態代碼和執行時間
* HEADERS: 除BASIC記錄日誌外,還會記錄請求頭和響應頭的信息
* FULL: 在HEADERS的基礎上,請求和響應的元數據,都會保存
*/
HelloClient helloClient = Feign.builder().logLevel(Logger.Level.FULL)
.logger(new Logger.JavaLogger().appendToFile("logs/main.log"))
.target(HelloClient.class, "http://localhost:8080/");
String result = helloClient.sayHello();
System.out.println(result);
}
}