Feign如何自定义注解翻译器

网友投稿 382 2022-08-20


Feign如何自定义注解翻译器

目录Feign自定义注解翻译器新建自定义注解MyUrl新建接口,使用MyUrl注解定义注解翻译器测试类启动服务类Feign注解说明

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 {

* 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;

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:java实现学生宿舍系统
下一篇:Java十分钟快速掌握单例模式
相关文章

 发表评论

暂时没有评论,来抢沙发吧~