ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

OpenFeign组件服务间调用时参数传递

2021-07-31 16:59:34  阅读:263  来源: 互联网

标签:String OpenFeign age ids 参数传递 test 组件 public name


OpenFeign组件

微服务间通信的方式??

服务间通信的方式主要有以下两种:


1.基于Http应用层协议

特点

1.使用http rest方式,使用json作为数据交换的

2.效率较低,但是耦合度低(耦合度低意味着如果不同服务使用不同的技术框架进行开发后,进行通信的成本低)

典型的实现
1.RestTemplate
缺点:
1.服务调用使路径写死,耦合度高

2.要想实现负载均衡,必须得结合Ribbon组件,造成冗余代码


2.OpenFeign(推荐)
特点:
1.OpenFeign组件是spring团队基于netflix的Feign组件进行封装和扩展形成的自己的一个项目,它是一个伪HttpClient;

OpenFeign是一个伪HTTP客户端,底层还是RestTemplate,是对RestTemplate的封装

2.OpenFeign支持可插拔的编码器和解码器

比如帮我们默认实现json和其他数据类型的装换

3.OpenFeign默认集成了Ribbon

默认实现了负载均衡的效果,不需要我们再像RestTemlate那样,利用ribbon编写实现负载均衡的相关代码;
并且springcloud为feign添加了springmvc注解的支持。

4.使用方便,代码量少

使用时只需要添加几个注解,编写一个接口类即可,耦合度低


2.基于RPC传输层协议

特点

1.使用的是传输层的协议,以二进制方式传递数据

2.效率高,但是耦合度高,如果不同服务使用不同的技术框架进行开发后,进行通信的成本高

典型的RPC框架:Dubbo

