当前位置: 首页 > news >正文

SpringAOP入门基础银行转账实例(进阶版)------------事务处理

SpringAOP入门基础银行转账实例**(进阶版)**------------事务处理

由上一节讲述的通过Connection和QueryRunner对事务进行的处理(详情可以去我之前写的博客文章:https://blog.csdn.net/m0_56245143/article/details/130069160?spm=1001.2014.3001.5501查看)

接下来由我们将对它进行简单的AOP改造

我们还是沿用上次的项目模块:
在这里插入图片描述

Spring基于配置文件的AOP

环境搭建

对该项目进行maven工程添加依赖:pom.xml

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>7</source><target>7</target></configuration></plugin></plugins></build><groupId>com.etime</groupId><artifactId>day05</artifactId><version>1.0-SNAPSHOT</version><properties><spring.version>5.2.5.RELEASE</spring.version></properties><dependencies><!--导入spring的context坐标--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><!--导入Jdbc模块依赖--><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version></dependency><!--   DBUtils    --><!--        <dependency>--><!--            <groupId>commons-dbutils</groupId>--><!--            <artifactId>commons-dbutils</artifactId>--><!--            <version>1.6</version>--><!--        </dependency>--><!-- 数据库相关 --><!--        <dependency>--><!--            <groupId>mysql</groupId>--><!--            <artifactId>mysql-connector-java</artifactId>--><!--            <version>5.1.6</version>--><!--        </dependency>--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.11</version></dependency><!--c3p0--><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!--        添加测试依赖--><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version></dependency><!--        dbutils依赖的添加--><dependency><groupId>commons-dbutils</groupId><artifactId>commons-dbutils</artifactId><version>1.7</version></dependency><!--        添加aop配置依赖--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.7</version></dependency></dependencies>
</project>

创建Spring的配置文件并导入约束

准备的资源:需要扫描当前项目包下的com.etime、需要配置文件内的连接数据库的基本资源、以及导入数据库连接的约束、配置JdbcTemplate模块

application.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!--    扫描包--><context:component-scan base-package="com.etime"></context:component-scan><!--加载属性文件--><context:property-placeholder location="classpath:jdbc.properties"/><!--数据源对象--><bean id="ds" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.driver}"/><property name="jdbcUrl" value="${jdbc.url}"/><property name="user" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean><!--    配置JdbcTemplate模板对象--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="ds"/></bean><!--    加载QueryRunner--><bean id="qr" class="org.apache.commons.dbutils.QueryRunner"></bean><!--    配置切面-->
<!--    <aop:config>-->
<!--        <aop:aspect id="tm" ref="transactionUtil">-->
<!--&lt;!&ndash;            配置切面点&ndash;&gt;-->
<!--&lt;!&ndash;            配置com.etime.service.impl包下的AccountServiceImpl类中的transferAccount方法&ndash;&gt;-->
<!--            <aop:pointcut id="po" expression="execution(public void com.etime.service.impl.AccountServiceImpl.transferAccount(..))"/>-->
<!--&lt;!&ndash;            开始事务&ndash;&gt;-->
<!--&lt;!&ndash;            <aop:before method="startTransaction" pointcut-ref="po"></aop:before>&ndash;&gt;-->
<!--&lt;!&ndash;&lt;!&ndash;            提交事务&ndash;&gt;&ndash;&gt;-->
<!--&lt;!&ndash;            <aop:after-returning method="commitTransaction" pointcut-ref="po"></aop:after-returning>&ndash;&gt;-->
<!--&lt;!&ndash;&lt;!&ndash;            出现错误回滚&ndash;&gt;&ndash;&gt;-->
<!--&lt;!&ndash;            <aop:after-throwing method="rollBackTransaction" pointcut-ref="po"></aop:after-throwing>&ndash;&gt;-->
<!--&lt;!&ndash;&lt;!&ndash;            关闭事务&ndash;&gt;&ndash;&gt;-->
<!--&lt;!&ndash;            <aop:after method="closeTransaction" pointcut-ref="po"></aop:after>&ndash;&gt;-->
<!--            <aop:around method="transactionAround" pointcut-ref="po"></aop:around>-->
<!--        </aop:aspect>-->
<!--    </aop:config>-->
<!--&lt;!&ndash;    开启spring对注解AOP的支持&ndash;&gt;-->
<!--&lt;!&ndash;    <aop:aspectj-autoproxy/>&ndash;&gt;--><!--&lt;!&ndash;    配置事务管理器&ndash;&gt;-->
<!--    <bean id="dtm" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">-->
<!--        <property name="dataSource" ref="ds"></property>-->
<!--    </bean>--><!--&lt;!&ndash;    配置事务的通知引用事务管理器&ndash;&gt;-->
<!--&lt;!&ndash;    在tx:advice中配置事务的属性&ndash;&gt;-->
<!--    <tx:advice id="d" transaction-manager="dtm">-->
<!--        <tx:attributes>-->
<!--            <tx:method name="*"/>-->
<!--        </tx:attributes>-->
<!--    </tx:advice>--><!--&lt;!&ndash;    配置AOP切入点表达式&ndash;&gt;-->
<!--    <aop:config>-->
<!--        <aop:pointcut id="point" expression="execution(public void com.etime.service.impl.AccountServiceImpl.transferAccount(..))"/>-->
<!--&lt;!&ndash;        在aop:config标签内部:建立事务通知和切入点表达式的关系&ndash;&gt;-->
<!--        <aop:advisor advice-ref="d" pointcut-ref="point"></aop:advisor>-->
<!--    </aop:config>-->
</beans>

