目录
ribbon底层封装了RestTemplate进行Rest api远程调用
RestTemplate是springboot提供的远程调用工具
常用的方法:
该方法是getForEntity方法的进一步封装,通过HttpMessageConverterExtractor对HTTP的请求响应体body内容进行对象转换,实现请求直接返回包装好的对象内容。有三个重载。
getForObject(String url,Class responseType,Object ...urlVariables);
url参数为指定访问的地址如果其中有传递的参数,使用{1},{2}这种类型的占位符表示,responseType是参数返回结果的类型,urlVariables是前面url占位符对应的参数。
getForObject(String url,Class responseType,Map urlVariables);
前两个参数与前一致,最后一个参数使用Map封装替换url中出现的占位符。
getForObject(String url,Class responseType);
没有需要传递的参数。
用于发送post请求,与get类似
也提供了三种重载:
postForObject(String url,Class responseType,Object ...urlVariables);
postForObject(String url,Class responseType,Map urlVariables);
postForObject(String url,Class responseType);
这里先不使用Ribbon,先单独使用RestTemplate进行远程调用
当前是一个商品信息,用户和订单三者之间的服务,并且使用Eureka集群提供服务发现与注册
结构及功能为:
其中
item-service 用于商品服务,其中有获取商品信息和减少库存的方法
user-service 用于用户服务,其中有获取用户信息和增加用户积分的功能
order-service 用于订单服务,其中有获取订单和添加订单的功能
现在需要使用RestTemplate进行远程调用这三个服务
由于Eureka-client中包含ribbon依赖,所以只需添加eureka-client依赖即可
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
服务名称为ribbon,使用3001端口,并且注册到两台eureka服务器中
spring: application: name: ribbon server: port: 3001 eureka: client: service-url: defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka
添加RestTemplate实例
package cn.tedu.sp06; .... @EnableDiscoveryClient @SpringBootApplication public class Sp06RibbonApplication { //创建 RestTemplate 实例,并存入 spring 容器 @Bean public RestTemplate getRestTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(Sp06RibbonApplication.class, args); } }
package cn.tedu.sp06.controller; ... @RestController public class RibbonController { @Autowired private RestTemplate rt; @GetMapping("/item-service/{orderId}") public JsonResult<List<Item>> getItems(@PathVariable String orderId) { //向指定微服务地址发送 get 请求,并获得该服务的返回结果 //{1} 占位符,用 orderId 填充 return rt.getForObject("http://localhost:8001/{1}", JsonResult.class, orderId); } @PostMapping("/item-service/decreaseNumber") public JsonResult decreaseNumber(@RequestBody List<Item> items) { //发送 post 请求 return rt.postForObject("http://localhost:8001/decreaseNumber", items, JsonResult.class); } // @GetMapping("/user-service/{userId}") public JsonResult<User> getUser(@PathVariable Integer userId) { return rt.getForObject("http://localhost:8101/{1}", JsonResult.class, userId); } @GetMapping("/user-service/{userId}/score") public JsonResult addScore( @PathVariable Integer userId, Integer score) { return rt.getForObject("http://localhost:8101/{1}/score?score={2}", JsonResult.class, userId, score); } // @GetMapping("/order-service/{orderId}") public JsonResult<Order> getOrder(@PathVariable String orderId) { return rt.getForObject("http://localhost:8201/{1}", JsonResult.class, orderId); } @GetMapping("/order-service") public JsonResult addOrder() { return rt.getForObject("http://localhost:8201/", JsonResult.class); } }
注意:
1、可以看出,用户发送请求首先到RibbonController然后通过这里转发到对应的服务路径,实现远程调用。
2、携带参数的GET请求,会使用{1}表示占位符进行转发。
根据RibbonController的路径发送请求
http://localhost:3001/item-service/35
使用postman发送
http://localhost:3001/item-service/decreaseNumber
[{"id":1,"name":"abc","number":100},{"id":2,"name":"def","number":200}]
http://localhost:3001/user-service/10
http://localhost:3001/user-service/10/score?score=100
http://localhost:3001/order-service/20
http://localhost:3001/order-service
浏览器发送请求先到ribbon服务器的RibbonController,之后通过RestTemplate的getForObject或postForObject方法分别远程调用到item-service、user-service、ordder-service。