如何集成和使用Feign的远程调用

2023-12-16 15:38:02
  1. feign的简单介绍
    1. Feign是一个声明式的http客户端,可以帮助我们优雅的实现http请求的发送
      1. OpenFeign/feign: Feign makes writing java http clients easier (github.com)
      2. Spring Cloud OpenFeign 中文文档 (springdoc.cn)
      3. Spring Cloud OpenFeign
  2. 在spring cloud的基础上集成feign
    1. 新建并修改maven模块user-feign-api,定义第三方调用时需要引用的feign接口模块
      1. 在maven的pom文件中添加openfeign依赖
        1. 
                  <!-- openfeign依赖 -->
                  <dependency>
                      <groupId>org.springframework.cloud</groupId>
                      <artifactId>spring-cloud-starter-openfeign</artifactId>
                  </dependency>
          
      2. 在模块中新建UserApi的FeignClient的接口类,其他相关的类略
        1. package com.app.user.api;
          
          
          import com.app.user.common.ResultBean;
          import com.app.user.pojo.User;
          import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
          import org.springframework.cloud.openfeign.FeignClient;
          import org.springframework.web.bind.annotation.*;
          
          /**
           * 用户API
           *
           * @author Administrator
           */
          @FeignClient(value = "nacos-feign-user-service", path = "/users")
          public interface UserApi {
              /**
               * 新增用户
               *
               * @param user 用户信息
               * @return 用户信息
               */
              @PostMapping
              ResultBean<User> save(@RequestBody User user);
          
              /**
               * 根据id修改用户信息
               *
               * @param user 用户信息
               * @return 修改提示信息
               */
              @PutMapping
              ResultBean<String> update(@RequestBody User user);
          
              /**
               * 根据id查询用户信息
               *
               * @param id 用户id
               * @return 用户信息
               */
              @GetMapping("/{id}")
              ResultBean<User> getById(@PathVariable Long id);
          
              /**
               * 用户信息分页
               *
               * @param page     当前页
               * @param pageSize 每页显示条数
               * @param username 用户名
               * @return 返回分页用户信息
               */
              @GetMapping("/page")
              ResultBean<Page<User>> page(@RequestParam int page, @RequestParam int pageSize, @RequestParam String username);
          
              /**
               * 获取用户记录数
               *
               * @return 返回记录数
               */
              @GetMapping("/count")
              ResultBean<Integer> count();
          
          }
          
        2. @FeignClient(value = "nacos-feign-user-service", path = "/users")
          1. 声明为feign的客户端,服务名称是nacos-feign-user-service,请求url前缀统一为/users,
        3. Feign客户端主要是基于SpringMVC的注解来声明远程调用的信息
    2. 新建并修改maven模块nacos-feign-user-service
      1. 在maven的pom文件中添加user-feign-api依赖,根据maven的依赖传递将同时也会引入了openfeign依赖
        1.         <!--引入user-feign的统一api-->
                  <dependency>
                      <groupId>com.app</groupId>
                      <artifactId>user-feign-api</artifactId>
                      <version>1.0.0</version>
                  </dependency>
      2. 在模块中新建UserController类,并实现接口UserApi,其他相关代码略
        1. package com.app.user.controller;
          
          
          import cn.hutool.core.util.StrUtil;
          import com.app.user.api.UserApi;
          import com.app.user.common.ResultBean;
          import com.app.user.pojo.User;
          import com.app.user.service.UserService;
          import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
          import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
          import lombok.RequiredArgsConstructor;
          import lombok.extern.slf4j.Slf4j;
          import org.springframework.web.bind.annotation.*;
          
          /**
           * 用户控制器
           *
           * @author Administrator
           */
          @RestController
          @RequestMapping("/users")
          @Slf4j
          @RequiredArgsConstructor
          public class UserController implements UserApi {
          
              /**
               * 结合@RequiredArgsConstructor进行构造器注入
               */
              private final UserService userService;
          
              /**
               * 新增用户
               *
               * @param user 用户信息
               * @return 用户信息
               */
              @Override
              public ResultBean<User> save(@RequestBody User user) {
                  log.info("新增用户,用户信息:{}", user.toString());
                  userService.save(user);
                  return ResultBean.success(user);
              }
          
              /**
               * 根据id修改用户信息
               *
               * @param user 用户信息
               * @return 修改提示信息
               */
              @Override
              public ResultBean<String> update(@RequestBody User user) {
                  log.info(user.toString());
                  userService.updateById(user);
                  return ResultBean.success("用户信息修改成功");
              }
          
              /**
               * 根据id查询用户信息
               *
               * @param id 用户id
               * @return 用户信息
               */
              @Override
              public ResultBean<User> getById(@PathVariable Long id) {
                  log.info("根据id查询用户信息...");
                  User user = userService.getById(id);
                  if (user != null) {
                      return ResultBean.success(user);
                  }
                  return ResultBean.error("没有查询到对应用户信息");
              }
          
              /**
               * 用户信息分页
               *
               * @param page     当前页
               * @param pageSize 每页显示条数
               * @param username 用户名
               * @return 返回分页用户信息
               */
              @Override
              public ResultBean<Page<User>> page(@RequestParam int page, @RequestParam int pageSize, @RequestParam String username) {
                  log.info("page = {},pageSize = {},username = {}", page, pageSize, username);
                  // 1、构造简单分页模型
                  Page<User> pageInfo = new Page<>(page, pageSize);
                  // 2、构造条件构造器
                  LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
                  // 3、添加用户名过滤条件,使用模糊匹配,不为空时才生效
                  queryWrapper.like(StrUtil.isNotEmpty(username), User::getUsername, username);
                  // 4、添加排序条件
                  queryWrapper.orderByDesc(User::getId);
                  // 5、执行查询,查询的结果将会直接存在于pageInfo对象中
                  userService.page(pageInfo, queryWrapper);
                  return ResultBean.success(pageInfo);
              }
          
              /**
               * 获取用户记录数
               *
               * @return 返回记录数
               */
              @Override
              public ResultBean<Integer> count() {
                  log.info("计算用户数目...");
                  int i = userService.countNum();
                  return ResultBean.success(i);
              }
          
          }
          
    3. 新建maven模块nacos-feign-order-service,当前的模块将会通过feign远程调用nacos-feign-user-service服务获取信息
      1. 在maven的pom文件中添加user-feign-api依赖,根据maven的依赖传递将同时也会引入了openfeign依赖
        1.         <!--引入user-feign的统一api-->
                  <dependency>
                      <groupId>com.app</groupId>
                      <artifactId>user-feign-api</artifactId>
                      <version>1.0.0</version>
                  </dependency>
      2. 在OrderController注入UserApi接口,并在方法使用处进行user远程调用,其他类信息略
        1. 
          /**
           * 订单控制器
           *
           * @author Administrator
           */
          @RestController
          @RequestMapping("/orders")
          @Slf4j
          @RequiredArgsConstructor
          @RefreshScope
          public class OrderController implements OrderApi {
          
              /**
               * 结合@RequiredArgsConstructor进行构造器注入
               */
              private final OrderService orderService;
              /**
               * 注入user-feign的统一api的bean,以此可以进行声明式的http的远程调用
               */
              private final UserApi userApi;
          
              /**
               * 根据id查询订单信息
               *
               * @param id 订单id
               * @return 订单信息
               */
              @Override
              public ResultBean<OrderVo> getById(@PathVariable Long id) {
                  log.info("根据id查询订单信息...");
                  Order order = orderService.getById(id);
                  if (order != null) {
                      OrderVo orderVo = new OrderVo();
                      BeanUtil.copyProperties(order, orderVo);
                      // 远程查找用户服务获取用户名信息
                      // 发起feign的远程调用
                      com.app.user.common.ResultBean<User> userResult = userApi.getById(order.getUserId());
                      User user = userResult.getData();
                      if (user != null) {
                          orderVo.setUsername(user.getUsername());
                      }
                      return ResultBean.success(orderVo);
                  }
                  return ResultBean.error("没有查询到对应订单信息");
              }
          
          }
          
    4. 在OrderApplication添加注解@EnableFeignClients,并设置注解扫描包
      1. package com.app.order;
        
        import org.springframework.boot.SpringApplication;
        import org.springframework.boot.autoconfigure.SpringBootApplication;
        import org.springframework.cloud.openfeign.EnableFeignClients;
        
        /**
         * spring boot启动类
         *
         * @author Administrator
         */
        @SpringBootApplication
        @EnableFeignClients(basePackages = "com.app.user.api")
        public class OrderApplication {
            public static void main(String[] args) {
                SpringApplication.run(OrderApplication.class, args);
            }
        }
        
  3. 注意
    1. controller在继承feign的接口后,其参数列表中的注解映射并不会继承,因此Controller中必须再次声明方法、参数列表、注解

    2. 在引用@FeignClient的接口进行注入到使用的类时,需要在@EnableFeignClients进行包扫描,其中有下列方式可以将指定FeignClient加载
      1. 指定Feign应该扫描的包
        1. @EnableFeignClients(basePackages = "com.app.user.api")
      2. 指定需要加载的Client接口
        1. @EnableFeignClients(clients = {UserApi.class})
    3. 当使用Feign时,如果发送的是get请求,那么必须需要在请求参数前加上@RequestParam注解修饰,Controller里面可以不加该注解修饰

文章来源:https://blog.csdn.net/weixin_41926152/article/details/135031965
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。