创建ConnectionUtil.java完成连接的反转控制

ConnectionUtil.java

package com.etime.util;import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import sun.rmi.transport.Connection;@Component("connection")
public class ConnectionUtil {
//    @Autowired
//    private JdbcTemplate jdbcTemplate;@Autowiredprivate ComboPooledDataSource ds;@Bean(name = "connection")public Connection getConnection() throws Exception {return (Connection) ds.getConnection();}
}

AOP配置

使用aop:config声明AOP配置

aop:config:​		作用:开始声明aop配置< aop:config >​			配置的代码< /aop:config >

在这里插入图片描述

使用aop:aspect配置切面

aop: aspect​		作用:用于配置切面​		属性:​				id:给切面提供一个唯一标识​				ref:引用配置好的通知类bean的id​				<aop:aspect id="tm" ref="transactionUtil">​					...​				< /aop:aspect>

使用aop:pointcut配置切入点表达式

aop:pointcut作用:用于配置切入点表达式。就是指定对哪些类的哪些方法进行增强。属性:expression:用于定义切入点表达式。​			id:用于切入点表达式提供一个唯一标识< aop : poincut id="po" expression="execution(public void com.etime.service.impl.AccountServiceImpl.transferAccount(..))"/>

使用aop:xx配置对应的通知类型

aop:before作用:用于配置前置通知。指定增强的方法在切入点方法之前执行属性:method:用于指定通知类中的增强方法名称ponitcut-ref:用于指定切入点的表达式的引用ponitcut:用于指定切入点表达式执行时间点:切入点方法执行之前执行<aop:before method="startTransaction" pointcut-ref="po" ></aop:before >
aop:after-returning作用: 用于配置后置通知属性:method:指定通知中方法的名称。pointct:定义切入点表达式pointcut-ref:指定切入点表达式的引用执行时间点:切入点方法正常执行之后。它和异常通知只能有一个执行<aop:after-returning method="commitTransaction" pointcut-ref="po"></aop:after-returning > 
aop:after-throwing作用:用于配置异常通知属性:method:指定通知中方法的名称。pointct:定义切入点表达式pointcut-ref:指定切入点表达式的引用执行时间点:切入点方法执行产生异常后执行。它和后置通知只能执行一个<aop:after-throwing method="rollBackTransaction" pointcut-ref="po"></aop:after-throwing >
aop:after作用:用于配置最终通知属性:method:指定通知中方法的名称。pointct:定义切入点表达式pointcut-ref:指定切入点表达式的引用执行时间点:无论切入点方法执行时是否有异常,它都会在其后面执行。<aop:after method="closeTransaction" pointcut-ref="po"></aop:after >

application.xml

配置后的代码:

