远程调用之RestTemplate与Feign使用历程
前言
记录ratetemplate的调用原理及在微服务中的使用原理。
一、RestTemplate详解
现如今的 IT 项目,由服务端向外发起网络请求的场景,基本上处处可见!
传统情况下,在服务端代码里访问 http 服务时,一般会使用 JDK 的 HttpURLConnection 或者 Apache 的 HttpClient,不过这种方法使用起来太过繁琐,而且 api 使用起来非常的复杂,还得操心资源回收。
以下载文件为例,通过 Apache 的 HttpClient方式进行下载文件,会很复杂。
其实Spring已经为我们提供了一种简单便捷的模板类来进行操作,它就是RestTemplate。
RestTemplate是一个执行HTTP请求的同步阻塞式工具类,它仅仅只是在 HTTP 客户端库(例如 JDK HttpURLConnection,Apache HttpComponents,okHttp 等)基础上,封装了更加简单易用的模板方法 API,方便程序员利用已提供的模板方法发起网络请求和处理,能很大程度上提升我们的开发效率。
可以通过RestTemplate进行不同项目间远程调用,也可以在微服务中用来进行服务间的调用。
参看链接:https://blog.csdn.net/u012060033/article/details/123352747
二、RestTemplate使用详解
参看链接:https://blog.csdn.net/Sophia_0331/article/details/121196840
三、服务间调用的几种方式
3.1RestTemplate方式
配置信息
@Bean public RestTemplate getRestTemplate(){ return new RestTemplate(); }
服务的消费者(order)调用服务的提供者(Goods)
@Autowired private RestTemplate restTemplate; @GetMapping("/createOrder/{gid}/{number}") public Order order(@PathVariable("gid") Integer id,@PathVariable("number") Integer number){ log.info("用户开始下单,调用商品系统,查询{}号商品信息",id); Goods goods = restTemplate.getForObject("http://localhost:9002/goods/getGoods/" + id, Goods.class); log.info("商品信息查询完毕:"+ JSON.toJSONString(goods)); log.info("开始下单:"); Order order = new Order(); order.setUid(1); order.setUname("测试用户"); order.setGid(goods.getId()); order.setGname(goods.getGoodsName()); order.setNumber(number); orderService.createOrder(order); log.info("下单成功"); return order; }
通过上面的方式我们解决了微服务之间的相互调用,但是存在硬编码的问题,如果服务提供者的地址发生变化,就需要手工修改代码;如果有多个服务提供者,无法实现服务的负载均衡;如果服务增多,人工调用会变得更加的复杂。
这个时候就会需要服务治理,服务治理是微服务架构最核心的问题,用于实现各个微服务的自动化注册与发现。在这里选择Nacos。
3.2引入Nacos注册中心
1.在服务的提供者与消费者的pom文件中引入依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
2.在application.yml中添加配置
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.206.151:8848
3.在对应的微服务上添加
@EnableDiscoveryClient
4.代码
@Autowired private RestTemplate restTemplate; @Autowired private DiscoveryClient discoveryClient; @GetMapping("/createOrder2/{gid}/{number}") public Order order2(@PathVariable("gid") Integer id,@PathVariable("number") Integer number){ log.info("用户开始下单,调用商品系统,查询{}号商品信息",id); //从nacos中获取服务地址 ServiceInstance service = discoveryClient.getInstances("goods-service").get(0); String url = service.getHost() + ":" + service.getPort(); //通过restTemplate调用 Goods goods = restTemplate.getForObject("http://"+url+"/goods/getGoods/" + id, Goods.class); log.info("商品信息查询完毕:"+ JSON.toJSONString(goods)); log.info("开始下单:"); Order order = new Order(); order.setUid(1); order.setUname("测试用户"); order.setGid(goods.getId()); order.setGname(goods.getGoodsName()); order.setNumber(number); orderService.createOrder(order); log.info("下单成功"); return order; }
注:DiscoveryClient是专门负责服务注册和发现的,我们可以通过它获取到注册到注册中心的所有服务。
3.3Fegin实现服务调用
Feign是Spring Cloud提供的一个声明式的伪Http客户端, 它使得调用远程服务就像调用本地服务一样简单, 只需要创建一个接口并添加一个注解即可。
Nacos很好的兼容了Feign, Feign默认集成了 Ribbon, 所以在Nacos下使用Fegin默认就实现了负载均衡的效果。
1.添加依赖
org.springframework.cloud spring-cloud-starter-openfeign
2.在启动类上添加注解
@EnableFeignClients
3.新建client包,并创建接口(把服务提供者controller对应的方法名复制过来,注意路径要完整。
@FeignClient(“goods-service”) public interface GoodsService { @RequestMapping("/goods/getGoods/{id}") public Goods goods(@PathVariable("id") Integer id);
}
4.代码
@Autowired private GoodsService goodsService; @GetMapping("/createOrder3/{gid}/{number}") public Order order3(@PathVariable("gid") Integer id,@PathVariable("number") Integer number){ log.info("用户开始下单,调用商品系统,查询{}号商品信息",id); //通过feign调用商品微服务 Goods goods = goodsService.goods(id); log.info("商品信息查询完毕:"+ JSON.toJSONString(goods)); log.info("开始下单:"); Order order = new Order(); order.setUid(1); order.setUname("测试用户"); order.setGid(goods.getId()); order.setGname(goods.getGoodsName()); order.setNumber(number); orderService.createOrder(order); log.info("下单成功"); return order; }
参看链接:https://blog.csdn.net/swebin/article/details/131070791
在所有的矛盾中,要优先解决主要矛盾,其他矛盾也就迎刃而解。
不要做个笨蛋,为失去的郁郁寡欢,聪明的人,已经找到了解决问题的办法,或正在寻找。