三、OpenFeign服务间调用之参数传递
1. 微服务架构服务间通讯方式
  • http协议
  • springcloud两种方式: 1. RestTemplate + Ribbon 2. OpenFeign(推荐)
2. 服务间通信参数传递

参数传递类型

  • 零散类型
  • 对象类型
  • 数组或集合类型参数

零散类型参数传递

QueryString方式传递参数:?name=zhangsan&age=20

  • 被调用Share服务定义一个接受零散参数类型的接口QueryString
@RestController
@RequestMapping("shareConApi")
public class ShareController {

    private static Logger log = LoggerFactory.getLogger(ShareController.class);

    /**
     * 定义一个接受零散参数类型的接口QueryString
     */
    @GetMapping("testQueryString")
    public String testQueryString(String name, Integer age) {
        log.info("testQueryString name={} age={}", name, age);
        return "testQueryString Ok";
    }

}
  • 调用方Friend开发需要调用的服务客户端接口
/**
 * 调用Share服务的接口
 */
@FeignClient(value = "SHARE") // value=调用服务的ID
public interface ShareClients {
    /**
     * 声明调用Share服务中 零散参数传递的接口
     */
    @GetMapping("shareConApi/testQueryString")
    public String invokeQueryString(String name, Integer age);
}
  • 调用方Friend调用客户端接口
@RestController
@RequestMapping("friendConApi")
public class FriendController {

    private static Logger log = LoggerFactory.getLogger(FriendController.class);
    @Resource
    private ShareClients shareClients;

    @GetMapping("testInvokeQueryString")
    public String testInvokeQueryString() {
        String result = shareClients.invokeQueryString("zhangsan", 20);
        log.info("testInvokeQueryString result={}", result);
        return "testInvokeQueryString Ok";
    }
}
  • 启动测试
    在这里插入图片描述
    此时调用方Friend抛出异常,ShareClients…invokeQueryString() Method has too many Body parameters

原因:ShareClients是一个OpenFeign接口,是一个伪HttpClient,底层在请求testQueryString地址的时候,不知道参数该如何组织(意思就是零散类型参数传递方式有’?name=zhangsan&age=20’和’/zhangsan/20’两种方式)
但是当你只有一个参数的时候,服务接口是可以调用的(很神奇…当只有一个参数的时候,默认是?name=zhangsan这种方式传递参数)
解决:在OpenFeign接口申明中必须给参数加入注解,明确告诉OpenFeign参数组织方式@RequestParam或@PathVariable

/**
     * 声明调用Share服务中 零散参数传递的接口
     * testQueryString?name=zhangsan&age=20
     */
    @GetMapping("shareConApi/testQueryString")
    public String invokeQueryString(@RequestParam("name") String name, @RequestParam("age") Integer age);

在这里插入图片描述
PathVariable方式传递参数:/zhangsan/20

  • 被调用Share服务定义一个接受零散参数类型的接口 PathVariable
@RestController
@RequestMapping("shareConApi")
public class ShareController {

    private static Logger log = LoggerFactory.getLogger(ShareController.class);

    /**
     * 定义一个接受零散参数类型的接口PathVariable
     * @param name
     * @return
     */
    @GetMapping("testPathVariable/{name}/{age}")
    public String testPathVariable(@PathVariable("name") String name, @PathVariable("age") Integer age) {
        log.info("testPathVariable name={} age={}", name, age);
        return "testPathVariable Ok";
    }
}
  • 调用方Friend开发需要调用的服务客户端接口
/**
 * 调用Share服务的接口
 */
@FeignClient(value = "SHARE") // value=调用服务的ID
public interface ShareClients {
    /**
     * 声明调用Share服务中 零散参数传递的接口
     * testQueryString/zhangsan/20
     */
    @GetMapping("shareConApi/testPathVariable/{name}/{age}")
    public String invokePathVariable(@PathVariable("name") String name, @PathVariable("age") Integer age);
}
  • 调用方Friend调用客户端接口
@RestController
@RequestMapping("friendConApi")
public class FriendController {

    private static Logger log = LoggerFactory.getLogger(FriendController.class);
    @Resource
    private ShareClients shareClients;

    @GetMapping("testInvokePathVariable")
    public String testInvokePathVariable() {
        String result = shareClients.invokePathVariable("zhangsan", 20);
        log.info("testInvokePathVariable result={}", result);
        return "testInvokePathVariable Ok";
    }

}
  • 启动测试
    在这里插入图片描述

对象类型参数传递

对象方式传递参数:entity

  • 被调用Share服务定义一个接受对象类型的接口RequestBody
@RestController
@RequestMapping("shareConApi")
public class ShareController {

    private static Logger log = LoggerFactory.getLogger(ShareController.class);
    
