Seata(分布式事务实例环境搭建)

文章目录

    • 1.基本介绍
        • 1.引出Seata
        • 2.问题分析
    • 2.Seata的安装和配置
        • 1.解压到d盘
        • 2.修改D:\seata\conf\file.conf文件
          • 1.修改事务组
          • 2.修改日志存储模式为db
          • 3.修改数据库(MySQL5.7)连接信息
          • 4.创建seata数据库
          • 5.复制db_store.sql的内容,创建需要的表
          • 6.修改registry.conf 配置注册中心nacos
        • 3.启动测试
          • 1.启动nacos
          • 2.双击seata-server.bat,启动seata-server
          • 3.输入http://192.168.137.1:8848/nacos/index.html查看注册情况
          • 4.这个seata也是一个微服务,注册到Nacos
    • 3.Seata分布式事务应用实例
        • 1.工作流程分析
        • 2.数据库表设计
          • 1.订单微服务的数据库
          • 2.库存微服务的数据库
          • 3.账号微服务的数据库
          • 4.检查数据库信息
          • 5.分别为三个库创建对应的回滚日志表
            • 1.脚本在seata的conf目录下 db_undo_log.sql
            • 2.复制脚本为三个数据库创建回滚日志表
            • 3.完整脚本
          • 6.检查数据库信息
        • 3.微服务模块 seata_storage_micro_service-10010
          • netstat -aon | findstr :<端口号> 可以查看端口是否被占用
          • 1.新建子模块
          • 2.检查父子pom.xml
          • 3.pom.xml引入依赖
          • 4.application.yml
          • 5.D:\seata\conf\file.conf 配置事务组和seata服务的ip+端口和db(前面都配置了)![image-20240331112135077](https://img-blog.csdnimg.cn/img_convert/9406fa41f2321367d0e94d12bfcd3c49.png)
          • 6.再将这个文件复制到src/main/resources下,然后修改这行,seata的服务ip+端口以及db根据实际情况修改
          • 7.复制D:\seata\conf\registry.conf到src/main/resources下,然后配置注册中心nacos(前面也配过,直接复制即可)
          • 8.最终的文件目录
          • 9.com/sun/springcloud/entity/Storage.java 创建实体类
          • 10.com/sun/springcloud/dao/StorageDao.java 创建dao层
          • 11.mapper/StorageMapper.xml 实现接口的方法
          • 12.com/sun/springcloud/service/StorageService.java 编写service层接口
          • 13.com/sun/springcloud/service/Impl/StorageServiceImpl.java 编写service层实现类
          • 14.com/sun/springcloud/controller/StorageController.java 编写controller
          • 15.com/sun/springcloud/config/MyBatisConfig.java 配置类,依赖注入所有Mapper接口(不用加@Mapper注解了)
          • 16.com/sun/springcloud/config/DataSourceProxyConfig.java 配置数据源代理为 seata
          • 17.com/sun/springcloud/SeataStorageMicroServiceApplication10010.java 创建主启动类
          • 18.测试
            • 1.启动nacos和seata
            • 2.运行主启动类,并从nacos查看注册情况(如果有报错,先全部重启一下)
            • 3.测试controller
        • 4.微服务模块 seata_account_micro_service-10012
          • 1.新建子模块
          • 2.检查父子pom.xml
          • 3.pom.xml 引入依赖
          • 4.application.yml
          • 5.拷贝10010的两个配置文件
          • 6.com/sun/springcloud/entity/Account.java 创建实体类
          • 7.com/sun/springcloud/dao/AccountDao.java 创建Mapper接口
          • 8.mapper/AccountMapper.xml 创建Mapper.xml
          • 9.com/sun/springcloud/service/AccountService.java 编写service的接口
          • 10.com/sun/springcloud/service/Impl/AccountServiceImpl.java 编写service实现类
          • 11.com/sun/springcloud/controller/AccountController.java 编写controller层
          • 12.将10010的两个配置文件粘贴过来
          • 13.编写主启动类
          • 14.测试
            • 1.启动nacos和seata
            • 2.运行主启动类,并从nacos查看注册情况(如果有报错,先全部重启一下)
            • 3.测试controller
        • 5.微服务模块 seata-order-micro-service-10008
          • 1.新建子模块
          • 2.检查父子pom.xml
          • 3.pom.xml引入依赖
          • 4.application.yml
          • 5.将两个配置文件粘贴过来
          • 6.com/sun/springcloud/entity/Order.java 创建实体类
          • 7.com/sun/springcloud/dao/OrderDao.java 编写Mapper接口
          • 8.mapper/OrderMapper.xml 编写Mapper.xml
          • 9.service层思路分析
          • 10.com/sun/springcloud/service/OrderService.java 编写service接口
          • 11.com/sun/springcloud/service/AccountService.java 声明要远程调用AccountController.java的接口
          • 12.com/sun/springcloud/service/StorageService.java 声明要远程调用StorageController.java的接口
          • 13.com/sun/springcloud/service/Impl/OrderServiceImpl.java 编写service实现类
          • 14.com/sun/springcloud/controller/OrderController.java 编写controller
          • 15.将两个配置类复制过来
          • 16.编写主启动类
          • 17.测试
            • 1.启动nacos和seata
            • 2.运行主启动类,并从nacos查看注册情况(如果有报错,先全部重启一下)
            • 3.启动报错
            • 4.解决问题
            • 5.再次运行,查看nacos注册情况

1.基本介绍

1.引出Seata

image-20240331093340192

image-20240331093350132

2.问题分析

image-20240331093410759

2.Seata的安装和配置

1.解压到d盘

image-20240331093959650

2.修改D:\seata\conf\file.conf文件
1.修改事务组

image-20240331094307051

2.修改日志存储模式为db

image-20240331094402339

3.修改数据库(MySQL5.7)连接信息

在这里插入图片描述

4.创建seata数据库
# 创建数据库 seata
create database seata;
use seata;
5.复制db_store.sql的内容,创建需要的表

image-20240331095307621

# 创建表
-- the table to store GlobalSession data
drop table if exists `global_table`;
create table `global_table` (`xid` varchar(128)  not null,`transaction_id` bigint,`status` tinyint not null,`application_id` varchar(32),`transaction_service_group` varchar(32),`transaction_name` varchar(128),`timeout` int,`begin_time` bigint,`application_data` varchar(2000),`gmt_create` datetime,`gmt_modified` datetime,primary key (`xid`),key `idx_gmt_modified_status` (`gmt_modified`, `status`),key `idx_transaction_id` (`transaction_id`)
);-- the table to store BranchSession data
drop table if exists `branch_table`;
create table `branch_table` (`branch_id` bigint not null,`xid` varchar(128) not null,`transaction_id` bigint ,`resource_group_id` varchar(32),`resource_id` varchar(256) ,`lock_key` varchar(128) ,`branch_type` varchar(8) ,`status` tinyint,`client_id` varchar(64),`application_data` varchar(2000),`gmt_create` datetime,`gmt_modified` datetime,primary key (`branch_id`),key `idx_xid` (`xid`)
);-- the table to store lock data
drop table if exists `lock_table`;
create table `lock_table` (`row_key` varchar(128) not null,`xid` varchar(96),`transaction_id` long ,`branch_id` long,`resource_id` varchar(256) ,`table_name` varchar(32) ,`pk` varchar(36) ,`gmt_create` datetime ,`gmt_modified` datetime,primary key(`row_key`)
);
6.修改registry.conf 配置注册中心nacos

image-20240331095851458

image-20240331095834040

3.启动测试
1.启动nacos

image-20240331101309947

2.双击seata-server.bat,启动seata-server

image-20240331101333118

image-20240331101319741

3.输入http://192.168.137.1:8848/nacos/index.html查看注册情况

image-20240331101410953

4.这个seata也是一个微服务,注册到Nacos

image-20240331101502110

3.Seata分布式事务应用实例

1.工作流程分析

image-20240331102145235

2.数据库表设计
1.订单微服务的数据库
-- 订单微服务的数据库
CREATE DATABASE order_micro_service;
USE order_micro_service;
# 查看目前正在使用的数据库
select database();
# 创建订单表
CREATE TABLE `order`(id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,user_id BIGINT DEFAULT NULL ,product_id BIGINT DEFAULT NULL ,nums INT DEFAULT NULL ,money INT DEFAULT NULL,`status` INT DEFAULT NULL COMMENT '0:创建中; 1:已完结' );
select * from `order`;
2.库存微服务的数据库
-- 库存微服务的数据库
CREATE DATABASE storage_micro_service;
USE storage_micro_service;
CREATE TABLE `storage`(id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,product_id BIGINT DEFAULT NULL ,amount INT DEFAULT NULL COMMENT '库存量' );
-- 初始化库存表
INSERT INTO `storage` VALUES(NULL, 1, 10);
SELECT * FROM `storage`;
3.账号微服务的数据库
-- 账号微服务的数据库
CREATE DATABASE account_micro_service;
USE account_micro_service;
CREATE TABLE `account`(id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY ,user_id BIGINT DEFAULT NULL ,money INT DEFAULT NULL COMMENT '账户金额' );
-- 初始化账户表
INSERT INTO `account` VALUES(NULL, 666, 10000);
select * from `account`;
4.检查数据库信息

image-20240331103557149

5.分别为三个库创建对应的回滚日志表
1.脚本在seata的conf目录下 db_undo_log.sql

image-20240331103729957

2.复制脚本为三个数据库创建回滚日志表
CREATE TABLE `undo_log` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`branch_id` bigint(20) NOT NULL,`xid` varchar(100) NOT NULL,`context` varchar(128) NOT NULL,`rollback_info` longblob NOT NULL,`log_status` int(11) NOT NULL,`log_created` datetime NOT NULL,`log_modified` datetime NOT NULL,`ext` varchar(100) DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
3.完整脚本
use order_micro_service;
CREATE TABLE `undo_log`
(`id`            bigint(20)   NOT NULL AUTO_INCREMENT,`branch_id`     bigint(20)   NOT NULL,`xid`           varchar(100) NOT NULL,`context`       varchar(128) NOT NULL,`rollback_info` longblob     NOT NULL,`log_status`    int(11)      NOT NULL,`log_created`   datetime     NOT NULL,`log_modified`  datetime     NOT NULL,`ext`           varchar(100) DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDBAUTO_INCREMENT = 1DEFAULT CHARSET = utf8;use storage_micro_service;
CREATE TABLE `undo_log`
(`id`            bigint(20)   NOT NULL AUTO_INCREMENT,`branch_id`     bigint(20)   NOT NULL,`xid`           varchar(100) NOT NULL,`context`       varchar(128) NOT NULL,`rollback_info` longblob     NOT NULL,`log_status`    int(11)      NOT NULL,`log_created`   datetime     NOT NULL,`log_modified`  datetime     NOT NULL,`ext`           varchar(100) DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDBAUTO_INCREMENT = 1DEFAULT CHARSET = utf8;use account_micro_service;
CREATE TABLE `undo_log`
(`id`            bigint(20)   NOT NULL AUTO_INCREMENT,`branch_id`     bigint(20)   NOT NULL,`xid`           varchar(100) NOT NULL,`context`       varchar(128) NOT NULL,`rollback_info` longblob     NOT NULL,`log_status`    int(11)      NOT NULL,`log_created`   datetime     NOT NULL,`log_modified`  datetime     NOT NULL,`ext`           varchar(100) DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDBAUTO_INCREMENT = 1DEFAULT CHARSET = utf8
6.检查数据库信息

image-20240331104254360

3.微服务模块 seata_storage_micro_service-10010
netstat -aon | findstr :<端口号> 可以查看端口是否被占用

image-20240331104939353

1.新建子模块

image-20240331105031899

2.检查父子pom.xml

image-20240331105106185

image-20240331105117331

3.pom.xml引入依赖
  • 注意这里引入的nacos是nacos-discovery starter,没有整合Seata之前引入的跟这个不一样!!!
    <dependencies><!-- 提示 application.yml --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><!-- 引入 openfeign --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!-- 在微服务模块引入 nacos-discovery starter --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--seata--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId><exclusions><!-- 排除自带的 seata-all --><exclusion><artifactId>seata-all</artifactId><groupId>io.seata</groupId></exclusion></exclusions></dependency><!-- 引入指定版本的 io.seata --><dependency><groupId>io.seata</groupId><artifactId>seata-all</artifactId><version>0.9.0</version></dependency><!-- springboot web starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><!-- 如果在子工程/模块指定了 version,则以指定为准 --></dependency><!--1. starter-actuator 是 springboot 程序的监控系统,可以实现健康检查,info 信息等2. 访问 http://localhost:10000/actuator 可以看到相关链接, 还可以做相关设置. --><!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!-- mybatis --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><!-- druid --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><!-- 这里我们重新指定一下 version 因为父项目中没有对这个依赖进行版本仲裁--><version>1.1.13</version></dependency><!-- mysql --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- jdbc --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><!-- lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- test --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- 公共模块的jar包 --><dependency><groupId>org.example</groupId><artifactId>e_commerce_center-common-api</artifactId><version>1.0-SNAPSHOT</version></dependency></dependencies>
4.application.yml
server:port: 10010 # 配置服务端口
spring:application:name: seata-storage-micor-service # 配置服务的名称,名字任意这里与项目名保持一致cloud:alibaba:seata:  # 配置seatatx-service-group: sun_order_tx_group # 自定义事务组名称,与\conf\file.conf保持一致nacos: # 配置nacosdiscovery:server-addr: localhost:8848datasource: # 配置数据源driver-class-name: com.mysql.jdbc.Driver# 别忘记创建数据库之后修改数据库名称url: username: password:
logging:  # 配置seata日志级别level:io:seata: info
mybatis:mapperLocations: classpath:mapper/*.xml # 扫描所有Mapper.xmlconfiguration:map-underscore-to-camel-case: true # 开启驼峰命名
5.D:\seata\conf\file.conf 配置事务组和seata服务的ip+端口和db(前面都配置了)image-20240331112135077
6.再将这个文件复制到src/main/resources下,然后修改这行,seata的服务ip+端口以及db根据实际情况修改

image-20240331112838536

7.复制D:\seata\conf\registry.conf到src/main/resources下,然后配置注册中心nacos(前面也配过,直接复制即可)

image-20240331113355613

8.最终的文件目录

image-20240331113408627

9.com/sun/springcloud/entity/Storage.java 创建实体类
package com.sun.springcloud.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** Description: 库存实体类** @Author sun* @Create 2024/3/31 11:41* @Version 1.0*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Storage {private Long id;private Long productId; // 这里使用的驼峰命名法,数据库中使用的是下划线命名法,可以自动映射private Integer amount;
}
10.com/sun/springcloud/dao/StorageDao.java 创建dao层
  • 注意这里的@Param注解一旦指定,就不需要在xml实现的时候指定参数类型了,直接使用#{}来取出数据即可
package com.sun.springcloud.dao;import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;/*** Description:** @Author sun* @Create 2024/3/31 11:50* @Version 1.0*/
@Mapper
public interface StorageDao {//扣减库存信息,这里的@Param注解的作用是给参数命名,这样在xml文件中就可以直接使用该名称void reduce(@Param("productId") Long productId, @Param("nums") Integer nums);
}
11.mapper/StorageMapper.xml 实现接口的方法
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sun.springcloud.dao.StorageDao"><resultMap id="BaseResultMap" type="com.sun.springcloud.entity.Storage"><id column="id" property="id" jdbcType="BIGINT"/><result column="product_id" property="productId" jdbcType="BIGINT"/><result column="amount" property="amount" jdbcType="INTEGER"/></resultMap>
<!--实现void reduce(@Param("productId") Long productId, @Param("nums") Integer nums);--><update id="reduce">UPDATE storageSET amount = amount - #{nums}WHERE product_id = #{productId}</update></mapper>
12.com/sun/springcloud/service/StorageService.java 编写service层接口
package com.sun.springcloud.service;/*** Description:** @Author sun* @Create 2024/3/31 13:01* @Version 1.0*/
public interface StorageService {void reduce(Long productId, Integer nums);
}
13.com/sun/springcloud/service/Impl/StorageServiceImpl.java 编写service层实现类
package com.sun.springcloud.service.Impl;import com.sun.springcloud.dao.StorageDao;
import com.sun.springcloud.service.StorageService;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;import javax.annotation.Resource;/*** Description:** @Author sun* @Create 2024/3/31 13:02* @Version 1.0*/
@Service
@Slf4j
public class StorageServiceImpl implements StorageService {@Resourceprivate StorageDao storageDao;private static final Logger LOGGER =LoggerFactory.getLogger(StorageServiceImpl.class);@Overridepublic void reduce(Long productId, Integer nums) {LOGGER.info("==========seata_storage_micro_service-10010 扣 减 库 存 start==========");storageDao.reduce(productId, nums);LOGGER.info("==========seata_storage_micro_service-10010 扣 减 库 存 end==========");}
}
14.com/sun/springcloud/controller/StorageController.java 编写controller
package com.sun.springcloud.controller;import com.sun.springcloud.service.StorageService;
import com.sun.springcloud.util.Result;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;/*** Description:** @Author sun* @Create 2024/3/31 13:07* @Version 1.0*/
@RestController
public class StorageController {@Resourceprivate StorageService storageService;//扣减库存@RequestMapping("/storage/reduce")public Result reduce(Long productId, Integer nums) {storageService.reduce(productId, nums);return Result.success("扣减库存成功 ok", null);}
}
15.com/sun/springcloud/config/MyBatisConfig.java 配置类,依赖注入所有Mapper接口(不用加@Mapper注解了)
package com.sun.springcloud.config;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;/*** Description: MyBatis配置类,扫描所有Mapper接口,这样就不用在每个Mapper接口上添加@Mapper注解** @Author sun* @Create 2024/3/31 13:16* @Version 1.0*/
@MapperScan("com.sun.springcloud.dao")
@Configuration
public class MyBatisConfig {
}
16.com/sun/springcloud/config/DataSourceProxyConfig.java 配置数据源代理为 seata
package com.sun.springcloud.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.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import javax.sql.DataSource;/*** Description: 配置数据源的代理是 seata** @Author sun* @Create 2024/3/31 13:28* @Version 1.0*/
@Configuration
public class DataSourceProxyConfig {// 配置文件中的mybatis.mapperLocations@Value("${mybatis.mapperLocations}")private String mapperLocations; // mybatis的mapper文件位置// 配置数据源@Bean@ConfigurationProperties(prefix = "spring.datasource") // 读取配置文件中的数据源配置public DataSource druidDataSource() {return new DruidDataSource();}// 配置数据源代理为seata的DataSourceProxy@Bean // 配置数据源代理引入的包: io.seata.rm.datasource.DataSourceProxypublic DataSourceProxy dataSourceProxy(DataSource dataSource) {return new DataSourceProxy(dataSource);}// 配置SqlSessionFactory为seata的SqlSessionFactoryBean@Bean // 配置SqlSessionFactory,常规配置public SqlSessionFactory sqlSessionFactoryBean(DataSourceProxy dataSourceProxy)throws Exception {SqlSessionFactoryBean sqlSessionFactoryBean =new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSourceProxy);sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations)); // mybatis的mapper文件位置sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());return sqlSessionFactoryBean.getObject();}
}
17.com/sun/springcloud/SeataStorageMicroServiceApplication10010.java 创建主启动类
package com.sun.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;/*** Description:** @Author sun* @Create 2024/3/31 13:37* @Version 1.0*/
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) // 取消数据源的自动创建,使用代理数据源
@EnableDiscoveryClient // 开启服务发现
@EnableFeignClients // 开启Feign客户端
public class SeataStorageMicroServiceApplication10010 {public static void main(String[] args) {SpringApplication.run(SeataStorageMicroServiceApplication10010.class, args);}
}
18.测试
1.启动nacos和seata
2.运行主启动类,并从nacos查看注册情况(如果有报错,先全部重启一下)

image-20240331134531958

3.测试controller

image-20240331142326632

4.微服务模块 seata_account_micro_service-10012
1.新建子模块

image-20240331143146853

2.检查父子pom.xml

image-20240331143229518

image-20240331143308804

3.pom.xml 引入依赖
    <dependencies><!-- 提示 application.yml --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><!-- 引入 openfeign --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!-- 在微服务模块引入 nacos-discovery starter --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--seata--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId><exclusions><!-- 排除自带的 seata-all --><exclusion><artifactId>seata-all</artifactId><groupId>io.seata</groupId></exclusion></exclusions></dependency><!-- 引入指定版本的 io.seata --><dependency><groupId>io.seata</groupId><artifactId>seata-all</artifactId><version>0.9.0</version></dependency><!-- springboot web starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><!-- 如果在子工程/模块指定了 version,则以指定为准 --></dependency><!--1. starter-actuator 是 springboot 程序的监控系统,可以实现健康检查,info 信息等2. 访问 http://localhost:10000/actuator 可以看到相关链接, 还可以做相关设置. --><!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!-- mybatis --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><!-- druid --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><!-- 这里我们重新指定一下 version 因为父项目中没有对这个依赖进行版本仲裁--><version>1.1.13</version></dependency><!-- mysql --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- jdbc --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><!-- lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- test --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- 公共模块的jar包 --><dependency><groupId>org.example</groupId><artifactId>e_commerce_center-common-api</artifactId><version>1.0-SNAPSHOT</version></dependency></dependencies>
4.application.yml
server:port: 10012 # 配置服务端口
spring:application:name: seata-account-micor-service # 配置服务的名称,名字任意这里与项目名保持一致cloud:alibaba:seata:  # 配置seatatx-service-group: sun_order_tx_group # 自定义事务组名称,与\conf\file.conf保持一致nacos: # 配置nacosdiscovery:server-addr: localhost:8848datasource: # 配置数据源driver-class-name: com.mysql.jdbc.Driver# 别忘记创建数据库之后修改数据库名称url: username: password: 
logging:  # 配置seata日志级别level:io:seata: info
mybatis:mapperLocations: classpath:mapper/*.xml # 扫描所有Mapper.xmlconfiguration:map-underscore-to-camel-case: true # 开启驼峰命名
5.拷贝10010的两个配置文件

image-20240331144400717

6.com/sun/springcloud/entity/Account.java 创建实体类
package com.sun.springcloud.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** Description:** @Author sun* @Create 2024/3/31 14:46* @Version 1.0*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Account {private Long id;private Long userId;private Integer money;
}
7.com/sun/springcloud/dao/AccountDao.java 创建Mapper接口
package com.sun.springcloud.dao;import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;/*** Description:** @Author sun* @Create 2024/3/31 14:48* @Version 1.0*/
@Mapper
public interface AccountDao {void reduce(@Param("userId") Long userId, @Param("money") Integer money);
}
8.mapper/AccountMapper.xml 创建Mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sun.springcloud.dao.AccountDao"><resultMap id="BaseResultMap" type="com.sun.springcloud.entity.Account"><id column="id" property="id" jdbcType="BIGINT"/><result column="user_id" property="userId" jdbcType="BIGINT"/><result column="money" property="money" jdbcType="INTEGER"/></resultMap><!-- 扣减金额 --><update id="reduce">UPDATE accountSETmoney = money - #{money}WHEREuser_id = #{userId};</update>
</mapper>
9.com/sun/springcloud/service/AccountService.java 编写service的接口
package com.sun.springcloud.service;/*** Description:** @Author sun* @Create 2024/3/31 14:59* @Version 1.0*/public interface AccountService {void reduce(Long userId, Integer money);
}
10.com/sun/springcloud/service/Impl/AccountServiceImpl.java 编写service实现类
package com.sun.springcloud.service.Impl;/*** Description:** @Author sun* @Create 2024/3/31 15:01* @Version 1.0*/import com.sun.springcloud.dao.AccountDao;
import com.sun.springcloud.service.AccountService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
@Service
public class AccountServiceImpl implements AccountService {private static final Logger LOGGER =LoggerFactory.getLogger(AccountServiceImpl.class);@ResourceAccountDao accountDao;@Overridepublic void reduce(Long userId, Integer money) {LOGGER.info("========seata_account_micro_service-10012 扣减账户余额 start ======");accountDao.reduce(userId,money);LOGGER.info("========seata_account_micro_service-10012 扣减账户余额 end ======");}
}
11.com/sun/springcloud/controller/AccountController.java 编写controller层
package com.sun.springcloud.controller;/*** Description:** @Author sun* @Create 2024/3/31 15:07* @Version 1.0*/import com.sun.springcloud.service.AccountService;
import com.sun.springcloud.util.Result;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;@RestController
public class AccountController {@ResourceAccountService accountService;/*** 扣减账户余额*/@RequestMapping("/account/reduce")public Result result(@RequestParam("userId") Long userId, @RequestParam("money") Integer money){accountService.reduce(userId,money);return Result.success("200", "扣减账户余额 OK");}
}
12.将10010的两个配置文件粘贴过来

image-20240331151617636

13.编写主启动类
package com.sun.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;/*** Description:** @Author sun* @Create 2024/3/31 15:17* @Version 1.0*/
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})  // 取消数据源的自动配置,使用seata代理数据源配置
@EnableFeignClients // 开启Feign
@EnableDiscoveryClient // 开启服务发现
public class SeataAccountMicroServiceApplication10012 {public static void main(String[] args) {SpringApplication.run(SeataAccountMicroServiceApplication10012.class, args);}}
14.测试
1.启动nacos和seata
2.运行主启动类,并从nacos查看注册情况(如果有报错,先全部重启一下)

image-20240331153110430

3.测试controller

image-20240331153103501

5.微服务模块 seata-order-micro-service-10008
1.新建子模块

image-20240331153640908

2.检查父子pom.xml

image-20240331153833981

image-20240331153843676

3.pom.xml引入依赖
    <dependencies><!-- 提示 application.yml --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><!-- 引入 openfeign --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!-- 在微服务模块引入 nacos-discovery starter --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--seata--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId><exclusions><!-- 排除自带的 seata-all --><exclusion><artifactId>seata-all</artifactId><groupId>io.seata</groupId></exclusion></exclusions></dependency><!-- 引入指定版本的 io.seata --><dependency><groupId>io.seata</groupId><artifactId>seata-all</artifactId><version>0.9.0</version></dependency><!-- springboot web starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><!-- 如果在子工程/模块指定了 version,则以指定为准 --></dependency><!--1. starter-actuator 是 springboot 程序的监控系统,可以实现健康检查,info 信息等2. 访问 http://localhost:10000/actuator 可以看到相关链接, 还可以做相关设置. --><!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!-- mybatis --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><!-- druid --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><!-- 这里我们重新指定一下 version 因为父项目中没有对这个依赖进行版本仲裁--><version>1.1.13</version></dependency><!-- mysql --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- jdbc --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><!-- lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- test --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- 公共模块的jar包 --><dependency><groupId>org.example</groupId><artifactId>e_commerce_center-common-api</artifactId><version>1.0-SNAPSHOT</version></dependency></dependencies>
4.application.yml
server:port: 10008 # 配置服务端口
spring:application:name: seata-order-micor-service # 配置服务的名称,名字任意这里与项目名保持一致cloud:alibaba:seata:  # 配置seatatx-service-group: sun_order_tx_group # 自定义事务组名称,与\conf\file.conf保持一致nacos: # 配置nacosdiscovery:server-addr: localhost:8848datasource: # 配置数据源driver-class-name: com.mysql.jdbc.Driver# 别忘记创建数据库之后修改数据库名称url: username: password: 
logging:  # 配置seata日志级别level:io:seata: info
mybatis:mapperLocations: classpath:mapper/*.xml # 扫描所有Mapper.xmlconfiguration:map-underscore-to-camel-case: true # 开启驼峰命名
5.将两个配置文件粘贴过来

image-20240331154514691

6.com/sun/springcloud/entity/Order.java 创建实体类
package com.sun.springcloud.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** Description:** @Author sun* @Create 2024/3/31 15:48* @Version 1.0*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order {private Long id;private Long userId;private Long productId;private Integer nums;private Integer money;private Integer status;
}
7.com/sun/springcloud/dao/OrderDao.java 编写Mapper接口
package com.sun.springcloud.dao;/*** Description:** @Author sun* @Create 2024/3/31 15:51* @Version 1.0*/import com.sun.springcloud.entity.Order;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;@Mapper
public interface OrderDao {//新建订单void save(Order order);//修改订单状态void update(@Param("userId") Long userId, @Param("status") Integer status);
}
8.mapper/OrderMapper.xml 编写Mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sun.springcloud.dao.OrderDao"><resultMap id="BaseResultMap" type="com.sun.springcloud.entity.Order"><id column="id" property="id" jdbcType="BIGINT"/><result column="user_id" property="userId" jdbcType="BIGINT"/><result column="product_id" property="productId" jdbcType="BIGINT"/><result column="nums" property="nums" jdbcType="INTEGER"/><result column="money" property="money" jdbcType="INTEGER"/><result column="status" property="status" jdbcType="INTEGER"/></resultMap><insert id="save">insert into `order` (id, user_id, product_id, nums, money, status)values (null, #{userId}, #{productId}, #{nums}, #{money}, 0);</insert><update id="update">update `order`set status = 1where user_id = #{userId}and status = #{status};</update>
</mapper>
9.service层思路分析

image-20240331160559684

10.com/sun/springcloud/service/OrderService.java 编写service接口
package com.sun.springcloud.service;import com.sun.springcloud.entity.Order;/*** Description:** @Author sun* @Create 2024/3/31 16:09* @Version 1.0*/
public interface OrderService {void save(Order order);
}
11.com/sun/springcloud/service/AccountService.java 声明要远程调用AccountController.java的接口
package com.sun.springcloud.service;import com.sun.springcloud.util.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;/*** Description:** @Author sun* @Create 2024/3/31 16:13* @Version 1.0*/
@FeignClient(value = "seata-account-micor-service")
public interface AccountService {@RequestMapping("/account/reduce")public Result result(@RequestParam("userId") Long userId, @RequestParam("money") Integer money);
}
12.com/sun/springcloud/service/StorageService.java 声明要远程调用StorageController.java的接口
package com.sun.springcloud.service;import com.sun.springcloud.util.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;/*** Description:** @Author sun* @Create 2024/3/31 16:19* @Version 1.0*/
@FeignClient(value = "seata-storage-micor-service")
public interface StorageService {@RequestMapping("/storage/reduce")public Result reduce(Long productId, Integer nums);
}
13.com/sun/springcloud/service/Impl/OrderServiceImpl.java 编写service实现类
package com.sun.springcloud.service.Impl;import com.sun.springcloud.dao.OrderDao;
import com.sun.springcloud.entity.Order;
import com.sun.springcloud.service.AccountService;
import com.sun.springcloud.service.OrderService;
import com.sun.springcloud.service.StorageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;import javax.annotation.Resource;/*** Description:** @Author sun* @Create 2024/3/31 16:48* @Version 1.0*/
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {@Resource // 注入OrderDao对象private OrderDao orderDao;@Resource // 注入针对接口的代理对象,这里是AccountService接口的代理对象,进行远程调用private AccountService accountService;@Resource // 注入针对接口的代理对象,这里是StorageService接口的代理对象,进行远程调用private StorageService storageService;@Overridepublic void save(Order order) {log.info("----->下单开始");log.info("----->本地生成订单开始");// 1.保存订单orderDao.save(order);log.info("----->本地生成订单结束");log.info("----->订单微服务开始调用账户,扣减账户余额开始");// 2.调用远程服务,扣减账户余额accountService.result(order.getUserId(), order.getMoney());log.info("----->订单微服务开始调用账户,扣减账户余额结束");log.info("----->订单微服务开始调用库存,扣减库存开始");// 3.调用远程服务,扣减库存storageService.reduce(order.getProductId(), order.getNums());log.info("----->订单微服务开始调用库存,扣减库存结束");log.info("----->修改订单状态开始");// 4.修改订单状态orderDao.update(order.getUserId(), 0);log.info("----->修改订单状态结束");log.info("----->下单结束");}
}
14.com/sun/springcloud/controller/OrderController.java 编写controller
package com.sun.springcloud.controller;import com.sun.springcloud.entity.Order;
import com.sun.springcloud.service.OrderService;
import com.sun.springcloud.util.Result;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;/*** Description:** @Author sun* @Create 2024/3/31 17:06* @Version 1.0*/
@RestController
public class OrderController {@Resource // 依赖注入针对接口的代理对象,这里是OrderService接口的代理对象private OrderService orderService;@GetMapping("/order/save")public Result save(Order order) { // 这里没有使用@RequestBody注解,前端可以直接使用url传参orderService.save(order);return Result.success("订单创建成功", null);}
}
15.将两个配置类复制过来

image-20240331190555254

16.编写主启动类
package com.sun.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;/*** Description:** @Author sun* @Create 2024/3/31 19:09* @Version 1.0*/
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) // 排除数据源的自动配置
@EnableDiscoveryClient
@EnableFeignClients
public class SeataOrderMicroServiceApplication10008 {public static void main(String[] args) {SpringApplication.run(SeataOrderMicroServiceApplication10008.class, args);}
}
17.测试
1.启动nacos和seata
2.运行主启动类,并从nacos查看注册情况(如果有报错,先全部重启一下)
3.启动报错
  • 这个显示是方法的参数有问题

