• @FeignClient常用属性


    @FeignClient(name = "gateway-test", value = "gateway-test", url = "localhost:9997", fallbackFactory = FallbackFactory.class, contextId = "GatewayClient")
    

    name/value: 服务名称

    //查看源码可知: 两个属性等价
    public @interface FeignClient {
       @AliasFor("value")
    	String name() default "";
    
    	@AliasFor("value")
    	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的值

    示例:

    image

    Product服务: 服提供者, 服务名product-client, 存在一个接口/product/test, 返回"test"字符串

    User服务: 调用方, 服务名user-client, 存在一个接口/user/test, 调用product服务的test接口

    //配置url方式,请求地址为url的地址
    @FeignClient(name = "product-client", url = "localhost:9997")
    public interface ProductClient {
    
        /**
         *  ..
         * @return .
         */
        @GetMapping("/product/test")
        String test();
    }
    
    @RequestMapping("/user")
    public class UserController {
    
        @Resource
        private ProductClient client;
    
        @GetMapping("/test")
        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的值作为请求地址进行调用
    
    
    //使用服务名调用方式
    @FeignClient(name = "product-client")
    public interface ProductClient {
    
        /**
         *  ..
         * @return .
         */
        @GetMapping("/product/test")
        String test();
    }
    //调用成功,后台能看到获取注册中心(nacos)的数据解析获取真实的url地址的日志
    

    image

    //用一个不存在的服务名再验证一下
    @FeignClient(name = "product-client123")
    public interface ProductClient {
    
        /**
         *  ..
         * @return .
         */
        @GetMapping("/product/test")
        String test();
    }
    //报错信息:
    com.netflix.client.ClientException: Load balancer does not have available server for client: product-client123
    

    fallbackFactory: 获取异常信息

    示例:

    user服务开启hystrix
    feign:
      hystrix:
        enabled: true
     
    //user服务添加fallback,用于在调用服务出现错误时,返回自定义信息
    @Component
    public class ProductClientFallback implements ProductClient{
        @Override
        public String test() {
            return "error";
        }
    } 
    
    //user服务添加fallbackFactory,用户在调用服务出现错误时,获取错误信息
    @Component
    public class ProductClientFallbackFactory implements FallbackFactory<ProductClient> {
        @Resource
        ProductClientFallback fallback;
        @Override
        public ProductClient create(Throwable cause) {
            System.out.println("cause.getMessage() = " + cause.getMessage());
            return fallback;
        }
    }   
    
    //product服务修改/product/test接口,模拟出现异常
    @RestController
    @RequestMapping("/product")
    public class ProductController {
        @GetMapping("/test")
        public String test() throws Exception {
            throw new Exception("test Exception");
        }
    }    
    

    Postman访问 http://localhost:8200/user/test ,成功返回自定义的异常信息

    image

    查看服务调用方User的日志, 成功打印出错误日志

    image

    message信息为空的话,配置一下Product服务:

    server:
      error:
        include-message: ALWAYS
    

    具体原因请查看 博客, 也可以通过使用@ControllerAdvice来解决

    contextId: 别名

    假设一个User服务有两个FeignClient,都需要调用Product服务, 因为name属性值一样,所以需要通过配置contextId来区分,否则启动项目时会报错

    @FeignClient(name = "product-client", fallbackFactory = ProductClientFallbackFactory.class, contextId = "ProductClientCopy")
    public interface ProductClientCopy {
    
        /**
         *  ..
         * @return .
         */
        @GetMapping("/product/testCopy")
        String test();
    }
    
    @FeignClient(name = "product-client", fallbackFactory = ProductClientFallbackFactory.class, contextId = "ProductClient")
    public interface ProductClient {
    
        /**
         *  ..
         * @return .
         */
        @GetMapping("/product/testCopy")
        String test();
    }
    
  • 相关阅读:
    Java 定时任务
    Swing中常用的方法
    瀑布流ajax分页
    权限管理
    图片自动加水印
    jsp自动生成静态页(提供思路)
    分页查询语句
    使用phpmailer发送邮件(以QQ邮箱为例)
    在浏览器的标签页显示网站标志图标(或指定图标)的方法
    随机生成验证码
  • 原文地址:https://www.cnblogs.com/llysc/p/15094772.html
Copyright © 2020-2023  润新知