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);
}
}