image-20240331193701454

image-20240331194112655

4.解决问题

被远程调用的微服务模块的参数使用@RequestParam

image-20240331194929212

image-20240331194914004

远程调用微服务模块时也需要加上@RequestParam

image-20240331194958222

image-20240331195011063

  • 使用GET方式时,通常需要加@RequestParam:这是因为GET请求主要用于从服务器检索特定资源。在GET请求中,请求参数通常通过URL的查询字符串部分传递,而@RequestParam正是用于处理这类参数的。它告诉Spring框架如何从请求的查询参数映射值到方法的参数上。
  • 使用POST方式时,通常需要加@RequestBody:POST请求通常用于向服务器提交数据,这些数据作为请求的主体发送。@RequestBody注解允许你的方法接收一个来自客户端的JSON(或其他格式)请求体,并将其反序列化为Java对象。这意味着客户端可以发送复杂的数据结构作为请求体的一部分,而服务端可以直接操作这些数据结构的Java表示。
  • 总结就是在微服务中,如果使用controller使用get方式,则需要在参数中添加@RequestParam,如果controller中使用post方式,就需要在参数中添加@RequestBody
5.再次运行,查看nacos注册情况

image-20240331194831406

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/784983.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Web实例_报表开发01-基于HTML进行报表呈现

Web实例_报表开发01-基于HTML进行报表呈现 报表开发是一种在利用了软件的基础上, 针对不同类型的报表, 进行开放的工作。 而以报表的方式, 将相关的内容、数值呈现出来的话, 则会起到更好的概况作用。 再加上, 报表开发工作是依托于计算机来完成的, 因此在效率、完整性等方面…

