前言
什么是 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ù)治理框架。
組件選擇
版本選擇
開發(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
父POM可以刪除不需要的文件(父項(xiàng)目只需要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項(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/feign和http://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