总结:`在springcloud中服务间调用方式主要是使用 http restful方式进行服务间调用

OpenFeign服务间通信时参数传递

1.基本数据类型

GoodsClient接口

@FeignClient(value = "GOODS")
public interface GoodsClient {

    /*
    * 注意:这里的方法需要保证返回类型,形参,请求路径一致
    * 方法名可以与被调用的服务名不同
    *
    * feign默认给我们实现了负载均衡!!
    * */
    @GetMapping("/test")
    String test(String name,Integer age);
}

商品服务controller

 	@GetMapping("/test")
    public String test(String name,Integer age){
        log.info("name:{},age:{}",name,age);
        return name + age;
    }

CategoryController调用商品服务的test方法

@GetMapping
    public String testService(){
        String test = goodsClient.test("jw", 20);
        return test;
    }

启动报错显示太多参数

Caused by: java.lang.IllegalStateException: Method has too many Body parameters: public abstract java.lang.String com.jw.feignclient.GoodsClient.test(java.lang.String,java.lang.Integer)

原因是:

我们知道通过QueryString传递有两种方式,一种是
/test?name=jw&age=20的形式
另一种是rest的方式,直接把参数写在路径中
/test/jw/20

由于OpenFeign是伪客户端,底层在调用服务时还是基于RestTemplate,当我们通过GoodsClient调用test服务是,GoodsClient会把接收的参数传递给RestTemplate进行封装;此时RestTemplate不知道该基于哪种方式进行封装,所以会报错;

如果我们只写一个参数,那么默认就是?name=xx的形式
如果有多个参数就需要我们用注解显示声明

@RequestParams
如果是想以/test?name=xxx&age=xxx 的形式传递参数,那么使@RequestParams;

@FeignClient(value = "GOODS")
public interface GoodsClient {

    /*
    * 注意:这里的方法需要保证返回类型,形参,请求路径一致
    * 方法名可以与被调用的服务名不同
    *
    * feign默认给我们实现了负载均衡!!
    * */
   
    @GetMapping("/test")
    String test(@RequestParam String name,@RequestParam Integer age);
}

注意:如果我们@RequestParam赋值,被调用方需要一致

@GetMapping("/test")
String test(@RequestParam("aa") String name,@RequestParam("bb") Integer age);

//商品服务
@GetMapping("/test")
public String test(String aa,Integer bb){
     	log.info("name:{},age:{}",aa,bb);
       return aa + bb;
}

@GetMapping("/test")
public String test(@RequestParam("aa") String name,@RequestParam("bb") Integer age){
     	log.info("name:{},age:{}",name,age);
       return name + age;
}

@PathVariable
如果是想以/test/jw/20形式传递参数,那么使用@PathVariable

@FeignClient(value = "GOODS")
public interface GoodsClient {

    /*
    * 注意:这里的方法需要保证返回类型,形参,请求路径一致
    * 方法名可以与被调用的服务名不同
    *
    * feign默认给我们实现了负载均衡!!
    * */

    @GetMapping("/test1/{name}/{age}")
    String test1(@PathVariable("name") String name, @PathVariable("age") Integer age);
}

	//商品服务controller
	@GetMapping("/test1/{name}/{age}")
    public String test1(@PathVariable("name")String name,@PathVariable("age") Integer age){
        log.info("name:{},age:{}",name,age);
        return name+age;
    }
    
  	//**CategoryController调用商品服务的test1方法**
	 @GetMapping
    public String testService(){
        String test = goodsClient.test1("jw", 20);
        return test;
    }

2.传递对象类型

使用@RequestBody注解会把对象以aplication/json的形式传参,被调用的服务也需要加上@RequestBody该注解,把收到的json转成对应的对象

	//categoryController
	@GetMapping
    public String testService(){
        //String test = goodsClient.test1("jw", 20);
        goodsClient.save(new Goods(1,"aa",22.12,new Date()));
        return null;
    }

    //接口
	@FeignClient(value = "GOODS")
	public interface GoodsClient {
    /*
    * 注意:这里的方法需要保证返回类型,形参,请求路径一致
    * 方法名可以与被调用的服务名不同
    *
    * feign默认给我们实现了负载均衡!!
    * */
    @PostMapping("/savegoods")
    void save(@RequestBody Goods goods);
	}
	
 	//GoodsController
	@PostMapping("/savegoods")
    public void save(@RequestBody Goods goods){
        log.info("goods:{}",goods);
    }

3.传递数组和集合类型

**数组类型使用@RequestParam会把ids数组拼装成
/test3/?ids=1&ids=2&ids=3的形式

	@FeignClient(value = "GOODS")
	public interface GoodsClient {
    @GetMapping("/test3")
    void test3(@RequestParam("ids") String[] ids);
	}
	==================================
	  //goodsController
	@GetMapping("/test3")
    public void test3( String[] ids){
        log.info("ids:{}",ids);
    }	

集合类型
springMVC中get方式是不能用集合作参数的
比如以/test4/?ids=1&ids=2&ids=3,接收不到

	//不行
   @GetMapping("/test4")
   public void test4(ArrayList<String> ids){
       
   }
 

如果硬要接收集合,那么需要把集合作为类的属性

	@GetMapping("/test3")
    public void test3( GoodsVO vo){
        log.info("ids:{}",ids);
    }	
	
	class ProductVO{
    private ArrayList<String> ids;

    public ArrayList<String> getIds() {
        return ids;
    }

    public void setIds(ArrayList<String> ids) {
        this.ids = ids;
    }
}

此时在FeignClient中还是同数组一样,因为@RequestParam会把接收到的ids拼接成/test4/?ids=1&ids=2&ids=3,在GoodController接收时,就会去Goodvo中找到ids进行赋值

   @FeignClient(value = "GOODS")
   public interface GoodsClient {
   @GetMapping("/test4")
   void test3(@RequestParam("ids") String[] ids);
   }

注意:这里是GET方式需要接收一个List集合
如果是POST方式直接加上@RequestBody注解以json方式传递即可

标签:String,OpenFeign,age,ids,参数传递,test,组件,public,name
来源: https://blog.csdn.net/weixin_46273997/article/details/119271031

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有