分布式事务篇-2.4 Spring-Boot整合Seata

news2024/9/28 9:28:23

文章目录

  • 前言
  • 一、pom jar导入:
  • 二、项目配置:
    • 2.1 配置 说明:
      • 2.1 .1 seata server 端:
      • 2.1 .2 seata client 端:
    • 2.2 开启seata 对于数据源的代理:
    • 2.3 seata-client 的注册中心:
    • 2.4 seata-client 的配置中心:
    • 2.5 去掉手写的数据源代理和feign代理:
  • 三、项目使用:
    • 3.1 AT 模式使用:
    • 3.2 XA 模式使用:
    • 3.3 TCC 模式使用:
  • 四、总结:
  • 五、参考:


前言

在了解了Seata 的工作原理后,如何在springboot 项目中进行整合使用,本文进行阐述。


提示:本文使用 seata 版本 :1.5 ;在整合之前 你需要先要部署seate 的服务

一、pom jar导入:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.14</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>spring-seata-storage</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-seata-storage</name>
    <description>spring-seata-storage</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <optional>true</optional>
            <version>3.1.6</version>
        </dependency>
        <!-- mysql -->
        <!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.21</version>
            <!-- <version>5.1.49</version>-->
        </dependency>
        <!-- https://mvnrepository.com/artifact/net.sf.jsqlparser/jsqlparser -->
        <dependency>
            <groupId>net.sf.jsqlparser</groupId>
            <artifactId>jsqlparser</artifactId>
            <version>0.8.0</version>
        </dependency>

        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-annotations</artifactId>
            <version>1.6.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.seata/seata-spring-boot-starter -->
       <!-- <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-spring-boot-starter</artifactId>
            <version>1.5.2</version>
        </dependency>-->
        <!--处理 在SpringBoot 2.4.x的版本之后,对于bootstrap.properties/bootstrap.yaml配置文件(我们合起来成为Bootstrap配置文件)的支持,
        需要导入如下的依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
            <version>3.1.6</version>
        </dependency>

        <!-- seata 使用nacos 作为配置中心和 注册中心时 使用  -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
            <version>2021.0.5.0</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>2021.0.5.0</version>
        </dependency>


        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <!-- 里面已经集成服务间调用X-id的传递,包括FeignClient的重写,如果在之前自定义封装过Feign,注意启动冲突-->
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
            <version>2021.0.5.0</version>
            <exclusions>
                <!--去除低版本-->
                <exclusion>
                    <groupId>io.seata</groupId>
                    <artifactId>seata-spring-boot-starter</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.seata/seata-spring-boot-starter -->
        <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-spring-boot-starter</artifactId>
            <version>1.6.1</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.example.springseata.springseatastorage</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

</project>

jar 目的:

  • spring-boot-starter-web: 使用 浏览器进行 http 访问;
  • lombok: 生成 get set 等方法,使代码更加简洁;
  • spring-boot-starter-test: 可以进行单元测试;
  • spring-cloud-starter-openfeign: 可以使用feign 接口进行服务间的http 通信;
  • mybatis-plus-boot-starte,mysql-connector-java ,jsqlparser:导入mysql-plus 进行 增删改查;
  • swagger-annotations: 类和方法的说明;
  • spring-cloud-starter-bootstrap :在SpringBoot 2.4.x的版本之后,对于bootstrap.properties/bootstrap.yaml配置文件(我们合起来成为Bootstrap配置文件)的支持;
  • spring-cloud-starter-alibaba-nacos: seata 使用nacos 作为配置中心和 注册中心时 使用;
  • spring-cloud-starter-alibaba-seata: 导入cloud对饮的jar 让其帮助进行 分布式事务xid 的传递;
  • seata-spring-boot-starter : seata 的核销服务jar;

springcloud ,springboot,springcloud-alibaba 版本对应:版本说明

二、项目配置:

2.1 配置 说明:

目的: 了解seat 客户端和服务端的 关系,清楚其配置的含义;

2.1 .1 seata server 端:

  • seata server 的存储模式:
    存储模式指定了Seata Server用于存储事务和元数据的方式,这个只有在seata 服务端才有。Seata Server支持三种存储模式:file、db和Redis。列如 当开始事务时需要生成全局事务id Xid ,在生成后就需要Seata 服务进行存储,所以他是Seata Server的重要组成部分;

  • seata server 的配置中心:
    配置中心的作用:用于配置 Seata Server的相关参数, Seata Server 端在启动的时候也可以配置很多参数,如果把这些参数都放到 Seata Server 中,每次修改度需要连接到Seata Server 的服务器,然后对其配置文件进行修改,如果把这个参数放到 配置中心如config ,zk,nacos 就可以在配置中心进行修改,更加的方便;

  • seata server 的注册中心:
    Seata Server 的注册中心是用于存储和管理 Seata 事务参与者的信息的组件;多个Seata Server 可以成为一个集群,然后注册到zk,eureka,nacos 里,这样方便集群的管理;

