SpringCloudAlibaba簡(jiǎn)單Demo

前言

  • 什么是 Spring Cloud 缘眶?
    Spring Cloud 是構(gòu)建在 Spring Boot 基礎(chǔ)之上,用于快速構(gòu)建分布式系統(tǒng)的通用模式的工具集髓废“跽福或者說(shuō),換成大家更為熟知的瓦哎,用于構(gòu)建微服務(wù)的技術(shù)棧。

  • Spring Cloud 和 Spring Boot 的區(qū)別和關(guān)系柔逼?
    1.Spring Boot 專注于快速方便的開發(fā)單個(gè)個(gè)體微服務(wù)蒋譬。
    2.Spring Cloud 是關(guān)注全局的微服務(wù)協(xié)調(diào)整理治理框架以及一整套的落地解決方案,它將 Spring Boot 開發(fā)的一個(gè)個(gè)單體微服務(wù)整合并管理起來(lái)愉适,為各個(gè)微服務(wù)之間提供:配置管理犯助,服務(wù)發(fā)現(xiàn),斷路器维咸,路由剂买,微代理,事件總線等的集成服務(wù)癌蓖。
    3.Spring Boot 可以離開 Spring Cloud 獨(dú)立使用瞬哼,但是 Spring Cloud 離不開 Spring Boot ,屬于依賴的關(guān)系租副。

總結(jié):
Spring Boot 坐慰,專注于快速,方便的開發(fā)單個(gè)微服務(wù)個(gè)體用僧。
Spring Cloud 结胀,關(guān)注全局的服務(wù)治理框架。

組件選擇

圖片來(lái)源于 Bilibili-尚硅谷 https://www.bilibili.com/video/BV18E411x7eT?p=4

版本選擇

開發(fā)項(xiàng)目最忌諱的就是版本對(duì)不上后期解決各種bug责循,項(xiàng)目搭建一定不能犯的錯(cuò)誤

Spring Boot糟港、Spring Cloud、Spring Coud Alibaba版本選擇官網(wǎng): 版本說(shuō)明

代碼開源地址

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

項(xiàng)目搭建

1.創(chuàng)建父項(xiàng)目

File -> new Project -> maven -> Next

File -> new Project -> maven

填寫項(xiàng)目名稱 -> Finish

父POM可以刪除不需要的文件(父項(xiàng)目只需要POM文件)

項(xiàng)目結(jié)構(gòu)圖

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項(xiàng)目是一個(gè)Java庫(kù)院仿,它會(huì)自動(dòng)插入編輯器和構(gòu)建工具中秸抚,Lombok提供了一組有用的注釋,用來(lái)消除Java類中的大量樣板代碼-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
        </dependency>

        <!--Hutool是一個(gè)小而全的Java工具類庫(kù)歹垫,通過(guò)靜態(tài)方法封裝耸别,降低相關(guān)API的學(xué)習(xí)成本,提高工作效率县钥,使Java擁有函數(shù)式語(yǔ)言般的優(yōu)雅秀姐,讓Java語(yǔ)言也可以“甜甜的”。-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>${hutool.version}</version>
        </dependency>

        <!-- fastjson json轉(zhuǎn)換 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>${fastjson.version}</version>
        </dependency>
    </dependencies>

2.創(chuàng)建子模塊

同樣是創(chuàng)建maven項(xiàng)目若贮,不過(guò)是在項(xiàng)目右鍵創(chuàng)建省有,后面操作和創(chuàng)建父POM項(xiàng)目是一樣的


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

創(chuàng)建子模塊項(xiàng)目名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>

添加主啟動(dòng)類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);
    }
}

添加測(cè)試接口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

啟動(dòng)com.cloud.pay.ConfigPayMain8001并訪問http://localhost:8001/config

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


注冊(cè)中心-服務(wù)注冊(cè) --> Nacos discovery

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

修改POM

<dependencies>
        <!--服務(wù)注冊(cè)-->
        <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>

創(chuàng)建主啟動(dòng)類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: '*'

添加測(cè)試接口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");
    }
}

啟動(dòng)com.cloud.pay.DiscoveryPayMain8002并訪問http://localhost:8002/discovery

查看服務(wù)列表可以看見cloud-discovery-client則服務(wù)注冊(cè)成功

服務(wù)消費(fèi)和RPC遠(yuǎn)程調(diào)用+負(fù)載均衡 --> Nacos Discovery + OpenFeign + Loadbalancer

