springboot-微服务feign 使用

基于Feign实现服务调用

Feign是什么

    feign是Spring Cloud提供的一个声明式的伪Http客户端,它使得调用远程服务就像调用本地服务一样。

    nacos很好地兼容了feign,feign默认集成了ribbon。所以在nacos下使用feign默认就实现了负载均衡的效果。

    Feign是一个声明式的伪Http客户端,它使得写Http客户端变得更简单。使用Feign,只需要创建一个接口并注解。它具有可插拔的注解特性,可使用Feign 注解和JAX-RS注解。Feign支持可插拔的编码器和解码器。Feign默认集成了Ribbon,并和Eureka结合,默认实现了负载均衡的效果

    Feign 采用的是基于接口的注解

    Feign 整合了ribbon,具有负载均衡的能力
    整合了Hystrix(SpringCloud官方那一套),具有熔断的能力

Feign的使用

首先,在orders中引入feign依赖。

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

/// 高版本需要添加依赖  loadbalance
<!--解决:Did you forget to include spring-cloud-starter-loadbalancer?-->
<dependency>    
<groupId>org.springframework.cloud</groupId>    
<artifactId>spring-cloud-loadbalancer</artifactId>    
<version>xxx</version>
</dependency>

然后,在主启动类上添加@EnableFeignClients注解

@SpringBootApplication
@MapperScan("com.example.orders.mapper")
@EnableDiscoveryClient
@EnableFeignClients
public class OrdersAppliaction {
    public static void main(String[] args) {
        SpringApplication.run(OrdersAppliaction.class,args);
    }

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

接着,在order这一方,创建一个IProductService接口,并使用Feign实现微服务调用

@FeignClient("micro-product") //此处名称必须为提供者的实例名称
///  这里若是没有集成springcloud 也可以写 固定的地址
///  如  @FeignClient(name = "order" , url = "localhost:8081/product")
public interface IProductService {
    @GetMapping("/product/{pid}")
    ResultVO findByPid(@PathVariable("pid") Integer pid);

    @GetMapping("/product/testLoadBalance")
    ResultVO testLoadBalance();
}

最后,修改OrderController代码,并测试。注意,这里使用IProductService替换掉了RestTemplate和DiscoveryClient。

RestController
@RequestMapping("/orders")
@Slf4j
public class OrdersController {
    @Resource
    private IProductService productService;
    @Resource
    private IOrdersService ordersService;

    @GetMapping("/{pid}/{count}")
    public ResultVO addOrder(@PathVariable Integer pid,@PathVariable Integer count){
        ResultVO resultVO = productService.findByPid(pid);
        Map map = (Map)resultVO.getE();
        Orders orders = new Orders();
        BeanUtil.fillBeanWithMap(map, orders, true);
        orders.setCount(count);
        orders.setUname("向来痴");
        log.info("填充完毕{}", orders);

        ResultVO<Orders> resultOrderVO = null;
        if(ordersService.save(orders))
            resultOrderVO = new ResultVO<Orders>(Constants.OPEN_SUCCESS, "订单插入成功",orders);
        else
            resultOrderVO = new ResultVO<Orders>(Constants.OPEN_FAILURE, "订单插入失败",orders);
        return resultOrderVO;
    }

    @GetMapping("/testLoadBalance")
    public ResultVO testLoadBalance() {
        ResultVO resultVO = productService.testLoadBalance();
        return resultVO;
    }
}

访问地址:

http://127.0.0.1:9000/orders/testLoadBalance

http://127.0.0.1:9000/orders/1/5

坑:

Request method 'POST' not supported

如果feign代理的是get请求,则每个参数必须带上注解,否则会报post not support!

1.首先保障Client接口和控制层接口的请求方式一致

2.如果有参数,必须指定@RequestParam

3:版本降级
Pom.xml
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>
提供者
    @GetMapping("/findById")
    public Userinfo findById(@RequestBody Integer uid){
        return userinfoMapper.selectByPrimaryKey(uid);
    }
消费者
    @GetMapping("/findById")
    public Userinfo findById(Integer uid){
        System.out.println("into "+uid);
        return userinfoService.findById(uid);
    }
feign接口
    @FeignClient("mircoprovider")
    public interface UserinfoService {
        @GetMapping("findById")
        public Userinfo findById(@RequestBody Integer uid);
    }
打完收工    

OpenFeign请求传递对象

OpenFeign在传递参数为对象类型是为空
解决的方法很简单,在参数前面加上@RequestBody即可

回顾 @RequestBody
@RequestBody注解常用来处理content-type不是默认的application/x-www-form-urlcoded编码的内容,比如说:application/json或者是application/xml等。一般情况下来说常用其来处理application/json类型。

消费者
    @GetMapping("/save")
    public String save(Userinfo info){
        System.out.println("into userinfo is "+info);
        return userinfoService.save(info);
    }
feign接口
    @PostMapping("/save")
    public String save(@RequestBody Userinfo info);
    
提供者
    @PostMapping("/save")
    public String save(@RequestBody Userinfo info){
        System.out.println("插入对象"+info);
        userinfoMapper.insert(info);
        return "ok";
    }

当然,还有其它几种姿势

feign接口
    @RequestMapping(value = "/user", method = RequestMethod.POST, consumes = "application/json")
    String getUserId(@RequestBody User user);
    
    1、consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
    2、produces: 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;
    3、或者 = MediaType.APPLICATION_JSON_VALUE
    4、正常来说,在FeignClient的接口中,也不需要在参数上注解@RequestBody ,只需要在实现类上添加@RequestBody 注解即可。
提供者
    @PostMapping("/save")
    public String save(@RequestBody Userinfo info){
        System.out.println("插入对象"+info);
        userinfoMapper.insert(info);
        return "ok";
    }   
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容