Spring Cloud_13_Feign第三方注解与请求拦截器

Feign第三方注解与请求拦截器

1、使用第三方直接

1.1、引入依赖

  • 如果想使用JAXRS规范来注解,可以使用Feign的“feign-jaxrs”模块

<dependency>
    <groupId>io.github.openfeigngroupId>
    <artifactId>feign-jaxrsartifactId>
    <version>9.5.0version>
dependency>

<dependency>
    <groupId>javax.ws.rsgroupId>
    <artifactId>jsr311-apiartifactId>
    <version>1.1.1version>
dependency>

1.2、修改客户端接口

package com.atm.cloud;

import javax.ws.rs.GET;
import javax.ws.rs.Path;

import feign.RequestLine;

public interface HelloClient {

    /*@RequestLine("GET /hello")
    public String sayHello();*/

    @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) {

        //设置了 JAXRSContract 类,Feign 就知道如何处理 JAXRS 的相关注解
        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 {

    /*@RequestLine("GET /hello")
    public String sayHello();*/

    /*@GET
    @Path("/hello")
    public String sayHello();*/

    @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) {

        //注解是MyAnnott类型,才解析
        if(MyAnnott.class.isInstance(annotation)){
            // 获取注解的实例
            MyAnnott myAnnott = method.getAnnotation(MyAnnott.class);
            // 获取服务的 url
            String url = myAnnott.url();
            // 获取配置的 HTTP 方法
            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/");
        // 请求 Hello World 接口
        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) {
        //设置请求头信息(这样就可以不需要在每一个方法中都设置了)
        //template.header("Content-Type", "application/json");
        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);
    }
}
  • 需要创建日志文件

你可能感兴趣的:(SpringCloud,SpringCloud)