2.1 .2 seata client 端:

  • seata client 的配置中心:
    同seata-sever 端相同,客户端在启动的时候也可以进行参数的配置,所以可以在客户端我们也可以 将参数放到 config ,zk,nacos 进行配置;

  • seata client 的注册中心:
    seata 客户端的注册中心,用于服务端的发现,一个重要的信息就是,可以将seata 客户端和seata 服务端 注册到相同的地方,已nacos 为例:服务端和客户端 注册到相同命名空间,相同分组,相同应用,此时客户端会动态的发现 seata 服务的地址,此时不需要在显示的设置 seata 服务断的地址;
    Seata 客户端在启动时会从 Nacos 服务获取 service.vgroupMapping.your-service-group 定义的服务群组实例,这需要和 Seata 服务端的配置保持一致。以下三个参数需要和 Seata 服务端保持一致:application:, group, namespace

2.2 开启seata 对于数据源的代理:

目的:让 seata 接管数据源,然后才能协调各个微服务的本地事务;

seata:
  enabled: true # spring 自动装配
  enable-auto-data-source-proxy: true # 开启数据源自动代理
  transport:
    enable-client-batch-send-request: true #客户端事务消息请求是否批量合并发送,默认true,false单条发送
  tx-service-group: my_tx_group # 事务分组
  application-id: storage
  service:
    vgroup-mapping:
      my_tx_group: default
#    grouplist:
#      default: localhost:8091
  • tx-service-group 定义事务分组,可以自定义,多个微服务只有在同一个事务分组中,分布式事务才能生效,也就是多个微服务改参数要保持一致;
  • application-id 该服务事务id ,同一分组下的 的微服务 需要进行不同的定义;
  • servicevgroup-mapping 定义改事务分组 连接的seata 服务端 集群的名称,改名称需要和seata server 定义的集群名称保持一致;
    在这里插入图片描述
  • grouplist 中 default 为集群的名称,后面的为集群seata-server 端的地址,注意 这中连接模式只在 seata 客户端为 file 模式下生效; 其他方式如nacos ,需要配置使得 seata-server 和seata-client 都注册在相同命名空间,相同分组,相同application 下,这样seata-client 就可以动态的发现seata-server 的实例地址;

2.3 seata-client 的注册中心:

目的: 了解本地springboot 服务如何连接到 seata server 端

客户端和服务端 seata 都是默认已file 作为注册中心:

  • file
    seata-server 服务端 注册中心使用的file 本地模式,则seata 客户端 也需要使用file注册模式:
    此时需要配置 seata.service.grouplist.default=127.0.0.1:8091 用于客户端连接 seata 服务端;

  • nacos
    seata-server 服务端 注册中心使用的nacos,则seata 客户端 也需要使用nacos注册模式:

 seata-server 服务端 注册中心使用的nacos,则seata 客户端 也需要使用nacos注册模式:
seata:
  enabled: true # spring 自动装配
  enable-auto-data-source-proxy: true # 开启数据源自动代理
  transport:
    enable-client-batch-send-request: true #客户端事务消息请求是否批量合并发送,默认true,false单条发送
  tx-service-group: my_tx_group
  application-id: storage
  service:
    vgroup-mapping:
      my_tx_group: default
#    grouplist:
#      default: localhost:8091

  registry:
    #    type: file
    type: nacos
    nacos:
      application: seata-server
      server-addr: localhost:8848
      group: SEATA_GROUP
      namespace: 7f2765bc-d8c1-4b49-b706-8c292d2ffac9
      username: nacos
      password: nacos

注意 application,server-addr,group,namespace,username,password 客户端和服务端报纸一致;

2.4 seata-client 的配置中心:

目的: 了解本地springboot 如何对seata 进行参数配置

客户端和服务端 seata 都是默认已file 作为配置中心,他们的只是用作参数的配置使用,所以他们各自是独立的;

  • file
    seata 客户端的默认配置;
  • nacos
    使用nacos 作为配置中心 :
