java
主页 > 软件编程 > java >

SpringCloud OpenFeign基本介绍与实现示例

2023-02-23 | 佚名 | 点击:

介绍

  在上面一篇介绍Nacos的文章最后,两个服务的相互调用是用的RestTemplate类完成的。但这种方式不是很推荐,更佳的方式是用OpenFeign组件去调用。OpenFeign是官方推出的服务调用和负载均衡组件,基于Ribbon和Hystrix,前身是第一代Spring Cloud的Feign,对Feign进行了扩展,支持了SpringMvc的相关注解。

常用注解

  OpenFeign是使用接口+注解实现的,因此了解它的常用注解是必要的,有以下几个:

@EnableFeignClients:在启动类上添加,用于开启OpenFeign功能。当项目启动时,会扫描带有@FeignClient的接口,生成代理类并注册到Spring容器中

@FeignClient:通知OpenFeign组件对该注解下的接口进行解析,通过动态代理的方式产生实现类,完成服务调用

@RequestMapping:SpringMvc中的注解,不过此时该注解表示发起Request请求(默认Get方式)

@GetMapping:SpringMvc中的注解,不过此时该注解表示发起Get请求

@PostMapping:SpringMvc中的注解,不过此时该注解表示发起Post请求

代码实现

  首先得把Nacos启动

  服务提供方,

  bootstrap.yml:

server:
  port: 8083
  servlet:
    context-path: /nacosProvider

spring:
  application:
    name: nacos-provider
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

  引入依赖:

1

2

3

4

5

6

7

8

9

10

11

12

<dependencies>

    <dependency>

        <groupId>com.alibaba.cloud</groupId>

        <artifactId>spring-cloud-starter-alibaba-nacos-discovery

        </artifactId>

        <version>2.2.0.RELEASE</version>

    </dependency>

    <dependency>

        <groupId>org.projectlombok</groupId>

        <artifactId>lombok</artifactId>

    </dependency>

</dependencies>

  服务方法:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

@Controller

@RequestMapping("/provide")

public class ProviderController {

    @RequestMapping("/distribute")

    @ResponseBody

    public String distribute() {

        return "吃鸡胸肉";

    }

    @RequestMapping("/distribute1")

    @ResponseBody

    public String distribute1(String name, Integer age) {

        return "姓名:" + name + ",年龄:" + age;

    }

    @PostMapping("/distribute2")

    @ResponseBody

    public String distribute2(@RequestBody Person p) {

        return "身高:" + p.getHeight() + ",肤色:" + p.getSkin();

    }

}

1

2

3

4

5

6

import lombok.Data;

@Data

public class Person {

    private Integer height;

    private String skin;

}

  服务调用方,

  bootstrap.yml

server:
  port: 8082
  servlet:
    context-path: /nacosInvoke

spring:
  application:
    name: nacos-invoke
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

  引入依赖:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

<dependencies>

    <dependency>

        <groupId>com.alibaba.cloud</groupId>

        <artifactId>spring-cloud-starter-alibaba-nacos-discovery

        </artifactId>

        <version>2.2.0.RELEASE</version>

    </dependency>

    <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-openfeign</artifactId>

        <version>2.2.0.RELEASE</version>

    </dependency>

    <dependency>

        <groupId>org.projectlombok</groupId>

        <artifactId>lombok</artifactId>

    </dependency>

</dependencies>

  启动类上添加注解:

1

2

3

4

5

6

7

8

9

10

11

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.openfeign.EnableFeignClients;

//开启OpenFeign

@EnableFeignClients

@SpringBootApplication

public class NacosInvokeApplication {

    public static void main(String[] args) {

        SpringApplication.run(NacosConfigApplication.class, args);

    }

}

  创建@FeignClient修饰的接口:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

import com.gs.nacos_invoke.dto.Person;

import org.springframework.cloud.openfeign.FeignClient;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RequestBody;

import org.springframework.web.bind.annotation.RequestParam;

/**

 * value值是服务提供方的服务名称

 */

@FeignClient(value = "nacos-provider")

public interface InvokeClient {

    @GetMapping("/nacosProvider/provide/distribute")

    String distribute();

    @GetMapping("/nacosProvider/provide/distribute1")

    String distribute1(@RequestParam("name") String name,

    @RequestParam("age") Integer age);

    @PostMapping("/nacosProvider/provide/distribute2")

    String distribute2(@RequestBody Person p);

}

  Person类(服务调用方再创建一个,不是同一个):

1

2

3

4

5

6

import lombok.Data;

@Data

public class Person {

    private Integer height;

    private String skin;

}

  编写控制器,使用接口请求提供方的服务:

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

import com.gs.nacos_invoke.dto.Person;

import com.gs.nacos_config.feign.InvokeClient;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestMapping;

@Controller

@RequestMapping("/user")

public class UserController {

    @Autowired

    private InvokeClient invokeClient;

    @GetMapping("/invoke")

    public void invoke(String name, Integer age) {

        String str = invokeClient.distribute();

        System.out.println(str);

    }

    @GetMapping("/invoke1")

    public void invoke1() {

        String str = invokeClient.distribute1("coder", 20);

        System.out.println(str);

    }

    @GetMapping("/invoke2")

    public void invoke2() {

        Person p = new Person();

        p.setHeight(183);

        p.setSkin("黄皮肤");

        String s = invokeClient.distribute2(p);

        System.out.println(s);

    }

}

注意事项

  OpenFeign是基于Ribbon的,所以它默认是负载均衡的。其次,它也是基于Hystrix的,有超时降级的处理:默认服务提供方的接口超时时间是1s,超过1s服务调用方会报错。1s是可以配置的,按照业务需要调整。@FeignClient注解有个fallback属性,当该属性有值时,服务提供方超时,会返回程序所指定的降级值。

  服务调用方,bootstrap.yml添加(更规范的做法是引入spring-cloud-starter-alibaba-nacos-config依赖,nacos中新建配置,然后在这个配置中添加):

feign:
  hystrix:
    enabled: true
ribbon:
    # 请求连接的超时时间
    ConnectionTimeout: 3000
    # 请求处理的超时时间
    ReadTimeout: 3000

hystrix:
    command:
        default:
            execution:
                isolation:
                    thread:
                        timeoutInMilliseconds: 3000

  接口修改为:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

import com.gs.nacos_invoke.dto.Person;

import org.springframework.cloud.openfeign.FeignClient;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RequestBody;

import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(value = "nacos-provider",

        fallback = InvokeClientFallback.class)

public interface InvokeClient {

    @GetMapping("/nacosProvider/provide/distribute")

    String distribute();

    @GetMapping("/nacosProvider/provide/distribute1")

    String distribute1(@RequestParam("name") String name,

    @RequestParam("age") Integer age);

    @PostMapping("/nacosProvider/provide/distribute2")

    String distribute2(@RequestBody Person p);

}

  fallback指定的类:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

import com.gs.nacos_invoke.dto.Person;

import org.springframework.stereotype.Component;

@Component

public class InvokeClientFallback implements InvokeClient {

    @Override

    public String distribute() {

        return "超时3s";

    }

    @Override

    public String distribute1(String name, Integer age) {

        return "超时3s";

    }

    @Override

    public String distribute2(Person p) {

        return "超时3s";

    }

}

  服务提供方ProviderController类的方法中,加入Thread.sleep(4000);或者throw new RuntimeException("抛异常");来触发降级(抛出未捕获的异常也能触发)。

原文链接:https://blog.csdn.net/gs2436/article/details/127938265
相关文章
最新更新