創(chuàng)建子模塊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>

添加主啟動(dòng)類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調(diào)用接口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 {

    /**
     * 調(diào)用cloud-discovery-client的服務(wù)提供者
     *
     * @return
     */
    @GetMapping("/discovery")
    ResponseEntity<String> discovery();
}

添加測(cè)試接口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());
    }
}

啟動(dòng)com.cloud.pay.FeignPayMain9001和服務(wù)提供者cloud-discovery-client-8002的啟動(dòng)類com.cloud.pay.DiscoveryPayMain8002并訪問http://localhost:9001/feign嘗試多刷新幾次

發(fā)現(xiàn)可以通過(guò)9001調(diào)用8002端口提供的服務(wù)痒留,但是反復(fù)刷新只能一直調(diào)用8002,我們可以利用8002修改端口啟動(dòng)8003 (不會(huì)可以參考 Idea中一個(gè)服務(wù)按多個(gè)端口同時(shí)啟動(dòng)

啟動(dòng)DiscoveryPayMain8003服務(wù)再反復(fù)刷新http://localhost:9001/feign發(fā)現(xiàn)會(huì)輪詢8002和8003(你也可以多啟動(dòng)幾個(gè)測(cè)試)

服務(wù)網(wǎng)關(guān) --> gateway

創(chuàng)建子模塊cloud-gateway-service-7001

修改pom.xml

<dependencies>
        <!--服務(wù)注冊(cè)-->
        <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>
        <!--服務(wù)網(wǎng)關(guān)-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
    </dependencies>

添加主啟動(dòng)類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

啟動(dòng)com.cloud.pay.GatewayMain7001并訪問http://localhost:7001/feignhttp://localhost:7001/discovery測(cè)試


更多配置測(cè)試:https://www.cnblogs.com/babycomeon/p/11161073.html

服務(wù)降級(jí) --> 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>

添加主啟動(dòng)類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

添加測(cè)試接口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

啟動(dòng)com.cloud.pay.SentinelMain6001.java和sentinel管控頁(yè)面并登錄蠢沿,然后訪問http://localhost:6001/sentinel后查看http://localhost:8080/

新增流控規(guī)則后嘗試快速刷新和每秒刷新一次http://localhost:6001/sentinel


測(cè)試發(fā)現(xiàn)規(guī)則限定每秒只能訪問一次伸头,規(guī)則范圍為的被Sentinel限流了

QPS:每秒查詢率(QPS,Queries-per-second)是對(duì)一個(gè)特定的查詢服務(wù)器在規(guī)定時(shí)間內(nèi)所處理流量多少的衡量標(biāo)準(zhǔn)舷蟀。

更多配置測(cè)試:http://www.reibang.com/p/35ba0d96450d

分布式事務(wù)

安裝:?jiǎn)为?dú)文章介紹http://www.reibang.com/p/d08ee4567749
主要是安裝配置麻煩一點(diǎn)恤磷,使用就非常簡(jiǎn)單

添加三個(gè)子模塊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>
        <!--服務(wù)注冊(cè)-->
        <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>
        <!--分布式事務(wù)-->
        <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>
        <!-- 實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)連接池的自動(dòng)化配置 -->
        <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>
        <!-- 連接池 阿里巴巴數(shù)據(jù)源 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>${druid.version}</version>
        </dependency>
    </dependencies>

主啟動(dòng)類OrderMain5001 三個(gè)項(xiàng)目都一樣需要主啟動(dòng)類,代碼是一樣的不重復(fù)貼了

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);
    }
}

實(shí)體類com.cloud.order.domain.Order 也是每個(gè)項(xiàng)目都有野宜,具體的看源碼吧扫步,這里算是在復(fù)習(xí)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;

    /**
     * 產(chǎn)品id
     */
    private Long productId;

    /**
     * 數(shù)量
     */
    private Integer count;

    /**
     * 金額
     */
    private BigDecimal money;

    /**
     * 訂單狀態(tài):0:創(chuàng)建中;1:已完結(jié)
     */
    private Integer status;
}

數(shù)據(jù)庫(kù)持久化接口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> {
}

訂單業(yè)務(wù)邏輯接口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> {

    /**
     * 創(chuàng)建訂單
     * @param order
     */
    void create(Order order);
}

