目录
微服务是一种架构风格,按照业务板块来划分应用代码,使单个应用的职责更清晰,相互之间可以做到独立升级迭代。
以电子商城为例,一个商城应用拆分成了多个微服务,如用户服务、交易服务和商品服务,相互之间协作支持整个商城的应用。
SpringCloud是目前国内使用最广泛的微服务框架。官网地址:Spring Cloud。
SpringCloud集成了各种微服务功能组件,并基于SpringBoot实现了这些组件的自动装配,从而提供了良好的开箱即用体验:
值得注意的是 SpringCloud 与 SpringBoot 的版本兼容关系如下:
我们脑海中因该出现一幅图:
实际上,微服务的组件远不止于此,还有很多的组件,但是以上呢,就是我们最常用的几个组件啦~
前面我们了解到微服务需要对一块大的服务,拆分成多个小的微服务,那么这个拆分的粒度我们应该如何去把控呢?需要我们注意一下几点:
例如:我们将一个大的服务拆分成了订单模块和用户模块,并且每一个微服务有自己的数据库(订单数据库和用户数据库)。由于在不同的数据库中,因此只能通过订单 id 查询订单数据,或者通过用户 id 查询用户数据,不能交叉访问,如下图
那么如果需求是:“根据订单id查询订单的同时,把订单所属的用户信息一起返回”,我们该如何跨服务访问呢?接着往下走~
需求是:“根据订单id查询订单的同时,把订单所属的用户信息一起返回”。
相同的服务,我们可以直接通过 mapper 调用其数据库,不同的服务如何相互调用呢?办法很简单,就如上图,用户模块提供公开的访问接口("/user/{id}"),订单模块主动向用户模块发送 http 请求获取数据,这样就做到了跨服务之间的调用~
根据刚刚所说的案例,我们只需要以下四步:
1)注册RestTemplate
在订单服务(order-service)的OrderApplication中(SpringBoot 启动类)注册RestTemplate,如下:
- import org.mybatis.spring.annotation.MapperScan;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.context.annotation.Bean;
- import org.springframework.web.client.RestTemplate;
-
- //@MapperScan 注解的作用相当于在指定包下的所有 mapper 接口上都加上了 @mapper 注解
- @MapperScan("cn.itcast.order.mapper")
- @SpringBootApplication
- public class OrderApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(OrderApplication.class, args);
- }
-
- /**
- * 将 RestTemplate 对象注入到 spring 容器中
- * @return
- */
- @Bean
- public RestTemplate restTemplate() {
- return new RestTemplate();
- }
-
- }
2)服务远程调用RestTemplate
在订单服务中,通过 RestTemplate 的 getForObject / postForObject 方法来构造get / post 请求(此处显然使用 get 请求获取用户数据),请求中携带的参数便是订单表中的 userId 数据,当用户微服务接收到请求后,就可以根据 userId 获取用户数据,最后返回到订单服务中,这样就实现了跨服务调用~
- import cn.itcast.order.mapper.OrderMapper;
- import cn.itcast.order.pojo.Order;
- import cn.itcast.order.pojo.User;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- import org.springframework.web.client.RestTemplate;
-
- @Service
- public class OrderService {
-
- @Autowired
- private OrderMapper orderMapper;
- @Autowired
- private RestTemplate restTemplate;
-
- public Order queryOrderById(Long orderId) {
- // 1.查询订单
- Order order = orderMapper.findById(orderId);
- // 2.利用 RestTemplate 发送 http 请求,查询用户
- String url = "http://localhost:8081/user/" + order.getUserId();
- //get请求:getForObject
- //post请求:postForObject
- //第一个参数是 url, 第二个参数是请求后响应的参数类型(自动的反序列化)
- User user = restTemplate.getForObject(url, User.class);
- // 3.封装 User 到 Order
- order.setUser(user);
- // 4.返回
- return order;
- }
- }
跨服务调用前的执行效果:
跨服务调用后的执行效果:
你学费了吗?