seata:
  enabled: true # spring 自动装配
  enable-auto-data-source-proxy: true # 开启数据源自动代理
  transport:
    enable-client-batch-send-request: true #客户端事务消息请求是否批量合并发送,默认true,false单条发送
  tx-service-group: my_tx_group
  application-id: storage
  service:
    vgroup-mapping:
      my_tx_group: default
#    grouplist:
#      default: localhost:8091
  config:
    type: nacos
#    type: file
    nacos:
      server-addr: localhost:8848
      namespace: c0befc56-f31b-4de6-929b-6f75604992d1
#      namespace: 7f2765bc-d8c1-4b49-b706-8c292d2ffac9
      group: DEFAULT_GROUP
      username: nacos
      password: nacos
      ##if use MSE Nacos with auth, mutex with username/password attribute
      #access-key: ""
      #secret-key: ""
      data-id: seata.properties

本文测试时虽然在 nacos 中创建了seata.properties 的配置文件但是其 配置的参数没有起作用;
在这里插入图片描述
会提示无法找到service.vgroupMapping.my_tx_group(my_tx_group 为定义的分组名称)的集群,通过创建 service.vgroupMapping.my_tx_group 配置文件 并且定义default 得以解决,目前没有找到其它解决办法;
在这里插入图片描述

2.5 去掉手写的数据源代理和feign代理:

  • seata DataSourceProxy 的代理:因为在其配置文件中已经开启了自动代理

seata:
  enabled: true # spring 自动装配
  enable-auto-data-source-proxy: true # 开启数据源自动代理
所以需要去重 手动加入的代理,防止冲突,导致 事务失效

在这里插入图片描述

  • feign 接口的代理:
    因为引入的spring-cloud-starter-alibaba-seata 已经对feign 进行了xid 的处理
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <!-- 里面已经集成服务间调用X-id的传递,包括FeignClient的重写,如果在之前自定义封装过Feign,注意启动冲突-->
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
    <version>2021.0.5.0</version>
    <exclusions>
        <!--去除低版本-->
        <exclusion>
            <groupId>io.seata</groupId>
            <artifactId>seata-spring-boot-starter</artifactId>
        </exclusion>
    </exclusions>
</dependency>

所以可以去除 手动增加的对于feign 接口xid 的特殊处理防止冲突:
在这里插入图片描述

三、项目使用:

3.1 AT 模式使用:

seata 客户端的事务模式默认使用AT 模式;通过以下两个步骤配置就可使用:

  • 在每个 数据库中增加undo_log 表,用于AT 模式事务日志记录使用:
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=8 DEFAULT CHARSET=utf8;
  • 在不同服务中都完成seata 的集群 ,然后在对应的业务实现中增加@GlobalTransactional(rollbackFor =
    Exception.class) 注解:
    在这里插入图片描述

3.2 XA 模式使用:

  • mysql 开启XA协议:
SHOW VARIABLES LIKE 'innodb_support_xa';

在这里插入图片描述
如果没有开通,则打开 MySQL 配置文件 my.cnf 或 my.ini。在文件中找到 [mysqld] 部分,并在该部分下添加以下行:

[mysqld]
innodb_support_xa = 1

保存配置文件并重启 MySQL 服务;

  • 显示设置 模式为XA 模式,代码层面无需变动;
 seata.data-source-proxy-mode=XA

3.3 TCC 模式使用:

根据两阶段行为模式的不同,我们将分支事务划分为 Automatic (Branch) Transaction Mode 和 TCC (Branch) Transaction Mode.

AT 模式(参考链接 TBD)基于 支持本地 ACID 事务 的 关系型数据库:

一阶段 prepare 行为:在本地事务中,一并提交业务数据更新和相应回滚日志记录。
二阶段 commit 行为:马上成功结束,自动 异步批量清理回滚日志。
二阶段 rollback 行为:通过回滚日志,自动 生成补偿操作,完成数据回滚。
相应的,TCC 模式,不依赖于底层数据资源的事务支持:

一阶段 prepare 行为:调用 自定义 的 prepare 逻辑。
二阶段 commit 行为:调用 自定义 的 commit 逻辑。
二阶段 rollback 行为:调用 自定义 的 rollback 逻辑。
所谓 TCC 模式,是指支持把 自定义 的分支事务纳入到全局事务的管理中。

  • tcc 事务记录表:tcc_fence_log
