Feign如何自定义注解翻译器

作者:chengqiuming 时间:2022-11-09 07:05:04 

Feign自定义注解翻译器

新建自定义注解MyUrl

package org.crazyit.cloud.contract; 
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 MyUrl {
    //为注解配置两个属性
    String url();
    String method();
}

新建接口,使用MyUrl注解

package org.crazyit.cloud.contract; 
public interface ContractClient { 
    @MyUrl(url = "/hello", method = "GET")
    public String hello();
}

定义注解翻译器

package org.crazyit.cloud.contract; 
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 data, Class<?> clz) {
        // 处理类级别注解
    }
 
    @Override
    protected void processAnnotationOnMethod(MethodMetadata data,
            Annotation annotation, Method method) {
        // 注解是MyUrl类型的,才处理
        if(MyUrl.class.isInstance(annotation)) {
            MyUrl myUrl = method.getAnnotation(MyUrl.class);
            String url = myUrl.url();
            String httpMethod = myUrl.method();
            data.template().method(httpMethod);
            data.template().append(url);
        }
    }
 
    @Override
    protected boolean processAnnotationsOnParameter(MethodMetadata data,
            Annotation[] annotations, int paramIndex) {
        // 处理参数级别注解
        return false;
    } 
}

测试类

package org.crazyit.cloud.contract; 
import org.crazyit.cloud.jaxrs.RsClient; 
import feign.Feign;
import feign.jaxrs.JAXRSContract;
 
public class ContractMain { 
    public static void main(String[] args) {
        ContractClient client = Feign.builder()
                .contract(new MyContract())
                .target(ContractClient.class,
                "http://localhost:8080");
        String result = client.hello();
        System.out.println(result);
    }
 
}

启动服务类

测试

Hello World

Feign注解说明

Feign是常用的微服务rpc调用框架,下面对一些注解说明

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface FeignClient {
   /**
    * value和name的作用一样,如果没有配置url那么配置的值将作为服务名称,用于服务发现。反之只是一个名称。
    *
    */
   @AliasFor("name")
   String value() default "";
   /**
    * serviceId已经废弃了,直接使用name即可。
    */
   /** @deprecated */
   @Deprecated
   String serviceId() default "";
   /**
    *某个服务提供的接口不止定义在一个类中,这样启动时会报Bean的名称冲突。
    * 解决方法:
    * 1:参数配置添加
    *  spring.main.allow-bean-definition-overriding=true
    *
    * 2:给每个client指定contextid
    *
    */
   String contextId() default "";
   /**
    *
    *  在注册Feign Client Configuration的时候需要一个名称,名称是通过getClientName方法获取的.
    *  查看源码可知,如果配置了contextId就会用contextId,
    *  如果没有配置就会去value,然后是name,最后是serviceId。
    *  默认都没有配置,当出现一个服务有多个Feign Client的时候就会报错了。
    *
    *  其次的作用是在注册FeignClient中,contextId会作为Client 别名的一部分,如果配置了qualifier优先用qualifier作为别名。
    *
    */
   /**
    *见 value
    *
    */
   @AliasFor("value")
   String name() default "";
   /**
    *
    * 在注册FeignClient中,指定client别名
    *
    */
   String qualifier() default "";
   /**
    *
    * url用于配置指定服务的地址,相当于直接请求这个服务,不经过Ribbon的服务选择。像调试等场景可以使用。
    *
    */
   String url() default "";
   /**
    *
    * 当调用请求发生404错误时,decode404的值为true,那么会执行decoder解码,否则抛出异常。
    *
    */
   boolean decode404() default false;
   /**
    *
    * configuration是配置Feign配置类,在配置类中可以自定义Feign的Encoder、Decoder、LogLevel、Contract等。
    * 具体查看FeignConfiguration类
    *
    */
   Class<?>[] configuration() default {};
   /**
    *
    * 定义容错的处理类,也就是回退逻辑,fallback的类必须实现Feign Client的接口,无法知道熔断的异常信息。
    *
    *
    *
    *
    * 举例:
    * //实现调用接口方法
    * @Component
    * public class UserRemoteClientFallback implements UserRemoteClient {
    *     @Override
    *     public User getUser(int id) {
    *     return new User(0, "默认fallback");
    *     }
    * }
    *
    * //user服务
    * @FeignClient(value = "user", fallback = UserRemoteClientFallback.class)
    * public interface UserRemoteClient {
    *     @GetMapping("/user/get")
    *     public User getUser(@RequestParam("id")int id);
    * }
    *
    *
    */
   Class<?> fallback() default void.class;
   /**
    *
    * 也是容错的处理,可以知道熔断的异常信息。熔断的另一种处理方法。
    *
    * //服务类作为参数传入FallbackFactory模板参数
    * @Component
    * public class UserRemoteClientFallbackFactory implements FallbackFactory<UserRemoteClient> {
    * private Logger logger = LoggerFactory.getLogger(UserRemoteClientFallbackFactory.class);
    *
    * @Override
    * public UserRemoteClient create(Throwable cause) {
    * return new UserRemoteClient() {
    * @Override
    * public User getUser(int id) {
    * logger.error("UserRemoteClient.getUser异常", cause);
    * return new User(0, "默认");
    * }
    * };
    * }
    * }
    *
    */
   Class<?> fallbackFactory() default void.class;
   /**
    *
    * path定义当前FeignClient访问接口时的统一前缀
    * 比如接口地址是/user/get, 如果你定义了前缀是user, 那么具体方法上的路径就只需要写/get 即可。
    *
    * @FeignClient(name = "user", path="user")
    * public interface UserRemoteClient {
    *     @GetMapping("/get")
    *     public User getUser(@RequestParam("id") int id);
    * }
    *
    */
   String path() default "";
   /**
    *  primary对应的是@Primary注解,默认为true.
    *  官方这样设置也是有原因的。当我们的Feign实现了fallback后,也就意味着Feign Client有多个相同的Bean在Spring容器中,
    *  当我们在使用@Autowired(建议使用@Resource注入对象)进行注入的时候,不知道注入哪个,所以我们需要设置一个优先级高的,@Primary注解就是干这件事情的。
    *
    *
    */
   boolean primary() default true;
}