<!--    配置切面--><aop:config><aop:aspect id="tm" ref="transactionUtil">
<!--            配置切面点-->
<!--            配置com.etime.service.impl包下的AccountServiceImpl类中的transferAccount方法--><aop:pointcut id="po" expression="execution(public void com.etime.service.impl.AccountServiceImpl.transferAccount(..))"/>
<!--            开始事务--><aop:before method="startTransaction" pointcut-ref="po"></aop:before>
<!--            提交事务--><aop:after-returning method="commitTransaction" pointcut-ref="po"></aop:after-returning>
<!--            出现错误回滚--><aop:after-throwing method="rollBackTransaction" pointcut-ref="po"></aop:after-throwing>
<!--            关闭事务--><aop:after method="closeTransaction" pointcut-ref="po"></aop:after>
<!--            <aop:around method="transactionAround" pointcut-ref="po"></aop:around>--></aop:aspect></aop:config>

service:修改

package com.etime.service.impl;import com.etime.dao.AccountDao;
import com.etime.entity.Account;
import com.etime.service.AccountService;
import com.etime.util.TransactionUtil;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.sql.SQLException;@Service("as")
public class AccountServiceImpl implements AccountService {@Autowiredprivate AccountDao accountDao;//    @Autowired
//    private TransactionUtil transactionUtil;//这里不能将此处的异常try,catch.spring只能捕捉throws的异常@Overridepublic void transferAccount(String name1, String name2, double money) throws SQLException {
//        try {
//            //开启事务
//            transactionUtil.startTransaction();//收到的钱Account accountOne=accountDao.getByName(name1);accountOne.setMoney(accountOne.getMoney()+money);accountDao.updateAccount(accountOne);//钱转出Account accountTwo=accountDao.getByName(name2);accountTwo.setMoney(accountTwo.getMoney()-money);accountDao.updateAccount(accountTwo);//            //以上数据没有数据操作错误,就提交
//            transactionUtil.commitTransaction();
//        }catch (SQLException e){
//            //如果数据有误,进行数据回滚
//            transactionUtil.rollBackTransaction();
//            e.printStackTrace();
//        }finally {
            //如果服务结束,事务关闭(不管是否服务成功都进行最后的事务关闭)
//            transactionUtil.closeTransaction();
//        }}
}

如图所示的运行结果:异常事务能正常处理

在这里插入图片描述

切点表达式说明

切点表达式的语法

execution([修饰符] 返回值类型 包名.类名.方法名(参数))
  • 访问修饰符可以省略
  • 返回值类型、包名、类名、方法名可以使用星号* 代表任意
  • 包名与类名之间一个点 . 代表当前包下的类,两个点 … 表示当前包及其子包下的类
  • 参数列表可以使用两个点 … 表示任意个数,任意类型的参数列表

例如:

全匹配方式

public void 
com.etime.service.impl.AccountServiceImpl.saveAccount(com.etime.domain.Account)

访问修饰符可以省略

void com.etime.service.impl.AccountServiceImpl.saveAccount(com.etime.domain.Account)

返回值可以使用*号,表示任意返回值

* com.etime.service.impl.AccountServiceImpl.saveAccount(com.etime.domain.Account)

包名可以使用 * 号,表示任意包,但是有几级包,需要写几个 *

* *.*.*.*.AccountServiceImpl.saveAccount(com.etime.domain.Account)

使用…来表示当前包,及其子包

* com..AccountServiceImpl.saveAccount(com.etime.domain.Account)

类名可以使用*号,表示任意类

* com..*.saveAccount(com.etime.domain.Account)

方法名可以使用*号,表示任意方法

* com..*.*(com.etime.domain.Account)

参数列表可以使用*,表示参数可以是任意数据类型,但是必须有参数

* com..*.*(*)

参数列表可以使用…表示有无参数均可,有参数可以是任意类型

* com..*.*(..)

全通配方式:

* *..*.*(..)

注意: 通常情况下,我们都是对业务层的方法进行增强,所以切入点表达式都是切到业务层实现类。

execution(* com.etime.service.impl.*.*(..))

环绕通知配置事务管理

在TransactionUtil类当中添加方法