CREATE TABLE `tcc_fence_log` (
  `xid` varchar(128) NOT NULL COMMENT 'global id',
  `branch_id` bigint(20) NOT NULL COMMENT 'branch id',
  `action_name` varchar(64) NOT NULL COMMENT 'action name',
  `status` tinyint(4) NOT NULL COMMENT 'status(tried:1;committed:2;rollbacked:3;suspended:4)',
  `gmt_create` datetime(3) NOT NULL COMMENT 'create time',
  `gmt_modified` datetime(3) NOT NULL COMMENT 'update time',
  PRIMARY KEY (`xid`,`branch_id`),
  KEY `idx_gmt_modified` (`gmt_modified`),
  KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  • 订单服务 java demo:
    IOrderService:
public interface IOrderService extends IService<Order> {
    Boolean orderCreate(OrderReqDto reqDto);
}

实现类:

@Override
@GlobalTransactional(rollbackFor = Exception.class)
  public Boolean orderCreate(OrderReqDto reqDto) {
      log.error("Seata全局事务id=================>{}", RootContext.getXID());
      // stock服务未报错,order服务报错
      try {
          // 扣减库存-通过fegin 接口进行调用
          storageFeignApi.tccSumGoodNum(reqDto.getByGoods());
      } catch (Exception e) {
          e.printStackTrace();
          throw new RuntimeException(e);
      }

      // 订单创建
      Order order = new Order();
      order.setAccountId("123").setMoney(reqDto.getOrderMoney());
      this.save(order);
      return true;
  }

controller:

@ResponseBody
    @PostMapping("/tcc/sure")
    public Boolean orderCreate(@RequestBody OrderReqDto reqDto) throws SQLException {
        return orderService.orderCreate(reqDto);
    }
  • 库存服务 java demo:
    controller:
 @ResponseBody
    @PostMapping(value = "/tcc/sumGoodNum")
    public boolean tccSumGoodNum(@RequestBody List<GoodDto> param){
        return  tccStorageService.deduct(param);
    }

ITccStorageService:

package com.example.springseatastorage.service;


import com.example.springseatastorage.controller.dto.GoodDto;
import io.seata.rm.tcc.api.BusinessActionContext;
import io.seata.rm.tcc.api.BusinessActionContextParameter;
import io.seata.rm.tcc.api.LocalTCC;
import io.seata.rm.tcc.api.TwoPhaseBusinessAction;

import java.util.List;

@LocalTCC
public interface ITccStorageService {
    /**
     * 减库存
     * useTCCFence=true 为开启防悬挂
     * @param param
     */
    @TwoPhaseBusinessAction(name = "deduct", commitMethod = "busCommit", rollbackMethod = "busRollback", useTCCFence = true)
    boolean deduct(@BusinessActionContextParameter(paramName = "param")  List<GoodDto>param);

    /**
     * 提交事务
     *
     * @param actionContext
     * @return
     */
    boolean busCommit(BusinessActionContext actionContext);

    /**
     * 回滚事务
     *
     * @param actionContext
     * @return
     */
    boolean busRollback(BusinessActionContext actionContext);
}

ITccStorageServicempl:

package com.example.springseatastorage.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.springseatastorage.controller.dto.GoodDto;
import com.example.springseatastorage.entity.Storage;
import com.example.springseatastorage.service.IStorageService;
import com.example.springseatastorage.service.ITccStorageService;
import io.seata.core.context.RootContext;
import io.seata.rm.tcc.api.BusinessActionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ITccStorageServicempl implements ITccStorageService {
    @Autowired
    private IStorageService storageService;

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public boolean deduct(List<GoodDto> param) {
        log.error("Seata全局事务id=================>{}", RootContext.getXID());

        Map<String, Integer> good = param.stream().collect(Collectors.toMap(GoodDto::getGoodId, GoodDto::getBuyNum));
        LambdaQueryWrapper<Storage> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Storage::getGoodId, param.stream().map(e -> e.getGoodId()).collect(Collectors.toList()));
        List<Storage> storages = storageService.list(wrapper);
        storages.stream().forEach(e -> {
            e.setGoodNum(e.getGoodNum() - good.get(e.getGoodId()));
        });
        storageService.updateBatchById(storages);

        return true;
    }

    @Override
    public boolean busCommit(BusinessActionContext actionContext) {
        log.info("busCommit xid = " + actionContext.getXid() + "提交成功");
        return true;
    }

    @Override
    public boolean busRollback(BusinessActionContext actionContext) {
        // 编写对应的业务数据进行回滚
        List<GoodDto> param = actionContext.getActionContext("param", List.class);
//        int count = actionContext.getActionContext("count", Integer.class);
//        LambdaQueryChainWrapper<Stock> eq = lambdaQuery().eq(Stock::getCommodityCode, commodityCode);
//        Long count1 = eq.one().getCount();
//        // 扣了多少数,需要重新添加回去
//        lambdaUpdate().set(Stock::getCount, count + count1)
//                .eq(Stock::getCommodityCode, commodityCode)
//                .update();
        log.info("busRollback xid = " + actionContext.getXid() + "回滚成功");
        return true;
    }
}