来源:https://blog.csdn.net/chengqiuming/article/details/81140916

标签:Feign,注解,翻译器
0
投稿

猜你喜欢

  • Java命令设计模式优雅解耦命令和执行提高代码可维护性

    2023-11-23 06:25:46
  • Java SpringMVC异步处理详解

    2021-08-10 15:03:58
  • SpringBoot中获取profile的方法详解

    2023-11-19 18:05:00
  • SpringBoot优雅地实现全局异常处理的方法详解

    2023-09-06 09:17:02
  • 解决Mybatis-Plus操作分页后数据失效问题

    2023-11-25 11:31:55
  • SpringBoot中Dozer的使用小结

    2023-11-25 01:24:38
  • Android使用ContentResolver搜索手机通讯录的方法

    2021-12-28 08:33:16
  • Android隐藏标题栏及解决启动闪过标题的实例详解

    2023-10-10 12:18:12
  • Java程序部署到服务器上,接口请求下载文件失败/文件为空/文件名不对的问题

    2023-05-12 15:30:00
  • Java8 Stream流的常用方法汇总

    2023-07-17 17:56:59
  • C语言文件操作大全

    2022-10-17 06:25:01
  • android AlertDialog多种使用方法详解

    2021-09-14 05:57:10
  • C# 操作Excel代码总结

    2022-10-11 01:54:29
  • C#简单实现SNMP的方法

    2021-11-25 18:42:38
  • 详解JDK中ExecutorService与Callable和Future对线程的支持

    2023-11-25 07:39:07
  • 实例讲解JAVA设计模式之备忘录模式

    2023-08-29 16:31:19
  • Android自定义StepView仿外卖配送进度

    2022-07-30 01:34:35
  • Audio Source组件及相关API

    2023-07-07 14:22:37
  • Android如何获取系统通知的开启状态详解

    2021-12-28 05:45:09
  • C#游戏开发之实现贪吃蛇游戏

    2023-01-28 01:48:48
  • asp之家 软件编程 m.aspxhome.com