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">-->
<!--<!– 配置切面点–>-->
<!--<!– 配置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>-->
<!--<!– 开启spring对注解AOP的支持–>-->
<!--<!– <aop:aspectj-autoproxy/>–>--><!--<!– 配置事务管理器–>-->
<!-- <bean id="dtm" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">-->
<!-- <property name="dataSource" ref="ds"></property>-->
<!-- </bean>--><!--<!– 配置事务的通知引用事务管理器–>-->
<!--<!– 在tx:advice中配置事务的属性–>-->
<!-- <tx:advice id="d" transaction-manager="dtm">-->
<!-- <tx:attributes>-->
<!-- <tx:method name="*"/>-->
<!-- </tx:attributes>-->
<!-- </tx:advice>--><!--<!– 配置AOP切入点表达式–>-->
<!-- <aop:config>-->
<!-- <aop:pointcut id="point" expression="execution(public void com.etime.service.impl.AccountServiceImpl.transferAccount(..))"/>-->
<!--<!– 在aop:config标签内部:建立事务通知和切入点表达式的关系–>-->
<!-- <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>-->
<!--<!– 提交事务–>-->
<!-- <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>
运行结果:正常异常事务处理
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入门基础银行转账实例**(进阶版)**------------事务处理 由上一节讲述的通过Connection和QueryRunner对事务进行的处理(详情可以去我之前写的博客文章:https://blog.csdn.net/m0_56245143/article/details/130069160?spm1001.2014…...
【python学习】基础篇-常用函数-format函数 格式化操作
format()可以对数据进行格式化处理操作,语法如下: format(value,format_spec) value 为要转换的数据,fommat spec 为格式化解释, 当参数 format spec 为空时,等同于函数 str(value)的方式。 format spec 可以设置非常复…...
团团面试经验
1、Redis同时访问大量不存在的key会发生什么? 如果是缓存和数据库中都不存在,那么就会发生缓存穿透。 举个例子:某个黑客故意制造一些非法的 key 发起大量请求,导致大量请求落到数据库,结果数据库上也没有查到对应的数…...

今天面了个京东拿 38K 出来的,让我见识到了基础的天花板
今年的春招已经开始了,很多小伙伴收获不错,拿到了心仪的 offer。 各大论坛和社区里也看见不少小伙伴慷慨地分享了常见的软件测试面试题和八股文,为此咱这里也统一做一次大整理和大归类,这也算是划重点了。 俗话说得好࿰…...

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

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

基于飞桨实现的特定领域知识图谱融合方案:ERNIE-Gram文本匹配算法
文本匹配任务在自然语言处理领域中是非常重要的基础任务,一般用于研究两段文本之间的关系。文本匹配任务存在很多应用场景,如信息检索、问答系统、智能对话、文本鉴别、智能推荐、文本数据去重、文本相似度计算、自然语言推理、问答系统、信息检索等&…...

前端基础复习
1.什么叫HTML5?和原本的所说的HTML有什么区别? 本质上html和html5是一样的的。区别有: 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 论文地址:https://arxiv.org/pdf/2303.14189.pdf 概述 本文提出了一种通用的 CNN 和 Transformer 混合的视觉基础模型 移动设备和 ImageNet 数据集上的精度相同的前提下…...
C/C++文档阅读笔记-A Simple Makefile Tutorial解析
Makefile文件可以使得程序编译变得简单。本博文并不是很系统的讲解makefile,本博文的目标是让读者快速编写自己的makefile文件并能应用到中小项目中。 简单实例 举个例子有下面3个文件,分别是hellomake.c,hellofunc.c,hellomake.…...
GraphSAGE的基础理论
文章目录GraphSAGE原理(理解用)GraphSAGE工作流程GraphSAGE的实用基础理论(编代码用)1. GraphSAGE的底层实现(pytorch)PyG中NeighorSampler实现节点维度的mini-batch GraphSAGE样例PyG中的SAGEConv实现2. …...

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

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

【MySQL】(1)数据库基础,库与表的增删查改,数据库的备份与还原
文章目录服务器,数据库,表关系MySQL 数据存储逻辑SQL 分类存储引擎库的操作查看数据库创建数据库查看创建语句删除数据库选择(切换)数据库查看当前选择的数据库修改数据库字符集和排序规则表的操作创建表查询表查询表结构插入数据…...
Python基础-01 变量
注释 注释的分类 在Python中,支持单行及多行注释 单行注释 使用#对代码进行说明,#右边的所有内容就是注释的内容,起辅助说明作用 # #右边的都是注释,解析器会忽略 print(hello world) #在控制台里打印一段话多行注释 多行注释中,允许换行,使用三个单引号开始,三个单引号结…...

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

map原理
map源码结构体: type hmap struct {count int // 元素的个数B uint8 // buckets 数组的长度就是 2^B 个overflow uint16 // 溢出桶的数量buckets unsafe.Pointer // 2^B个桶对应的数组指针oldbuckets unsafe.Pointer // 发生扩容时࿰…...
[Ext JS]3.6 Ext JS 表格(Grid)概览
Grid, 翻译过来是网格, 也就是表格。 Grid 的基本构成 面板 :Ext.grid.Panel表格视图 :Ext.view.Table。 不直接使用, 通过面板的viewConfig配置项进行配置。比如可以用来配置表格中行是否跳色显示列: Ext.grid.column.Column。 表格中的列定义store , 表格的数据示例代码…...

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

UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...

JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...

Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...

基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...
uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)
UniApp 集成腾讯云 IM 富媒体消息全攻略(地理位置/文件) 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型,核心实现方式: 标准消息类型:直接使用 SDK 内置类型(文件、图片等)自…...

算术操作符与类型转换:从基础到精通
目录 前言:从基础到实践——探索运算符与类型转换的奥秘 算术操作符超级详解 算术操作符:、-、*、/、% 赋值操作符:和复合赋值 单⽬操作符:、--、、- 前言:从基础到实践——探索运算符与类型转换的奥秘 在先前的文…...

【java面试】微服务篇
【java面试】微服务篇 一、总体框架二、Springcloud(一)Springcloud五大组件(二)服务注册和发现1、Eureka2、Nacos (三)负载均衡1、Ribbon负载均衡流程2、Ribbon负载均衡策略3、自定义负载均衡策略4、总结 …...

简约商务通用宣传年终总结12套PPT模版分享
IOS风格企业宣传PPT模版,年终工作总结PPT模版,简约精致扁平化商务通用动画PPT模版,素雅商务PPT模版 简约商务通用宣传年终总结12套PPT模版分享:商务通用年终总结类PPT模版https://pan.quark.cn/s/ece1e252d7df...
CentOS 7.9安装Nginx1.24.0时报 checking for LuaJIT 2.x ... not found
Nginx1.24编译时,报LuaJIT2.x错误, configuring additional modules adding module in /www/server/nginx/src/ngx_devel_kit ngx_devel_kit was configured adding module in /www/server/nginx/src/lua_nginx_module checking for LuaJIT 2.x ... not…...