前言
大家好,一直以来我都本着用最通俗的话理解核心的知识点, 我认为所有的难点都离不开 基础知识 的铺垫。目前正在出一个SpringCloud
长期系列教程,从入门到进阶, 篇幅会较多~
适合人群
- 有一定的Java基础
- 想尝试微服务开发
- 有SpringBoot开发基础
- 想学习或了解SpringCloud
- 想提高自己的同学
大佬可以绕过 ~
背景
如果你是一路看过来的,很高兴你能够耐心看完。之前带大家学了Springboot
这门框架,熟练掌握了单体应用
的开发,如今微服务
开发盛行,对我们的技术要求也是越来越高,薪资也是令人兴奋。这个系列将会带大家学习SpringCloud
微服务开发,我会带大家一步一步的入门,耐心看完你一定会有收获
~
情景回顾
上期带大家一起认识了Nacos
以及带大家体验了一下它作为配置中心和注册中心的使用,本期就带大家结合注册中心
来进行服务的远程调用,首先学习一下基于rest
的远程调用RestTemplate
,我们一起来看一下吧~
配置 RestTemplate
先配置一下它,其实RestTemplate
并不是Cloud
的产物,它在org.springframework.web.client
下的一个类,也就是说我们的单体应用比如单独的SpringBoot
也可以用的,我们可以用它去进行http
请求调用
@Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate(ClientHttpRequestFactory factory) { return new RestTemplate(factory); } @Bean public ClientHttpRequestFactory clientHttpRequestFactory() { SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); factory.setReadTimeout(6000); factory.setConnectTimeout(3000); return factory; } } 复制代码
RestTemplate常用方法讲解
为了方便测试,我们在项目中新增两个模块,一个是consumer
一个是producer
,项目大家自己建,同样需要把服务注册到 Nacos中, RestTemplateConfig
放到consumer
中,因为它是调用端
producer
在producer
下新建一个HelloController
@RestController @RequestMapping("/hello") public class HelloController { @GetMapping("/app/{id:\\d+}") @ResponseBody public String hello1(@PathVariable String id) { return "hello " + id; } @PostMapping("/app/post") @ResponseBody public User hello2(@RequestBody User u) { return u; } } 复制代码
- User 类
@Data public class User { private String username; } 复制代码
consumer
同样的,我们也新建一个HelloController
, 我们之前讲过,我们直接使用ip+port
的方式也是可以直接调用的,但是我们有更好的方案,那么如何去结合注册中心使用呢?让我们直接可以通过服务名
就可以调用呢?这里我们只需要改一下RestTemplateConfig
,只需要加一个@LoadBalanced
的注解就可以了
@Bean @LoadBalanced // 这样可以使用服务对象调用 http://provicer/app/hello public RestTemplate restTemplate(ClientHttpRequestFactory factory) { return new RestTemplate(factory); } 复制代码
如果我想知道服务地址是啥,有什么办法可以拿到吗?我们这里可以通过服务发现获取服务提供者的信息
@GetMapping("/discoverSvrInfo") @ResponseBody public URI getSvrUrl() throws Exception { // 如果是多个服务提供者 ServiceInstance serviceInstance; if(true) { List<ServiceInstance> services = discoveryClient.getInstances("provider"); serviceInstance = services.size() > 0 ? services.get(0) : null; }else { serviceInstance = loadBalancerClient.choose("provider"); } // 发起调用 // 1. 不同命名空间下 调用,会导致找不到实例 if(serviceInstance == null) { throw new Exception("未获取到实例"); } return serviceInstance.getUri(); } 复制代码
大家可以自己打断点,看看里边都有些啥。有了基本的认识之后,下边我们就来整一下吧
发起 GET 请求
- 通过实体类
@RequestMapping("/hello/user/{id:\\d+}") @ResponseBody public User hello1(@PathVariable String id) { User u = restTemplate.getForEntity("http://provider/hello/app/{name}", User.class, id).getBody(); return u; } 复制代码
- 通过Map
Map<String, Object> params = new HashMap<>(); params.put("name", id); u = restTemplate.getForEntity("http://provider/hello/app/{name}", User.class, params).getBody(); 复制代码
发起 POST 请求
Map<String, String> us = new HashMap<>(); us.put("username", "java rest api -- "); us.put("username", us.get("username") + id); u = restTemplate.postForObject("http://provider/hello/app/post", us, User.class); 复制代码
同样的,它也有 postForObject postForEntity postForLocation
, 方法跟get
方式类似, 大家可以自己试一下
结束语
本期到这里就结束了, 总结一下,本节主要讲了,服务之间如何进结合服务发现机制
进行调用,我们通过基于rest
方式的调用,学习了restTemplate
的用法,最后完成了一个小例子,建议大家自己多去尝试 ~
下期预告
我们说虽然服务被拆分开, 但是还会产生问题的,想象一下多个微服务之间进行调用, 你能保障服务就不会出现问题吗,如果出现问题了,会产生什么后果❓ 会影响其它服务吗,想必肯定是的。这就是我们下期要讲的另一个核心组件Hystrix
。 关注我,不迷路, 下期不见不散 ~