/*** 环绕通知:* spring 框架为我们提供了一个接口:ProceedingJoinPoint,它可以作为环绕通知的方法参数。* 在环绕通知执行时,spring 框架会为我们提供该接口的实现类对象,我们直接使用就行。* @param pjp* @return*///环绕通知方法public Object transactionAround(ProceedingJoinPoint pjp) {Object result = null;try {//获取调用切入点方法时传入的参数Object[] args = pjp.getArgs();startTransaction();//运行切入点方法result = pjp.proceed(args);commitTransaction();} catch (Throwable throwable) {rollbackTransaction();throwable.printStackTrace();} finally {closeConnection();}return result;}
 aop:around:作用:用于配置环绕通知属性:method:指定通知中方法的名称。pointct:定义切入点表达式pointcut-ref:指定切入点表达式的引用说明:它是 spring 框架为我们提供的一种可以在代码中手动控制增强代码什么时候执行的方式。注意:通常情况下,环绕通知都是独立使用的
<!--    配置切面--><aop:config><aop:aspect id="tm" ref="transactionUtil">
<!--            配置切面点-->
<!--            配置com.etime.service.impl包下的AccountServiceImpl类中的transferAccount方法--><aop:pointcut id="po" expression="execution(public void com.etime.service.impl.AccountServiceImpl.transferAccount(..))"/>
<!--            开始事务-->
<!--            <aop:before method="startTransaction" pointcut-ref="po"></aop:before>-->
<!--&lt;!&ndash;            提交事务&ndash;&gt;-->
<!--            <aop:after-returning method="commitTransaction" pointcut-ref="po"></aop:after-returning>-->
<!--&lt;!&ndash;            出现错误回滚&ndash;&gt;-->
<!--            <aop:after-throwing method="rollBackTransaction" pointcut-ref="po"></aop:after-throwing>-->
<!--&lt;!&ndash;            关闭事务&ndash;&gt;-->
<!--            <aop:after method="closeTransaction" pointcut-ref="po"></aop:after>--><aop:around method="transactionAround" pointcut-ref="po"></aop:around></aop:aspect></aop:config>

运行结果:正常异常事务处理

在这里插入图片描述

Spring基于注解的AOP

AOP注解方式和XML方式完成的功能都是一样的,只是采用了两种开发方式而已。将原有的XML方式使用注解逐一替代。

接上一节所配置的环境

通知类使用注解配置和使用@Acpect注解声明为切面

在这里插入图片描述

在增强的方法上使用注解配置通知

@Before作用:把当前方法看成是前置通知属性:value:用于指定切入点表达式,还可以指定切入点表达式的引用。@Before("execution(public void com.etime.service.impl.AccountServiceImpl.transferAccount(..))")public void startTransaction() {try {System.out.println("启动事务");connection.setAutoCommit(false);} catch (SQLException e) {e.printStackTrace();}}     
 @AfterReturning作用: 把当前方法看成是后置通知。属性: value:用于指定切入点表达式,还可以指定切入点表达式的引用@AfterReturning("execution(public void com.etime.service.impl.AccountServiceImpl.transferAccount(..))")public void commitTransaction() {try {System.out.println("提交");connection.commit();} catch (SQLException e) {e.printStackTrace();}}
@AfterThrowing作用: 把当前方法看成是异常通知。属性: value:用于指定切入点表达式,还可以指定切入点表达式的引用@AfterThrowing("execution(public void com.etime.service.impl.AccountServiceImpl.transferAccount(..))")public void rollBackTransaction() {try {System.out.println("回滚");connection.rollback();} catch (SQLException e) {e.printStackTrace();}}
@After作用: 把当前方法看成是最终通知。属性: value:用于指定切入点表达式,还可以指定切入点表达式的引用@After("execution(public void com.etime.service.impl.AccountServiceImpl.transferAccount(..))")public void closeTransaction() {try {System.out.println("释放资源");connection.close();} catch (SQLException e) {e.printStackTrace();}}

到这里由上述的配置后可以直接运行,也是同样对事务进行处理,这里我就不运行了,只是用注解的方式更加的简洁

环绕通知配置事务管理

在TransactionUtil类中添加环绕配置