四、总结:

本文通过springboot 项目整合seata 然后 通过 AT,XA,TCC 事务模式,模拟实现分布式事务。

五、参考:

1 Seata新手部署指南;
2 版本说明;
3 Seata 事务模式;

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

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

相关文章

-9501 MAL系统没有配置或者服务器不是企业版(dm8达梦数据库)

dm8达梦数据库 -9501 MAL系统没有配置或者服务器不是企业版&#xff09; 环境介绍1 环境检查2 问题原因 环境介绍 搭建主备集群时&#xff0c;遇到报错-9501 MAL系统没有配置或者服务器不是企业版 1 环境检查 检查dmmal.ini配置文件权限正确 dmdba:dinstall&#xff0c;内容正…

2023年下软考信息安全工程师报名时间及汇总(附备考攻略)

信息安全工程师是近几年新增的中级考试科目&#xff0c;一般在下半年考试&#xff0c;难度还是有的&#xff0c;但是只要你有恒心&#xff0c;愿意付出&#xff0c;认真刷题备考&#xff0c;拿下证书还是没有问题的&#xff01; 2023年下半年由于考试改革&#xff0c;报名时间…

kubernetes如何使用kruise-rollout进行分批灰度发布

前言 部署在 Kubernetes 集群中的应用&#xff0c;在升级发布时可能会存在的问题&#xff1a; 1&#xff0c;由于 Kuberneter 底层 Pod 容器生命周期与网络组件生命周期是异步管理的&#xff0c;在升级时如果没有处理好应用优雅退出的问题&#xff0c;就很容易导致 http 访问请…

【JAVA】抽象类与接口--下

⭐ 作者&#xff1a;小胡_不糊涂 &#x1f331; 作者主页&#xff1a;小胡_不糊涂的个人主页 &#x1f4c0; 收录专栏&#xff1a;浅谈Java &#x1f496; 持续更文&#xff0c;关注博主少走弯路&#xff0c;谢谢大家支持 &#x1f496; 抽象类与接口 1. 实现多个接口2. 接口间…

Linux常用命令_文件处理命令

文章目录 1. 命令格式与目录处理命令ls1.1 命令格式1.2 目录处理命令&#xff1a;ls 2. 目录处理命令2.1 目录处理命令&#xff1a;mkdir2.2 目录处理命令&#xff1a;cd2.3 目录处理命令&#xff1a;pwd2.4 目录处理命令&#xff1a;rmdir2.5 目录处理命令&#xff1a;cp2.6 目…

openGauss学习笔记-50 openGauss 高级特性-DB4AI

文章目录 openGauss学习笔记-50 openGauss 高级特性-DB4AI50.1 关键字解析50.2 使用指导 openGauss学习笔记-50 openGauss 高级特性-DB4AI openGauss当前版本支持了原生DB4AI能力&#xff0c;通过引入原生AI算子&#xff0c;简化操作流程&#xff0c;充分利用数据库优化器、执…

【PHP】字符串数组

文章目录 字符串类型字符串转义字符串相关函数 数组定义方式数组特点二维数组数组遍历foreach遍历语法for循环遍历数组相关函数相关题目 字符串类型 定义语法 引号方式&#xff1a;比较适合定义那些比较短&#xff08;不超过一行&#xff09;或者没有结构要求的字符串 1&#…

基于Python的图书馆大数据可视化分析系统设计与实现【源码+论文+演示视频+包运行成功】

博主介绍&#xff1a;✌csdn特邀作者、博客专家、java领域优质创作者、博客之星&#xff0c;擅长Java、微信小程序、Python、Android等技术&#xff0c;专注于Java、Python等技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; …

vscode 与 C++

序 具体流程的话&#xff0c;官方文档里都有的&#xff1a;C programming with Visual Studio Code 浏览器下载一个mingw64&#xff0c;解压&#xff0c;配置环境变量vscode里安装c相关的插件没了 第一步只看文字&#xff0c;可能有点抽象&#xff0c;相关视频&#xff1a; …

