复制代码
- 1
JAVA
name/value: 服务名称
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
JAVA
//查看源码可知: 两个属性等价 public FeignClient { String name() default ""; String name() default ""; } //查看源码可知: 两个属性至少要配置一个 FeignClientsRegistrar { private String getClientName(Map<String, Object> client) { if (client == null) { return null; } String value = (String) client.get("contextId"); if (!StringUtils.hasText(value)) { value = (String) client.get("value"); } if (!StringUtils.hasText(value)) { value = (String) client.get("name"); } if (!StringUtils.hasText(value)) { value = (String) client.get("serviceId"); } if (StringUtils.hasText(value)) { return value; } throw new IllegalStateException("Either 'name' or 'value' must be provided in @" + FeignClient.class.getSimpleName()); } }
url: 请求地址, 没配置的话, 会把name/value的属性值当成服务名进行调用, 配置的话则使用url的值
示例:
Product服务: 服提供者, 服务名product-client, 存在一个接口/product/test, 返回"test"字符串
User服务: 调用方, 服务名user-client, 存在一个接口/user/test, 调用product服务的test接口
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
JAVA
//配置url方式,请求地址为url的地址 public interface ProductClient { /** * .. * @return . */ String test(); } public class UserController { private ProductClient client; public String test() { return client.test(); } } //访问http://localhost:8200/user/test报错: //Connection refused: connect executing GET http://localhost:9997/product/test with root cause //说明配置了url属性后,确实是根据url的值作为请求地址进行调用
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
JAVA
//使用服务名调用方式 public interface ProductClient { /** * .. * @return . */ String test(); } //调用成功,后台能看到获取注册中心(nacos)的数据解析获取真实的url地址的日志
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
JAVA
//用一个不存在的服务名再验证一下 public interface ProductClient { /** * .. * @return . */ String test(); } //报错信息: com.netflix.client.ClientException: Load balancer does not have available server for client: product-client123
fallbackFactory: 获取异常信息
示例:
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
JAVA
user服务开启hystrix feign: hystrix: enabled: true //user服务添加fallback,用于在调用服务出现错误时,返回自定义信息 public class ProductClientFallback implements ProductClient{ public String test() { return "error"; } } //user服务添加fallbackFactory,用户在调用服务出现错误时,获取错误信息 public class ProductClientFallbackFactory implements FallbackFactory<ProductClient> { ProductClientFallback fallback; public ProductClient create(Throwable cause) { System.out.println("cause.getMessage() = " + cause.getMessage()); return fallback; } } //product服务修改/product/test接口,模拟出现异常 public class ProductController { public String test() throws Exception { throw new Exception("test Exception"); } }
Postman访问 http://localhost:8200/user/test ,成功返回自定义的异常信息
查看服务调用方User的日志, 成功打印出错误日志
message信息为空的话,配置一下Product服务:
复制代码
- 1
- 2
- 3
YAML
server: error: include-message: ALWAYS
具体原因请查看 博客, 也可以通过使用@ControllerAdvice来解决
contextId: 别名
假设一个User服务有两个FeignClient,都需要调用Product服务, 因为name属性值一样,所以需要通过配置contextId来区分,否则启动项目时会报错
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
JAVA
public interface ProductClientCopy { /** * .. * @return . */ String test(); } public interface ProductClient { /** * .. * @return . */ String test(); }