@Around作用: 把当前方法看成是环绕通知。属性: value:用于指定切入点表达式,还可以指定切入点表达式的引用。@Around("execution(public void com.etime.service.impl.AccountServiceImpl.transferAccount(..))")public Object transactionAround(ProceedingJoinPoint pjp) {Object result = null;try {Object[] args = pjp.getArgs();startTransaction();result = pjp.proceed(args);commitTransaction();} catch (Throwable throwable) {rollbackTransaction();throwable.printStackTrace();} finally {closeConnection();}return result;}

加环绕配置

@Around作用: 把当前方法看成是环绕通知。属性: value:用于指定切入点表达式,还可以指定切入点表达式的引用。@Around("execution(public void com.etime.service.impl.AccountServiceImpl.transferAccount(..))")public Object transactionAround(ProceedingJoinPoint pjp) {Object result = null;try {Object[] args = pjp.getArgs();startTransaction();result = pjp.proceed(args);commitTransaction();} catch (Throwable throwable) {rollbackTransaction();throwable.printStackTrace();} finally {closeConnection();}return result;}

相关文章:

SpringAOP入门基础银行转账实例(进阶版)------------事务处理

SpringAOP入门基础银行转账实例**&#xff08;进阶版&#xff09;**------------事务处理 由上一节讲述的通过Connection和QueryRunner对事务进行的处理(详情可以去我之前写的博客文章&#xff1a;https://blog.csdn.net/m0_56245143/article/details/130069160?spm1001.2014…...

【python学习】基础篇-常用函数-format函数 格式化操作

format()可以对数据进行格式化处理操作&#xff0c;语法如下: format(value&#xff0c;format_spec) value 为要转换的数据&#xff0c;fommat spec 为格式化解释&#xff0c; 当参数 format spec 为空时&#xff0c;等同于函数 str(value)的方式。 format spec 可以设置非常复…...

团团面试经验

1、Redis同时访问大量不存在的key会发生什么&#xff1f; 如果是缓存和数据库中都不存在&#xff0c;那么就会发生缓存穿透。 举个例子&#xff1a;某个黑客故意制造一些非法的 key 发起大量请求&#xff0c;导致大量请求落到数据库&#xff0c;结果数据库上也没有查到对应的数…...

今天面了个京东拿 38K 出来的,让我见识到了基础的天花板

今年的春招已经开始了&#xff0c;很多小伙伴收获不错&#xff0c;拿到了心仪的 offer。 各大论坛和社区里也看见不少小伙伴慷慨地分享了常见的软件测试面试题和八股文&#xff0c;为此咱这里也统一做一次大整理和大归类&#xff0c;这也算是划重点了。 俗话说得好&#xff0…...

Qt创建SDK库(dll动态库)并调用SDK库(dll动态库)

Qt创建SDK库(dll动态库)并调用SDK库(dll动态库) 一、项目场景 在日常的项目中&#xff0c;我们经常会遇到调用别人的数学库、线程库、图形库等操作。这些库通常就被称为SDK&#xff0c;SDK全称是Software Development Kit&#xff08;软件开发工具包&#xff09;&#xff0c;…...

400以内的蓝牙耳机哪款好?400以内蓝牙耳机排行榜

谈起TWS&#xff0c;无论是传统的音频厂商还是手机厂商&#xff0c;都是其不可或缺的重要产品线&#xff0c;现在很多许多蓝牙耳机都不是千篇一律得形状&#xff0c;市场也鲜有商家在外观上下功夫&#xff0c;下面分享几款400元以内&#xff0c;内外兼具的耳机品牌。 一、南卡…...

基于飞桨实现的特定领域知识图谱融合方案:ERNIE-Gram文本匹配算法

文本匹配任务在自然语言处理领域中是非常重要的基础任务&#xff0c;一般用于研究两段文本之间的关系。文本匹配任务存在很多应用场景&#xff0c;如信息检索、问答系统、智能对话、文本鉴别、智能推荐、文本数据去重、文本相似度计算、自然语言推理、问答系统、信息检索等&…...

前端基础复习

1.什么叫HTML5&#xff1f;和原本的所说的HTML有什么区别&#xff1f; 本质上html和html5是一样的的。区别有&#xff1a; 1. 在文档类型声明上 HTML4.0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loos…...

Vue2 API-源码解析