红酒:分类视角下的红酒品质评估与标准制定

在红酒的世界中&#xff0c;品质的评估与标准的制定对于维护消费者权益、促进行业健康发展具有重要意义。云仓酒庄雷盛红酒作为业界持续发展品牌&#xff0c;从分类的视角出发&#xff0c;对红酒品质进行了多方的评估&#xff0c;并积极参与制定相关的标准。 首先&#xff0c;从…

优思学院|工程经理应如何利用PDCA循环?

作为工程经理&#xff0c;理解PDCA&#xff08;计划-执行-检查-行动&#xff09;质量管理循环程序对于确保项目质量和持续改进是十分重要。 PDCA 最早由美国质量管理专家 Walter A. Shewhart (1939)提出&#xff0c;其后被戴明博士&#xff08;Dr. Deming&#xff09;所采用、…

【Linux】权限理解

权限理解 1. shell命令以及运行原理2. Linux权限的概念3. Linux权限管理3.1 文件访问者的分类&#xff08;人&#xff09;3.2 文件类型和访问权限&#xff08;事物属性&#xff09;3.2.1 文件类型3.2.2 基本权限 3.3 文件权限值的表示方法3.4 文件访问权限的相关设置方法3.4.1 …

基于energy score的out-of-distribution数据检测,LeCun都说好 | NerulPS 2020