    /**
     * 定义一个接受对象类型的接口
     */
    @PostMapping("testRequestBody")
    public String testRequestBody(@RequestBody MemberEntity memberEntity) {
        log.info("testRequestBody memberEntity={}", memberEntity);
        return "testRequestBody Ok";
    }

}
  • 调用方Friend开发需要调用的服务客户端接口
/**
 * 调用Share服务的接口
 */
@FeignClient(value = "SHARE") // value=调用服务的ID
public interface ShareClients {
    /**
     * 声明调用Share服务中 对象参数传递的接口
     * @param memberEntity
     * @return
     */
    @PostMapping("shareConApi/testRequestBody")
    public String invokeRequestBody(@RequestBody MemberEntity memberEntity);
}
  • 调用方Friend调用客户端接口
@RestController
@RequestMapping("friendConApi")
public class FriendController {

    private static Logger log = LoggerFactory.getLogger(FriendController.class);
    @Resource
    private ShareClients shareClients;

    @GetMapping("testInvokeRequestBody")
    public String testInvokeRequestBody() {
        String result = shareClients.invokeRequestBody(new MemberEntity(1L, "zhangsan", 20, new Date()));
        log.info("testInvokeRequestBody result={}", result);
        return "testInvokeRequestBody Ok";
    }

}
  • 启动测试
    在这里插入图片描述
    在这里插入图片描述

数组和集合类型参数传递

数组方式传递参数:String[]

  • 被调用Share服务定义一个接受数组类型的接口 String[]
@RestController
@RequestMapping("shareConApi")
public class ShareController {
    private static Logger log = LoggerFactory.getLogger(ShareController.class);
    /**
     * 定义一个接受数组类型的接口
     */
    @GetMapping("testArray")
    public String testArray(String[] ids) {
        for (String id : ids) {
            log.info("testArray ids={}", id);
        }
        return "testArray Ok";
    }
}
  • 调用方Friend开发需要调用的服务客户端接口
/**
 * 调用Share服务的接口
 */
@FeignClient(value = "SHARE") // value=调用服务的ID
public interface ShareClients {
    /**
     * 声明调用Share服务中 数组参数传递的接口
     * testArray?ids=1&ids=2&ids=3
     */
    @GetMapping("shareConApi/testArray")
    public String invokeArray(@RequestParam("ids") String[] ids);
}
  • 调用方Friend调用客户端接口
@RestController
@RequestMapping("friendConApi")
public class FriendController {

    private static Logger log = LoggerFactory.getLogger(FriendController.class);
    @Resource
    private ShareClients shareClients;

    @GetMapping("testInvokeArray")
    public String testInvokeArray() {
        String result = shareClients.invokeArray(new String[]{"1", "2", "3"});
        log.info("testInvokeArray result={}", result);
        return "testInvokeArray Ok";
    }
}
  • 启动测试
    在这里插入图片描述
    在这里插入图片描述

集合方式传递参数:List

  • 被调用Share服务定义一个接受集合类型的接口 List
    springmvc不能直接接受集合类型参数,必须将集合类型参数放入对象中,使用对象的方式传递参数才可接收

OO:oriented object 面向对象
VO:value object 值对象,用来传递数据对象
DTO:date transfer object 数据传输对象

public class ListVo {
    private List<String> ids;
    public List<String> getIds() {
        return ids;
    }
    public void setIds(List<String> ids) {
        this.ids = ids;
    }
}
@RestController
@RequestMapping("shareConApi")
public class ShareController {

    private static Logger log = LoggerFactory.getLogger(ShareController.class);
    
    /**
     * 定义一个接受集合List类型的接口
     */
    @GetMapping("testList")
    public String testList(ListVo listVo) {
        listVo.getIds().forEach(id -> log.info("testList id={}", id.toString()));
        return "testList Ok";
    }
}
  • 调用方Friend开发需要调用的服务客户端接口
/**
 * 调用Share服务的接口
 */
@FeignClient(value = "SHARE") // value=调用服务的ID
public interface ShareClients {
    /**
     * 声明调用Share服务中 集合list参数传递的接口
     */
    @GetMapping("shareConApi/testList")
    public String invokeList(@RequestParam("ids") String[] ids);
}
  • 调用方Friend调用客户端接口
@RestController
@RequestMapping("friendConApi")
public class FriendController {

    private static Logger log = LoggerFactory.getLogger(FriendController.class);
    @Resource
    private ShareClients shareClients;

    @GetMapping("testInvokeList")
    public String testInvokeList() {
        String result = shareClients.invokeList(new String[]{"1", "2", "3"});
        log.info("testInvokeList result={}", result);
        return "testInvokeList Ok";
    }
}
  • 启动测试
    在这里插入图片描述
    在这里插入图片描述
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