RPC遠(yuǎn)程調(diào)用庫(kù)存微服務(wù)接口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 {

    /**
     * 庫(kù)存扣減
     *
     * @param productId 產(chǎn)品id
     * @param count     數(shù)量
     * @return
     */
    @PostMapping(value = "/storage/decrease")
    ResponseEntity decrease(@RequestParam("productId") Long productId, @RequestParam("count") Integer count);
}

RPC遠(yuǎn)程調(diào)用賬戶微服務(wù)接口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);
}

訂單業(yè)務(wù)實(shí)現(xiàn)接口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("訂單微服務(wù)開始調(diào)用庫(kù)存微服務(wù)匈子,做庫(kù)存扣減");
        storageService.decrease(order.getProductId(), order.getCount());
        log.info("訂單微服務(wù)開始調(diào)用庫(kù)存微服務(wù)河胎,做庫(kù)存扣減 end---");
        log.info("訂單微服務(wù)開始調(diào)用賬戶微服務(wù),做余額扣減");
        accountService.decrease(order.getUserId(), order.getMoney());
        log.info("訂單微服務(wù)開始調(diào)用賬戶微服務(wù)虎敦,做余額扣減 end---");
        log.info("修改訂單狀態(tài)");
        order.setStatus(0);
        this.saveOrUpdate(order);
        log.info("修改訂單狀態(tài) end---");
        log.info("訂單處理結(jié)束");
    }
}

訂單前端控制器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("創(chuàng)建訂單成功", HttpStatus.OK);
    }
}

數(shù)據(jù)源配置類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對(duì)數(shù)據(jù)源進(jìn)行代理
 *
 * @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

#分布式事務(wù)配置
seata:
  application-id: ${spring.application.name}
  enabled: true
  enable-auto-data-source-proxy: true
  #分組名稱
  tx-service-group: my_test_tx_group
  #服務(wù)配置
  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
  #注冊(cè)中心配置
  registry:
    type: nacos
    nacos:
      application: seata-server
      namespace: seata
      server-addr: localhost:8848
      group: SEATA_GROUP

另外兩個(gè)模塊請(qǐng)看源碼游岳,結(jié)構(gòu)是一樣的,順帶演示了Spring boot 整合mybatis plus項(xiàng)目的搭建

實(shí)體類對(duì)應(yīng)的sql初始化在父項(xiàng)目的sql文件夾中

完成后啟動(dòng)測(cè)試其徙,請(qǐng)先啟動(dòng)服務(wù)提供者(賬戶和庫(kù)存微服務(wù))胚迫,后啟動(dòng)訂單微服務(wù),訪問http://localhost:5001/order/create?userId=1&productId=1&count=10&money=100

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末唾那,一起剝皮案震驚了整個(gè)濱河市晌区,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌通贞,老刑警劉巖朗若,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異昌罩,居然都是意外死亡哭懈,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門茎用,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)遣总,“玉大人,你說(shuō)我怎么就攤上這事轨功⌒癯猓” “怎么了?”我有些...
    開封第一講書人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵古涧,是天一觀的道長(zhǎng)垂券。 經(jīng)常有香客問我,道長(zhǎng)羡滑,這世上最難降的妖魔是什么菇爪? 我笑而不...
    開封第一講書人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任算芯,我火速辦了婚禮,結(jié)果婚禮上凳宙,老公的妹妹穿的比我還像新娘熙揍。我一直安慰自己,他們只是感情好氏涩,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開白布届囚。 她就那樣靜靜地躺著,像睡著了一般是尖。 火紅的嫁衣襯著肌膚如雪意系。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評(píng)論 1 289
  • 那天析砸,我揣著相機(jī)與錄音,去河邊找鬼爆袍。 笑死首繁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的陨囊。 我是一名探鬼主播弦疮,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蜘醋!你這毒婦竟也來(lái)了胁塞?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤压语,失蹤者是張志新(化名)和其女友劉穎啸罢,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體胎食,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡扰才,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了厕怜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片衩匣。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖粥航,靈堂內(nèi)的尸體忽然破棺而出琅捏,到底是詐尸還是另有隱情,我是刑警寧澤递雀,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布柄延,位于F島的核電站,受9級(jí)特大地震影響缀程,放射性物質(zhì)發(fā)生泄漏拦焚。R本人自食惡果不足惜蜡坊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望赎败。 院中可真熱鬧秕衙,春花似錦、人聲如沸僵刮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)搞糕。三九已至勇吊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間窍仰,已是汗流浹背汉规。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留驹吮,地道東北人针史。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像碟狞,于是被迫代替她去往敵國(guó)和親啄枕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容