论文提出用于out-of-distributions输入检测的energy-based方案&#xff0c;通过非概率的energy score区分in-distribution数据和out-of-distribution数据。不同于softmax置信度&#xff0c;energy score能够对齐输入数据的密度&#xff0c;提升OOD检测的准确率&#xff0c;对算…

【JAVA】java基础(分支结构)洛谷刷题(含图解:吃苹果)

题目&#xff1a; 解析 代码 import java.util.Scanner;public class Main {public static void main(String[] args) {// TODO Auto-generated method stubScanner input new Scanner(System.in);int apple,time,rate; appleinput.nextInt(); rateinput.nextInt(); timeinpu…

专题【链表】刷题日记

题目列表 学习题(22题) 2024.03.31 两数相加 19. 删除链表的倒数第 N 个结点 合并K个升序链表 2024.04.01 24. 两两交换链表中的节点 25. K 个一组翻转链表 61. 旋转链表 83. 删除排序链表中的重复元素 82. 删除排序链表中的重复元素 II 86. 分隔链表 92. 反转链表 II 1…

【STM32嵌入式系统设计与开发】——14PWM(pwm脉宽输入应用)

这里写目录标题 一、任务描述二、任务实施1、WWDG工程文件夹创建2、函数编辑&#xff08;1&#xff09;主函数编辑&#xff08;2&#xff09;USART1初始化函数(usart1_init())&#xff08;3&#xff09;USART数据发送函数&#xff08; USART1_Send_Data&#xff08;&#xff09…

