• 02-微服务的拆分规则和基于RestTemplate的远程调用


    微服务的拆分与远程调用

    创建父工程

    任何分布式架构都离不开服务的拆分, 微服务也是一样 , 微服务的拆分遵守三个原则

    • 微服务需要根据业务模块拆分,不同微服务不要重复开发相同业务
    • 每个微服务都有自己独立的数据库, 不要直接访问其他微服务的数据库
    • 微服务可以将自己的业务暴露为接口供其他微服务调用

    创建父工程cloud-demo用来管理项目所需要的依赖的版本

    • order-service订单微服务模块(工程): 负责订单相关业务,如根据订单Id查询订单
    • user-service用户微服务模块(工程): 负责用户相关业务,如根据用户Id查询用户

    在这里插入图片描述

    <groupId>cn.itcast.demogroupId>
    <artifactId>cloud-demoartifactId>
    <version>1.0version>
    
    <modules>
        <module>user-servicemodule>
        <module>order-servicemodule>
    modules>
    <packaging>pompackaging>
    
    
    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.3.9.RELEASEversion>
        <relativePath/>
    parent>
    
    
    <properties>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
        <java.version>1.8java.version>
        <spring-cloud.version>Hoxton.SR10spring-cloud.version>
        <mysql.version>5.1.47mysql.version>
        <mybatis.version>2.1.1mybatis.version>
    properties>
    
    
    <dependencyManagement>
        <dependencies>
            
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>${spring-cloud.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
            
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <version>${mysql.version}version>
            dependency>
            
            <dependency>
                <groupId>org.mybatis.spring.bootgroupId>
                <artifactId>mybatis-spring-boot-starterartifactId>
                <version>${mybatis.version}version>
            dependency>
        dependencies>
    dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
        dependency>
    dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    创建订单微服务模块(工程)

    第一步: 执行cloud-order.sql文件创建订单数据库,cloud-ordertb_order表中含有用户数据库的tb_user表的Id字段

    在这里插入图片描述

    @Data
    public class Order {
        private Long id;
        private Long price;
        private String name;
        private Integer num;
        private Long userId;
        private User user;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    第二步: 配置order-service工程的pom.xml文件

    <parent>
        <artifactId>cloud-demoartifactId>
        <groupId>cn.itcast.demogroupId>
        <version>1.0version>
    parent>
    <modelVersion>4.0.0modelVersion>
    <artifactId>order-serviceartifactId>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
        dependency>
        
        <dependency>
            <groupId>org.mybatis.spring.bootgroupId>
            <artifactId>mybatis-spring-boot-starterartifactId>
        dependency>
    dependencies>
    <build>
        <finalName>appfinalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            plugin>
        plugins>
    build>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    第三步: 配置order-service工程的application.yml文件

    server:
      port: 8080
    spring:
      datasource:
        url: jdbc:mysql://localhost:3306/cloud_order?useSSL=false
        username: root
        password: 123
        driver-class-name: com.mysql.jdbc.Driver
    mybatis:
      type-aliases-package: cn.itcast.user.pojo
      configuration:
        map-underscore-to-camel-case: true
    logging:
      level:
        cn.itcast: debug
      pattern:
        dateformat: MM-dd HH:mm:ss:SSS
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    第四步: 创建Mapper接口和自定义Service类,这里就不再创建业务类的实现类了

    @Mapper
    public interface OrderMapper {
        @Select("select * from tb_order where id = #{id}")
        Order findById(Long id);
    }
    @Service
    public class OrderService {
        @Autowired
        private OrderMapper orderMapper;
        @Autowired
        private UserClient userClient;
        public Order queryOrderById(Long orderId) {
            // 查询订单
            Order order = orderMapper.findById(orderId);
            // 返回查询到的订单对象,user属性为null
            return order;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    第五步: 在order-service工程中创建controller/OrderController,编写接口根据订单Id从订单数据库中查询订单信息

    @RestController
    @RequestMapping("order")
    public class OrderController {
       @Autowired
       private OrderService orderService;
        @GetMapping("{orderId}")
        public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {
            // 根据id查询订单并返回
            return orderService.queryOrderById(orderId);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    第五步: 打开浏览器访问http://localhost:8080/order/101可以查询到订单数据的但此时user属性的值是null

    {
    	"id": 101,
    	"price": 699900,
    	"name": "Apple 苹果 iPhone 12 ",
    	"num": 1,
    	"userId": 1,
    	"user": null
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    创建用户微服务模块(工程)

    第一步: 执行cloud-user.sql文件创建用户数据库,创建tb_user表及其对应的实体类

    在这里插入图片描述

    @Data
    public class User {
        private Long id;
        private String username;
        private String address;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    第二步: 配置user-service工程的pom.xml文件

    <parent>
        <artifactId>cloud-demoartifactId>
        <groupId>cn.itcast.demogroupId>
        <version>1.0version>
    parent>
    <modelVersion>4.0.0modelVersion>
    
    <artifactId>user-serviceartifactId>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
        dependency>
        
        <dependency>
            <groupId>org.mybatis.spring.bootgroupId>
            <artifactId>mybatis-spring-boot-starterartifactId>
        dependency>
    dependencies>
    <build>
        <finalName>appfinalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            plugin>
        plugins>
    build>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    第三步: 配置user-service工程的application.yml文件

    server:
      port: 8081
    spring:
      datasource:
        url: jdbc:mysql://localhost:3306/cloud_user?useSSL=false
        username: root
        password: 123
        driver-class-name: com.mysql.jdbc.Driver
    mybatis:
      type-aliases-package: cn.itcast.user.pojo
      configuration:
        map-underscore-to-camel-case: true
    logging:
      level:
        cn.itcast: debug
      pattern:
        dateformat: MM-dd HH:mm:ss:SSS
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    第四步: 配置Mapper接口和Service类,这里就不再创建业务类的实现类了

    @Mapper
    public interface UserMapper {    
        @Select("select * from tb_user where id = #{id}")
        User findById(@Param("id") Long id);
    }
    @Service
    public class UserService {
        @Autowired
        private UserMapper userMapper;
        public User queryById(Long id) {
            return userMapper.findById(id);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    第五步: 在user-service工程中创建controller/UserController,编写接口根据用户Id从用户数据库中查询用户信息

    @Slf4j
    @RestController
    @RequestMapping("/user")
    public class UserController {
        @Autowired
        private UserService userService;
        /**
         * 路径: /user/110
         * @param id 用户id
         * @return 用户
         */
        @GetMapping("/{id}")
        public User queryById(@PathVariable("id") Long id) {
            return userService.queryById(id);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    第六步: 打开浏览器访问http://localhost:8081/user/1查询到的数据如下

    {
    	"id": 1,
    	"username": "柳岩",
    	"address": "湖南省衡阳市"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    远程调用(RestTemplate)

    需求: 访问订单模块根据订单Id查询订单,根据查询的订单对象中包含的userId访问用户模块查询出用户信息,然后封装到订单对象的user属性中返回

    在这里插入图片描述

    RestTemplate是Spring提供的发起http请求的工具类

    方法名功能
    Object getForObject(url, Xxx.class)发起一个get请求并指定返回的类型(服务器默认返回Json类型的数据)
    Object postForObject(url, Xxx.class)发起一个post请求并指定返回的类型(服务器默认返回Json类型的数据)

    第一步: 在order-service服务的代码逻辑中向user-service服务发起一个http请求,访问http://localhost:8081/user/{userId}查询用户信息

    在这里插入图片描述

    第二步: 在order-service服务中的OrderApplication启动类中(本质是个配置类)注册RestTemplate实例到Spring容器当中

    @MapperScan("cn.itcast.order.mapper")
    @SpringBootApplication
    public class OrderApplication {
        public static void main(String[] args) {
            SpringApplication.run(OrderApplication.class, args);
        }
    
        @Bean
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    第三步: 修改订单服务的OrderService类中的queryOrderById方法,根据Order对象中包含的userId发http请求访问用户服务查询用户信息,然后一并返回

    @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指定url地址发起http请求查询User,指定接收的类型(服务器默认返回Json类型的数据)
            String url = "http://localhost:8081/user/" + order.getUserId();
            User user = restTemplate.getForObject(url, User.class);
            // 3.存入order
            order.setUser(user);
            // 4.返回
            return order;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    第四步: 访问订单服务查询订单的接口http://localhost:8080/order/101,此时订单对象中包含对应用户的信息

    {
    	"id": 101,
    	"price": 699900,
    	"name": "Apple 苹果 iPhone 12 ",
    	"num": 1,
    	"userId": 1,
    	"user": {
    		"id": 1,
    		"username": "柳岩",
    		"address": "湖南省衡阳市"
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  • 相关阅读:
    博睿数据出席阿里云可观测技术峰会,数字体验管理驱动可持续发展
    集成算法——随机森林(Random Forest)
    改进后的 Google Play 管理中心用户管理: 访问请求、权限组等
    微服务之Eureka
    微软开发新模型;YouTube 推出新AI功能;可折叠iPhone 或发布?
    使用kubeadm搭建高可用集群-k8s相关组件及1.16版本的安装部署
    SSM整合demo及个人思考
    从零开始学Spring Boot系列-集成Kafka
    云原生超融合八大核心能力|ZStack Edge云原生超融合产品技术解读
    【期末大作业】基于HTML+CSS+JavaScript网上订餐系统(23个页面)
  • 原文地址:https://blog.csdn.net/qq_57005976/article/details/134543647