目录 Vue.extend(option) delimiters functional Vue.component(id, Function | Object) Vue.directive( id, [definition] ) Vue.filter( id, function) Vue.nextTick() Vue.set() Vue.delete(target, index/key) Vue.compile(template) Vue.observable(object) …...

FastViT: A Fast Hybrid Vision Transformer using Structural Reparameterization

FastViT: A Fast Hybrid Vision Transformer using Structural Reparameterization 论文地址&#xff1a;https://arxiv.org/pdf/2303.14189.pdf 概述 本文提出了一种通用的 CNN 和 Transformer 混合的视觉基础模型 移动设备和 ImageNet 数据集上的精度相同的前提下&#xf…...

C/C++文档阅读笔记-A Simple Makefile Tutorial解析

Makefile文件可以使得程序编译变得简单。本博文并不是很系统的讲解makefile&#xff0c;本博文的目标是让读者快速编写自己的makefile文件并能应用到中小项目中。 简单实例 举个例子有下面3个文件&#xff0c;分别是hellomake.c&#xff0c;hellofunc.c&#xff0c;hellomake.…...

GraphSAGE的基础理论

文章目录GraphSAGE原理&#xff08;理解用&#xff09;GraphSAGE工作流程GraphSAGE的实用基础理论&#xff08;编代码用&#xff09;1. GraphSAGE的底层实现&#xff08;pytorch&#xff09;PyG中NeighorSampler实现节点维度的mini-batch GraphSAGE样例PyG中的SAGEConv实现2. …...

Windows 安装 GDAL C++库

Windows 安装 GDAL C库1. 方法1&#xff1a;下载配置网友编译的GDAL版本1.1 下载1.2 配置1.3 测试1.4 缺点2. 方法2&#xff1a;自己编译3. 参考1. 方法1&#xff1a;下载配置网友编译的GDAL版本 1.1 下载 CSDN: GDAL&#xff0c;geos联合编译的库&#xff0c;版本为1.8.0&am…...

二叉树基础概念

1.二叉树种类 1.1 满二叉树 满二叉树&#xff1a;如果一棵二叉树只有度为 0 0 0 的结点和度为 2 2 2 的结点&#xff0c;并且度为0的结点在同一层上&#xff0c;则这棵二叉树为满二叉树。 如图所示&#xff1a; 这棵二叉树为满二叉树&#xff0c;也可以说深度为 k k k&…...

【MySQL】(1)数据库基础,库与表的增删查改,数据库的备份与还原

文章目录服务器&#xff0c;数据库&#xff0c;表关系MySQL 数据存储逻辑SQL 分类存储引擎库的操作查看数据库创建数据库查看创建语句删除数据库选择&#xff08;切换&#xff09;数据库查看当前选择的数据库修改数据库字符集和排序规则表的操作创建表查询表查询表结构插入数据…...

Python基础-01 变量

注释 注释的分类 在Python中,支持单行及多行注释 单行注释 使用#对代码进行说明,#右边的所有内容就是注释的内容,起辅助说明作用 # #右边的都是注释,解析器会忽略 print(hello world) #在控制台里打印一段话多行注释 多行注释中,允许换行,使用三个单引号开始,三个单引号结…...

springcloud2.1.0整合seata1.5.2+nacos2.10(附源码)

springcloud2.1.0整合seata1.5.2nacos2.10&#xff08;附源码&#xff09; 1.创建springboot2.2.2springcloud2.1.0的maven父子工程如下&#xff0c;不过多描述&#xff1a; 搭建过程中也出现很多问题&#xff0c;主要包括&#xff1a; 1.seataServer.properties配置文件的组…...

map原理

map源码结构体&#xff1a; type hmap struct {count int // 元素的个数B uint8 // buckets 数组的长度就是 2^B 个overflow uint16 // 溢出桶的数量​buckets unsafe.Pointer // 2^B个桶对应的数组指针oldbuckets unsafe.Pointer // 发生扩容时&#xff0…...

[Ext JS]3.6 Ext JS 表格(Grid)概览

Grid, 翻译过来是网格, 也就是表格。 Grid 的基本构成 面板 :Ext.grid.Panel表格视图 :Ext.view.Table。 不直接使用, 通过面板的viewConfig配置项进行配置。比如可以用来配置表格中行是否跳色显示列: Ext.grid.column.Column。 表格中的列定义store , 表格的数据示例代码…...