服务器安全事件应急响应排查方法

针对服务器操作系统的安全事件也非常多的。攻击方式主要是弱口令攻击、远程溢出攻击及其他应用漏洞攻击等。分析安全事件&#xff0c;找到入侵源&#xff0c;修复漏洞&#xff0c;总结经验&#xff0c;避免再次出现安全事件&#xff0c;以下是参考网络上文章&#xff0c;总结的…

初识编译和链接(C语言)

文章目录 编译和链接翻译环境预处理编译汇编链接 运行环境 编译和链接 编译和链接这两个大的过程构成了翻译环境。 其实&#xff0c;在ANSI C的任何一种实现中&#xff0c;存在两个不同的环境。 一个环境是翻译环境&#xff0c;另一个是执行环境。 翻译环境中&#xff0c;源…

【软件工程】详细设计(一)

1. 引言 1.1 编写目的 该文档的目的是描述《学生成绩管理系统》项目的详细设计&#xff0c;其主要内容包括&#xff1a; 系统功能简介 系统详细设计简述 各个模块的实现逻辑 最小模块组件的伪代码 本文档的预期的读者是&#xff1a; 开发人员 项目管理人员 测试人员 …

基于单片机汽车超声波防盗系统设计

**单片机设计介绍&#xff0c;基于单片机汽车超声波防盗系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机汽车超声波防盗系统设计概要主要涉及利用超声波传感器和单片机技术来实现汽车的安全防盗功能。以下是对…