云计算企业私有云平台建设方案PPT

导读&#xff1a;原文《云计算企业私有云平台建设方案PPT》&#xff08;获取来源见文尾&#xff09;&#xff0c;本文精选其中精华及架构部分&#xff0c;逻辑清晰、内容完整&#xff0c;为快速形成售前方案提供参考。 喜欢文章&#xff0c;您可以点赞评论转发本文&#xff0c;…

Linux常用命令_权限管理命令

文章目录 1. 权限管理命令: chmod2. 其他权限管理命令2.1 权限管理命令: chown2.2 权限管理命令: chgrp2.3 权限管理命令: umask 1. 权限管理命令: chmod {ugoa}中分别为&#xff1a;u-user、g-group、a-all&#xff1b;谁创建文件&#xff0c;谁是所有者&#xff1b;所属组为所…

HOOPS Exchange SDK 2023 Service Pack 2 Crack

内容摘自互联网&#xff0c;具体功能以官网介绍为准。。。 HOOPS SDK是全球领先开发商TechSoft 3D旗下的原生产品&#xff0c;专注于Web端、桌面端、移动端3D工程应用程序的开发。长期以来&#xff0c;HOOPS通过卓越的3D技术&#xff0c;帮助全球600多家知名客户推动3D软件创新…

Qt ui对某控件进行全局提升报错:no such file or directory

问题 在Qt项目中&#xff0c;设计师界面&#xff0c;对某一控件进行提升&#xff0c;设置完“提升的类名称”、“头文件”、全局包含后&#xff0c;构建时&#xff0c;报“no such file or directory”错误&#xff0c;但文件命名存在呀。 解决 根据问题就应该明白&#xf…

并查集(C++实现)

目录 一、并查集原理 二、并查集应用 2.1 并查集举例 2.2 并查集数组规律 2.3 并查集功能 三、并查集实现 3.1 并查集 3.2 根据名字查找 四、例题 4.1 省份数量 4.2 等式方程的可满足性 一、并查集原理 再一些应用问题中&#xff0c;需要将n个不同的元素划分成一些…

Python读取Excel:实现数据高效处理的利器

目录 一、Python读取Excel的常用库二、Python读取Excel的步骤三、具体案例和使用场景四、Python读取Excel的优势与其他编程语言比较 摘要 本文将介绍Python读取Excel的方法&#xff0c;并通过具体案例和使用场景展示如何实现数据高效处理。我们将介绍常用的Python库&#xff0c…

QT基础使用:组件和代码关联(信号和槽)

自动关联 ui文件在设计环境下&#xff0c;能看到的组件可以使用鼠标右键选择“转到槽”就是开始组件和动作关联。 在自动关联这个过程中软件自动动作的部分 需要对前面头文件进行保存&#xff0c;才能使得声明的函数能够使用。为了方便&#xff0c;自动关联时先对所有文件…

【Hello Algorithm】堆和堆排序

本篇博客简介&#xff1a; 讲解堆和堆排序相关算法 堆和堆排序 堆堆的概念堆的性质堆的表示形式堆的增加删除堆的最大值 堆排序堆排序思路时间复杂度为N的建堆方法已知一个近乎有序的数组 使用最佳排序方法排序 堆 堆的概念 这里注意&#xff01;&#xff01;&#xff01; 这…

日志系统——性能测试

日志系统项目已经编写完成&#xff0c;在本节完成性能测试之后就正式结束了 测试代码如下 #include "../logs/mjwlog.h" #include <vector> #include <thread>//参数&#xff1a;日志器名称&#xff0c;线程数量&#xff0c;输出日志条数&#xff0c;单…

nginx(七十八)nginx配置http2

一 ngx_http_v2模块 1、本文不讲解HTTP2的知识2、只讲解nginx中如何配置HTTP2 ① 前置条件 1、openssl的版本必须在1.0.2e及以上2、开启https加密,目前http2.0只支持开启了https的网站编译选项&#xff1a;--with-http_ssl_module --with-http_v2_module 特点&#xff1a…

【翻译】RISC-V指令集手册第Ⅱ卷:特权体系结构

第三章 机器级ISA&#xff0c;版本1.11 本章描述RISC-V系统中最高权限的机器模式(M-mode)下的机器级操作。M模式用于对硬件平台的低级访问&#xff0c;是复位时进入的第一个模式。M模式还可以用于实现在硬件中直接实现过于困难或代价过高的特性。RISC-V机器级ISA包含一个公共核…