关于使用云渲染的五大优势

在不影响质量或性能的情况下节省时间、金钱和资源&#xff0c;对于需要在通常较短且严格的期限内创建高质量 3D 内容的专业人士来说&#xff0c;云渲染都是最好的选择&#xff01;云渲染作为数字媒体生产的最新趋势&#xff0c;与传统的渲染农场和机器相比具有许多优势&#xf…...

CSS基础样式

1.高度和宽度 .c1{height:300px;width:500px; } 注意事项&#xff1a; 宽度&#xff0c;支持百分比 行内标签&#xff1a;默认无效 块级标签&#xff1a;默认有效&#xff08;右侧区域就算是空白&#xff0c;也不给占用&#xff09; 2.块级和行内标签 css样式&#xff1a;标签…...

第03章_流程控制语句

第03章_流程控制语句 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 本章专题与脉络 流程控制语句是用来控制程序中各语句执行顺序的语句&#xff0c;可以把语句组合成能完成一定功能的小逻辑模…...

配电网电压调节及通信联系研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

stegano(图片隐写、摩斯密码)

附件是PDF&#xff0c;我们在选择内容时发现光标溢出了文本 说明这里还存在一些我们看不到的内容 直接CtrlA全选&#xff0c;CtrlC复制后新建一个纯文本文件 将复制的东西粘贴过去 粘贴后发现果然多出来了一些东西&#xff0c;提取出来 BABA BBB BA BBA ABA AB B AAB ABAA A…...

wsl安装torch_geometric

在官网选择需要的版本 选择安装途径&#xff0c;选择runfile 执行第一行&#xff0c;会下载一个文件到目录下 需要降低C的版本&#xff0c;否则 执行sudo sh cuda_11.1.0_455.23.05_linux.run,会出现 查看对应的文件&#xff0c;会有 可以加上override参数之后&#xff0c;…...

ASP.NET Core - 依赖注入(二)

2&#xff0c;NET Core 依赖注入的基本用法 话接上篇&#xff0c;这一章介绍 .NET Core 框架自带的轻量级 Ioc 容器下服务使用的一些知识点&#xff0c;大家可以先看看上一篇文章 [ASP.NET Core - 依赖注入(一)] 2.3 服务解析 通过 IServiceCollection 注册了服务之后&#xf…...

Scala之集合(1)

目录 ​​​​​​​集合介绍&#xff1a; 不可变集合继承图&#xff1a;​编辑 可变集合继承图 数组&#xff1a; 不可变数组&#xff1a; 样例代码&#xff1a; 遍历集合的方法&#xff1a; 1.for循环 2.迭代器 3.转换成List列表&#xff1a; 4.使用foreach()函数&a…...

公网使用SSH远程登录macOS服务器【内网穿透】

文章目录前言1. macOS打开远程登录2. 局域网内测试ssh远程3. 公网ssh远程连接macOS3.1 macOS安装配置cpolar3.2 获取ssh隧道公网地址3.3 测试公网ssh远程连接macOS4. 配置公网固定TCP地址4.1 保留一个固定TCP端口地址4.2 配置固定TCP端口地址5. 使用固定TCP端口地址ssh远程前言…...

PVE相关的各种一键脚本(一键安装PVE)(一键开设KVM虚拟化的NAT服务器-自带内外网端口转发)

PVE 原始仓库&#xff1a;https://github.com/spiritLHLS/pve 前言 建议debian在使用前尽量使用最新的系统 非debian11可使用 debian一键升级 来升级系统 当然不使用最新的debian系统也没问题&#xff0c;只不过得不到官方支持 请确保使用前机器可以重装系统&#xff0c;…...

CSDN目录博客(zhaoshuangjian)

总目录 一、Java1.1 高并发1.2 多线程1.3 集合1.4 I/O1.5 异常1.6 事务1.7 锁机制1.8 JVM 二、数据库2.1 mysql2.1.1 mysql索引2.1.1 mysql锁2.1.1 mysql事务2.1.1 2.2 oracle2.3 postgresql2.4 达梦2.5 人大金仓kingbase 三、设计模式四、中间件4.1 缓存中间件-redis4.2 缓存中…...