八股 -- C#

面向对象 &#xff08;三大特性&#xff09; 三大特性目的是为了提供更好的代码组织、可维护性、扩展性和重用性 C#基础——面向对象 - 知乎 (zhihu.com) 封装 理解&#xff1a; 你不需要了解这个方法里面写了什么代码&#xff0c;你只需要了解这个方法能够给你返回什么数据&…

位运算 ----力扣2220

2220. 转换数字的最少位翻转次数 提示 一次 位翻转 定义为将数字 x 二进制中的一个位进行 翻转 操作&#xff0c;即将 0 变成 1 &#xff0c;或者将 1 变成 0 。 比方说&#xff0c;x 7 &#xff0c;二进制表示为 111 &#xff0c;我们可以选择任意一个位&#xff08;包含没有…

书生·浦语大模型-第一节课笔记

视频总结 23年发布的模型在一些材料中归位指令微调模型&#xff0c;后面逐渐升级应该已经是train的模型了 技术报告总结 InternLM2 Technical Report 评测与特点 6 dimensions and 30 benchmarks, long-context modeling, and open-ended subjective evaluations长文本…

猜数游戏(Python)

一、实验要求&#xff1a; &#xff08;1&#xff09;在游戏开始时&#xff0c;随机生成一个1~100之间的整数。 &#xff08;2&#xff09;在游戏中&#xff0c;玩家有10次机会猜数。如果10次都没有猜中&#xff0c;则游戏失败&#xff1b;否则&#xff0c;游戏成功。 &…

