SpringCloud+SpringBoot 项目搭建 (五) Feign

本篇文章接上一篇:SpringCloud+SpringBoot 项目搭建 (四) RockerMq

1.简介

Feign:是一个声明式WebService客户端。使用Feign能让编写Web Service客户端更加简单,它的使用方法就是定义一个接口,然后在上面添加注解,同时也支持JAX-RS标准的注解。

2.使用 feign

使用之前先学习下feignClient的注解

  • name:指定FeignClient的名称,如果项目使用了Ribbon,name属性会作为微服务的名称,用于服务发现
  • url: url一般用于调试,可以手动指定@FeignClient调用的地址
  • decode404:当发生http 404错误时,如果该字段位true,会调用decoder进行解码,否则抛出FeignException
  • configuration: Feign配置类,可以自定义Feign的Encoder、Decoder、LogLevel、Contract
  • fallback: 定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口
  • fallbackFactory: 工厂类,用于生成fallback类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码
  • path: 定义当前FeignClient的统一前缀

引用maven和配置

		<dependency>
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-starter-openfeign</artifactId>
             <version>2.1.3.RELEASE</version>
         </dependency>

在core里面编写一个最基本的feign配置信息

@Configuration
public class FeignConfiguration {
    @Bean
    public Contract feignContract() {
        return new SpringMvcContract();
    }
}

创建一个feignClient

@FeignClient(value = "productcenter",configuration = FeignConfiguration.class,fallback = ProductSearchFeignResilience.class)
public interface ProductSearchFeigApi {
    @RequestMapping("/api/product/searchProductId")
    public ApiResponse<ProductDto> searchId(@RequestParam("productId") String id);
}

创建feignClient实现方法

@RefreshScope
@RestController
public class ProductSearchFignClient implements ProductSearchFeigApi {
    @Resource
    ProductService productService;//商品模块中自己的服务
    @Override
    public ApiResponse<ProductDto> searchId(@RequestParam("productId") String id) {
        Product product = productService.getById(id);
        ProductDto productDto = null;
        if (product!=null) {
            productDto = new ProductDto();
            BeanUtils.copyProperties(product, productDto);
        }
        return ApiResponse.success(productDto);
    }
}

调用方法

@Log4j2
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
    @Resource
    OrderMapper orderMapper;
    @Resource
    private DefaultMQProducer defaultMQProducer;
    @Resource
    private ProductService productService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Order create(String productId,Integer number, Long userId) {
        //创建订单
       // TODO ... 参考上一期代码
        //扣除商品库存
       this.reduceProductStock(productId,number);
        //模拟发送短信
	    //TODO ... 参考上一期代码
        return insert>0?order:null;
    }
    
    private void reduceProductStock(String productId, Integer number){
        ProductDto productDto = productService.searchId(productId);
        productDto.setChangeStock(0-number);
        productService.updateProductStockById(productDto);
    }
}

@Log4j2
@Service
public class ProductServiceImpl implements ProductService {
    @Resource
    ProductSearchFeignApi productSearchFeignApi;//调用core里面的feignClient
    @Override
    public int updateProductStockById(ProductDto productDto) {
        return 0;
    }
    @Override
    public ProductDto searchId(String productId) {
        ApiResponse<ProductDto> apiResponse = productSearchFeignApi.searchId(productId);
        if(apiResponse==null){
            throw new MyProductServiceBusinessException("获取商品信息失败!");
        }
        if (apiResponse.error()) {
            throw new MyProductServiceBusinessException("服务器内部错误", productId);
        }
        return apiResponse.getResult();
    }
}

添加启动注解

/**订单模块*/
@MapperScan("com.dongyue.ordercenter.mapper")
@SpringBootApplication
@EnableEurekaClient
@ComponentScan(basePackages={"com.dongyue"})
@EnableFeignClients(basePackages = "com.dongyue")
public class OrdercenterApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrdercenterApplication.class, args);
    }
}

/**商品模块*/
@SpringBootApplication
@ComponentScan(basePackages={"com.dongyue"})
@EnableFeignClients(basePackages = {"com.dongyue"})
@EnableEurekaClient
@MapperScan("com.dongyue.productcenter.mapper")
public class ProductcenterApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProductcenterApplication.class, args);
    }
}

  • 坑点1 FeignClient中value里面的值一定要与要访问模块中在中心注册中的名称一样或者配置url
  • 坑点2 FeignClient创建的参数信息一定要与实现方法中的参数信息一致
  • 坑点3 如果跟启动没有在同一个包名下面,扫描需要添加路径,否则找不到资源
  • 坑点4 如果有可能出现服务被多次消费的情况别忘记加上配置:spring.main.allow-bean-definition-overriding=true
    至此一个最基本的feign就集成完毕
posted @ 2021-04-16 20:10  rr完美'诺言  阅读(20)  评论(0编辑  收藏  举报  来源