美文网首页
SpringCloudAlibaba简单Demo

SpringCloudAlibaba简单Demo

作者: 蜻蜓队长家长 | 来源:发表于2022-04-26 11:24 被阅读0次

    前言

    • 什么是 Spring Cloud ?
      Spring Cloud 是构建在 Spring Boot 基础之上,用于快速构建分布式系统的通用模式的工具集。或者说,换成大家更为熟知的,用于构建微服务的技术栈。

    • Spring Cloud 和 Spring Boot 的区别和关系?
      1.Spring Boot 专注于快速方便的开发单个个体微服务。
      2.Spring Cloud 是关注全局的微服务协调整理治理框架以及一整套的落地解决方案,它将 Spring Boot 开发的一个个单体微服务整合并管理起来,为各个微服务之间提供:配置管理,服务发现,断路器,路由,微代理,事件总线等的集成服务。
      3.Spring Boot 可以离开 Spring Cloud 独立使用,但是 Spring Cloud 离不开 Spring Boot ,属于依赖的关系。

    总结:
    Spring Boot ,专注于快速,方便的开发单个微服务个体。
    Spring Cloud ,关注全局的服务治理框架。

    组件选择

    图片来源于 Bilibili-尚硅谷 https://www.bilibili.com/video/BV18E411x7eT?p=4

    版本选择

    开发项目最忌讳的就是版本对不上后期解决各种bug,项目搭建一定不能犯的错误

    Spring Boot、Spring Cloud、Spring Coud Alibaba版本选择官网: 版本说明

    代码开源地址

    https://gitee.com/zhuheguo/cloud-demo2022

    项目搭建

    1.创建父项目

    File -> new Project -> maven -> Next

    File -> new Project -> maven 填写项目名称 -> Finish

    父POM可以删除不需要的文件(父项目只需要POM文件)

    项目结构图

    pom文件配置

        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
            <spring.cloud.alibaba-version>2021.1</spring.cloud.alibaba-version>
            <spring.cloud-version>2020.0.1</spring.cloud-version>
            <spring.boot.version>2.4.2</spring.boot.version>
            <lombok.version>1.18.16</lombok.version>
            <hutool.version>5.7.19</hutool.version>
            <fastjson.version>1.2.75</fastjson.version>
            <druid.version>1.1.22</druid.version>
            <mysql.version>8.0.23</mysql.version>
            <mybatis.plus.version>3.4.2</mybatis.plus.version>
        </properties>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-dependencies</artifactId>
                    <version>${spring.boot.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <dependency>
                    <groupId>com.alibaba.cloud</groupId>
                    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                    <version>${spring.cloud.alibaba-version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>${spring.cloud-version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <dependencies>
            <!--Lombok项目是一个Java库,它会自动插入编辑器和构建工具中,Lombok提供了一组有用的注释,用来消除Java类中的大量样板代码-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>
    
            <!--Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。-->
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>${hutool.version}</version>
            </dependency>
    
            <!-- fastjson json转换 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>${fastjson.version}</version>
            </dependency>
        </dependencies>
    

    2.创建子模块

    同样是创建maven项目,不过是在项目右键创建,后面操作和创建父POM项目是一样的


    分布式配置中心 --> Nacos Config

    创建子模块项目名cloud-config-service-8001

    修改pom.xml添加依赖

        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!--配置中心-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
            </dependency>
            <!--2021以上版本需要引入该jar才能使bootstrap配置文件生效-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-bootstrap</artifactId>
            </dependency>
        </dependencies>
    

    添加主启动类com.cloud.pay.ConfigPayMain8001

    package com.cloud.pay;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    /**
     * 功能描述:
     *
     * @Author: zhuheguo
     * @Date: 2022/4/25 9:00
     */
    @SpringBootApplication
    public class ConfigPayMain8001 {
        public static void main(String[] args) {
            SpringApplication.run(ConfigPayMain8001.class,args);
        }
    }
    

    添加测试接口com.cloud.pay.rest.ConfigPayController

    package com.cloud.pay.rest;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.cloud.context.config.annotation.RefreshScope;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * 功能描述:
     *
     * @Author: zhuheguo
     * @Date: 2022/4/25 9:07
     */
    @RestController
    @RefreshScope
    public class ConfigPayController {
    
        @Value("${key}")
        private String key;
    
        @GetMapping("/config")
        public ResponseEntity configPayTest() {
            return ResponseEntity.ok("test--config--key : " + key);
        }
    }
    

    resource添加bootstrap.yml

    management:
      endpoints:
        web:
          exposure:
            include: '*'
    spring:
      application:
        name: cloud-config-service
      cloud:
        nacos:
          config:
            server-addr: localhost:8848
            file-extension: yaml
            group: DEFAULT_GROUP
            namespace: cloud-demo
            #extension-configs:
            #  - dataId: seata.yaml
            #    refresh: true
      profiles:
        active: dev
    server:
      port: 8001
    

    安装Naocs:https://www.cnblogs.com/konglxblog/p/15820333.html

    添加命名空间cloud-demo

    添加配置文件cloud-config-service-dev.yaml


    key: abc123
    

    启动com.cloud.pay.ConfigPayMain8001并访问http://localhost:8001/config

    修改cloud-config-service-dev.yaml并刷新http://localhost:8001/config


    注册中心-服务注册 --> Nacos discovery

    新建子模块cloud-discovery-client-8002

    修改POM

    <dependencies>
            <!--服务注册-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>com.netflix.ribbon</groupId>
                        <artifactId>ribbon</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-loadbalancer</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
        </dependencies>
    

    创建主启动类com.cloud.pay.DiscoveryPayMain8002

    package com.cloud.pay;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    
    /**
     * 功能描述:
     *
     * @Author: zhuheguo
     * @Date: 2022/4/24 18:09
     */
    @SpringBootApplication
    @EnableDiscoveryClient
    public class DiscoveryPayMain8002 {
        public static void main(String[] args) {
            SpringApplication.run(DiscoveryPayMain8002.class,args);
        }
    }
    

    resource中添加application.yml

    server:
      port: 8002
    spring:
      application:
        name: cloud-discovery-client
      cloud:
        loadbalancer:
          cache:
            enabled: false
        nacos:
          discovery:
            server-addr: localhost:8848
            namespace: cloud-demo
            group: DEFAULT_GROUP
    management:
      endpoints:
        web:
          exposure:
            include: '*'
    

    添加测试接口com.cloud.pay.rest.DiscoveryPayController

    package com.cloud.pay.rest;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * 功能描述:
     *
     * @Author: zhuheguo
     * @Date: 2022/4/24 18:23
     */
    @RestController
    public class DiscoveryPayController {
    
        @Value("${server.port}")
        private Integer port;
    
        @GetMapping("/discovery")
        public ResponseEntity<String> discovery() {
            return ResponseEntity.ok(port + "-->discovery");
        }
    }
    

    启动com.cloud.pay.DiscoveryPayMain8002并访问http://localhost:8002/discovery

    查看服务列表可以看见cloud-discovery-client则服务注册成功

    服务消费和RPC远程调用+负载均衡 --> Nacos Discovery + OpenFeign + Loadbalancer

    创建子模块cloud-feign-consumer-9001

    修改pom.xml

    <dependencies>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>com.netflix.ribbon</groupId>
                        <artifactId>ribbon</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-loadbalancer</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
        </dependencies>
    

    添加主启动类com.cloud.pay.FeignPayMain9001

    package com.cloud.pay;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.openfeign.EnableFeignClients;
    
    /**
     * 功能描述:
     *
     * @Author: zhuheguo
     * @Date: 2022/4/25 10:08
     */
    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableFeignClients
    public class FeignPayMain9001 {
        public static void main(String[] args) {
            SpringApplication.run(FeignPayMain9001.class,args);
        }
    }
    

    resource中添加application.yml

    server:
      port: 9001
    spring:
      application:
        name: cloud-feign-consumer
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848
            namespace: cloud-demo
            group: DEFAULT_GROUP
    management:
      endpoints:
        web:
          exposure:
            include: '*'
    

    添加RPC调用接口com.cloud.pay.service.TestService

    package com.cloud.pay.service;
    
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.http.ResponseEntity;
    import org.springframework.stereotype.Component;
    import org.springframework.web.bind.annotation.GetMapping;
    
    /**
     * 功能描述:
     *
     * @Author: zhuheguo
     * @Date: 2022/4/25 10:15
     */
    @FeignClient("cloud-discovery-client")
    @Component
    public interface TestService {
    
        /**
         * 调用cloud-discovery-client的服务提供者
         *
         * @return
         */
        @GetMapping("/discovery")
        ResponseEntity<String> discovery();
    }
    

    添加测试接口com.cloud.pay.rest.FeignPayController

    package com.cloud.pay.rest;
    
    import com.cloud.pay.service.TestService;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.annotation.Resource;
    
    /**
     * 功能描述:
     *
     * @Author: zhuheguo
     * @Date: 2022/4/25 10:13
     */
    @RestController
    @Slf4j
    public class FeignPayController {
    
        @Resource
        private TestService service;
    
        @Value("${server.port}")
        private Integer port;
    
        @GetMapping("/feign")
        public ResponseEntity<String> test() {
            final ResponseEntity<String> responseEntity = service.discovery();
            log.info("HTTP Status::{}", responseEntity.getStatusCodeValue());
            log.info("body::{}", responseEntity.getBody());
            return ResponseEntity.ok(port + "--->" + responseEntity.getBody());
        }
    }
    

    启动com.cloud.pay.FeignPayMain9001和服务提供者cloud-discovery-client-8002的启动类com.cloud.pay.DiscoveryPayMain8002并访问http://localhost:9001/feign尝试多刷新几次

    发现可以通过9001调用8002端口提供的服务,但是反复刷新只能一直调用8002,我们可以利用8002修改端口启动8003 (不会可以参考 Idea中一个服务按多个端口同时启动

    启动DiscoveryPayMain8003服务再反复刷新http://localhost:9001/feign发现会轮询8002和8003(你也可以多启动几个测试)

    服务网关 --> gateway

    创建子模块cloud-gateway-service-7001

    修改pom.xml

    <dependencies>
            <!--服务注册-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>com.netflix.ribbon</groupId>
                        <artifactId>ribbon</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-loadbalancer</artifactId>
            </dependency>
            <!--服务网关-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-gateway</artifactId>
            </dependency>
        </dependencies>
    

    添加主启动类com.cloud.pay.GatewayMain7001

    package com.cloud.pay;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    
    /**
     * 功能描述:
     *
     * @Author: zhuheguo
     * @Date: 2022/4/25 14:01
     */
    @SpringBootApplication
    @EnableDiscoveryClient
    public class GatewayMain7001 {
        public static void main(String[] args) {
            SpringApplication.run(GatewayMain7001.class, args);
        }
    }
    

    添加配置文件application.yml

    management:
      endpoints:
        web:
          exposure:
            include: '*'
    spring:
      application:
        name: cloud-gateway-service
      cloud:
        nacos:
          discovery:
            namespace: cloud-demo
            server-addr: localhost:8848
        gateway:
          routes:
            - id: pay
              uri: lb://cloud-discovery-client
              predicates:
                - Path=/discovery**
            - id: order
              uri: lb://cloud-feign-consumer
              predicates:
                - Path=/feign**
    server:
      port: 7001
    

    启动com.cloud.pay.GatewayMain7001并访问http://localhost:7001/feignhttp://localhost:7001/discovery测试


    更多配置测试:https://www.cnblogs.com/babycomeon/p/11161073.html

    服务降级 --> sentinel

    新建子模块cloud-sentinel-service-6001

    修改pom.xml

        <dependencies>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>com.netflix.ribbon</groupId>
                        <artifactId>ribbon</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-loadbalancer</artifactId>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
        </dependencies>
    
    

    添加主启动类com.cloud.pay.SentinelMain6001.java

    package com.cloud.pay;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    
    /**
     * 功能描述:
     *
     * @Author: zhuheguo
     * @Date: 2022/4/25 17:27
     */
    @SpringBootApplication
    @EnableDiscoveryClient
    public class SentinelMain6001 {
        public static void main(String[] args) {
            SpringApplication.run(SentinelMain6001.class,args);
        }
    }
    

    添加application.yml

    management:
      endpoints:
        web:
          exposure:
            include: '*'
    spring:
      application:
        name: cloud-sentinel-service
      cloud:
        nacos:
          discovery:
            namespace: cloud-demo
            server-addr: localhost:8848
        sentinel:
          transport:
            dashboard: localhost:8080
    server:
      port: 6001
    

    添加测试接口com.cloud.pay.rest.SentinelController

    package com.cloud.pay.rest;
    
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * 功能描述:
     *
     * @Author: zhuheguo
     * @Date: 2022/4/25 17:28
     */
    @RestController
    public class SentinelController {
    
        @GetMapping("/sentinel")
        public ResponseEntity sentinel() {
            return ResponseEntity.ok("sentinel");
        }
    }
    

    安装sentinel:https://blog.csdn.net/Kevinnsm/article/details/117479096

    启动com.cloud.pay.SentinelMain6001.java和sentinel管控页面并登录,然后访问http://localhost:6001/sentinel后查看http://localhost:8080/

    新增流控规则后尝试快速刷新和每秒刷新一次http://localhost:6001/sentinel


    测试发现规则限定每秒只能访问一次,规则范围为的被Sentinel限流了

    QPS:每秒查询率(QPS,Queries-per-second)是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。

    更多配置测试:https://www.jianshu.com/p/35ba0d96450d

    分布式事务

    安装:单独文章介绍https://www.jianshu.com/p/d08ee4567749
    主要是安装配置麻烦一点,使用就非常简单

    添加三个子模块cloud-seata-order-service-5001 | cloud-seata-storage-service-5002 | cloud-seata-account-service-5003

    修改pom.xml

     <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!--服务注册-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>com.netflix.ribbon</groupId>
                        <artifactId>ribbon</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-loadbalancer</artifactId>
            </dependency>
            <!--RPC框架-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
            <!--分布式事务-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
            </dependency>
            <!--mybatis plus-->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>${mybatis.plus.version}</version>
            </dependency>
            <!-- 实现对数据库连接池的自动化配置 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jdbc</artifactId>
            </dependency>
            <!-- MySql -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
                <scope>runtime</scope>
            </dependency>
            <!-- 连接池 阿里巴巴数据源 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>${druid.version}</version>
            </dependency>
        </dependencies>
    

    主启动类OrderMain5001 三个项目都一样需要主启动类,代码是一样的不重复贴了

    package com.cloud.order;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.openfeign.EnableFeignClients;
    
    /**
     * 功能描述:
     *
     * @Author: zhuheguo
     * @Date: 2022/4/21 13:51
     */
    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableFeignClients
    public class OrderMain5001 {
        public static void main(String[] args) {
            SpringApplication.run(OrderMain5001.class, args);
        }
    }
    

    实体类com.cloud.order.domain.Order 也是每个项目都有,具体的看源码吧,这里算是在复习SpringBoot了

    package com.cloud.order.domain;
    
    import com.baomidou.mybatisplus.annotation.TableName;
    import lombok.Data;
    
    import java.math.BigDecimal;
    
    /**
     * 功能描述:
     *
     * @Author: zhuheguo
     * @Date: 2022/4/21 13:53
     */
    @Data
    @TableName("t_order")
    public class Order {
    
        private Long id;
    
        /**
         * 用户id
         */
        private Long userId;
    
        /**
         * 产品id
         */
        private Long productId;
    
        /**
         * 数量
         */
        private Integer count;
    
        /**
         * 金额
         */
        private BigDecimal money;
    
        /**
         * 订单状态:0:创建中;1:已完结
         */
        private Integer status;
    }
    

    数据库持久化接口com.cloud.order.service.mapper.OrderMapper

    package com.cloud.order.service.mapper;
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.cloud.order.domain.Order;
    import org.apache.ibatis.annotations.Mapper;
    
    /**
     * 功能描述:
     *
     * @Author: zhuheguo
     * @Date: 2022/4/21 14:19
     */
    @Mapper
    public interface OrderMapper extends BaseMapper<Order> {
    }
    

    订单业务逻辑接口com.cloud.order.service.OrderService

    package com.cloud.order.service;
    
    import com.baomidou.mybatisplus.extension.service.IService;
    import com.cloud.order.domain.Order;
    
    /**
     * 功能描述:
     *
     * @Author: zhuheguo
     * @Date: 2022/4/21 14:21
     */
    public interface OrderService extends IService<Order> {
    
        /**
         * 创建订单
         * @param order
         */
        void create(Order order);
    }
    

    RPC远程调用库存微服务接口com.cloud.order.service.StorageService

    package com.cloud.order.service;
    
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.http.ResponseEntity;
    import org.springframework.stereotype.Component;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    
    /**
     * 功能描述:
     *
     * @Author: zhuheguo
     * @Date: 2022/4/21 14:54
     */
    @FeignClient(value = "cloud-seata-storage-service")
    @Component
    public interface StorageService {
    
        /**
         * 库存扣减
         *
         * @param productId 产品id
         * @param count     数量
         * @return
         */
        @PostMapping(value = "/storage/decrease")
        ResponseEntity decrease(@RequestParam("productId") Long productId, @RequestParam("count") Integer count);
    }
    

    RPC远程调用账户微服务接口com.cloud.order.service.AccountService

    package com.cloud.order.service;
    
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.http.ResponseEntity;
    import org.springframework.stereotype.Component;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    
    import java.math.BigDecimal;
    
    /**
     * 功能描述:
     *
     * @Author: zhuheguo
     * @Date: 2022/4/21 14:54
     */
    @FeignClient("cloud-seata-account-service")
    @Component
    public interface AccountService {
        /**
         * 余额扣减
         *
         * @param userId 用户id
         * @param money  金额
         * @return
         */
        @PostMapping(value = "/account/decrease")
        ResponseEntity decrease(@RequestParam("userId") Long userId, @RequestParam("money") BigDecimal money);
    }
    

    订单业务实现接口com.cloud.order.service.impl.OrderServiceImpl

    package com.cloud.order.service.impl;
    
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.cloud.order.domain.Order;
    import com.cloud.order.service.AccountService;
    import com.cloud.order.service.OrderService;
    import com.cloud.order.service.StorageService;
    import com.cloud.order.service.mapper.OrderMapper;
    import io.seata.spring.annotation.GlobalTransactional;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.Resource;
    
    /**
     * 功能描述:
     *
     * @Author: zhuheguo
     * @Date: 2022/4/21 14:24
     */
    @Slf4j
    @Service
    public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
    
        @Resource
        private StorageService storageService;
    
        @Resource
        private AccountService accountService;
    
        @Override
        @GlobalTransactional(name = "cloud_create_order",rollbackFor = Exception.class)
        public void create(Order order) {
            log.info("开始新建订单");
            this.save(order);
            log.info("订单微服务开始调用库存微服务,做库存扣减");
            storageService.decrease(order.getProductId(), order.getCount());
            log.info("订单微服务开始调用库存微服务,做库存扣减 end---");
            log.info("订单微服务开始调用账户微服务,做余额扣减");
            accountService.decrease(order.getUserId(), order.getMoney());
            log.info("订单微服务开始调用账户微服务,做余额扣减 end---");
            log.info("修改订单状态");
            order.setStatus(0);
            this.saveOrUpdate(order);
            log.info("修改订单状态 end---");
            log.info("订单处理结束");
        }
    }
    

    订单前端控制器com.cloud.order.rest.OrderController

    package com.cloud.order.rest;
    
    import com.cloud.order.domain.Order;
    import com.cloud.order.service.OrderService;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.annotation.Resource;
    
    /**
     * 功能描述:
     *
     * @Author: zhuheguo
     * @Date: 2022/4/21 13:54
     */
    @RestController
    public class OrderController {
    
        @Resource
        private OrderService orderService;
    
        @GetMapping("/order/create")
        public ResponseEntity create(Order order) {
            orderService.create(order);
            return new ResponseEntity("创建订单成功", HttpStatus.OK);
        }
    }
    

    数据源配置类com.cloud.order.config.DataSourceProxyConfig

    package com.cloud.order.config;
    
    import com.alibaba.druid.pool.DruidDataSource;
    import io.seata.rm.datasource.DataSourceProxy;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.mybatis.spring.transaction.SpringManagedTransactionFactory;
    import org.springframework.beans.factory.annotation.Configurable;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    
    import javax.sql.DataSource;
    
    /**
     * 功能描述:使用seata对数据源进行代理
     *
     * @Author: zhuheguo
     * @Date: 2022/4/21 15:11
     */
    @Configurable
    public class DataSourceProxyConfig {
    
        @Bean
        @ConfigurationProperties(prefix = "spring.datasource")
        public DataSource druidDataSource(){
            return new DruidDataSource();
        }
        @Bean
        public DataSourceProxy dataSourceProxy(DataSource dataSource){
            return new DataSourceProxy(dataSource);
        }
    
        @Bean
        public SqlSessionFactory sessionFactoryBean(DataSourceProxy dataSourceProxy)throws Exception{
            SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
            sqlSessionFactoryBean.setDataSource(dataSourceProxy);
            sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());
            return sqlSessionFactoryBean.getObject();
        }
    }
    

    配置文件application.yml

    management:
      endpoints:
        web:
          exposure:
            include: '*'
    server:
      port: 5001
    spring:
      main:
        allow-bean-definition-overriding: true
      application:
        name: cloud-seata-order-service
      cloud:
        nacos:
          discovery:
            namespace: cloud-demo
            server-addr: localhost:8848
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/seata_order?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC
        username: root
        password: 123456
    
    #分布式事务配置
    seata:
      application-id: ${spring.application.name}
      enabled: true
      enable-auto-data-source-proxy: true
      #分组名称
      tx-service-group: my_test_tx_group
      #服务配置
      service:
        disable-global-transaction: false
        vgroup-mapping:
          my_test_tx_group: default
        grouplist:
          default: localhost:8091
      #配置中心配置
      config:
        type: nacos
        nacos:
          application: seata-server
          namespace: seata
          serverAddr: localhost:8848
          group: SEATA_GROUP
      #注册中心配置
      registry:
        type: nacos
        nacos:
          application: seata-server
          namespace: seata
          server-addr: localhost:8848
          group: SEATA_GROUP
    

    另外两个模块请看源码,结构是一样的,顺带演示了Spring boot 整合mybatis plus项目的搭建

    实体类对应的sql初始化在父项目的sql文件夹中

    完成后启动测试,请先启动服务提供者(账户和库存微服务),后启动订单微服务,访问http://localhost:5001/order/create?userId=1&productId=1&count=10&money=100

    相关文章

      网友评论

          本文标题:SpringCloudAlibaba简单Demo

          本文链接:https://www.haomeiwen.com/subject/thbfyrtx.html