centos7.5安装gitlab-runner,配置CI/CD流水线

一般不建议gitlab-server和gitlab-runner装在同一台服务器 第一步&#xff1a;安装gitlab-runner,最好和gitlab实例版本一致 # 下载官方gitlab-runner安装脚本 curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh" | s…

成为一名自由程序员

越来越多的程序员已经或希望加入到自由职业者的行列&#xff0c;你是否也是其中的一员呢&#xff1f;在这篇文章里我将尝试结合自身的一些经验&#xff0c;来告诉你成为自由程序员能够获得的那些益处&#xff0c;以及为了取得成功所需要面临的挑战。 自由程序员的类型 很多人把…

项目开发---用户登录发送短信实现(使用阿里云短信接口)(看这篇就够了)

目录&#xff1a; 使用阿里云开通短信服务教程编写代码 使用阿里云开通短信服务教程 阿里云官网&#x1f449;https://cn.aliyun.com/ 完成登录 进入短信服务 开通短信服务 购买短信条数 购买完成进入阿里云短信控制台https://dysms.console.aliyun.com/overview 开通个…

Taskflow应用:波前并行(Wavefront Parallelism)

2D的Wavefront如下图所示&#xff1a; #include <taskflow/taskflow.hpp>std::mutex cout_mutex; void format_str(std::string const& str) {std::lock_guard<std::mutex> lock(cout_mutex); std::cout << str << std::endl; }std::string crea…