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

Mybatis 小结

一、Mybatis 基本构成 

MyBatis的整体分为基础支持层、核心处理层、接口。

1.1、基础支持层 

1.1.1、数据源模块 

MyBatis自身提供了相应的数据源实现,也提供了与第三方接口数据源集成的接口,这些功能都位于数据源模块之中。

1.1.2、事务管理模块 

MyBatis对数据库中的事务进行了抽象,其自身提供了相应的事务接口和简单的实现,在很多场景中,MyBatis会与Spring框架集成,并由Spring框架管理事务相关配置。

1.1.3、缓存模块 

MyBatis中提供了一级缓存和二级缓存,而这两级缓存都依赖于基础支持层中的缓存模块实现。

1.1.4、Binding模块 

开发人员无须编写自定义 Mapper接口的实现,MyBatis会自动为其创建动态代理对象,
MyBatis 通过 Binding 模块将用户自定义的 Mapper 接口与映射配置文件关联起来,系统可以通过调用自定义 Mapper 接口中的方法执行相应的 SQL 语句完成数据库操作。

1.1.5、反射模块 

MyBatis中专门提供了反射模块,该模块对Java原生的反射进行了一系列优化,例如缓存了类的元数据,提高了反射的性能。

1.1.6、类型转换模块 

该功能在为 SQL 语句绑定实参以及映射查询结果集时都会涉及,将数据由 Java类型转换成 JDBC 类型。

1.1.7、日志模块 

MyBatis除了提供详细的日志输出信息,还能够集成第三方日志框架。
SLF4J 、LOG4J 、LOG4J2
JDK_LOGGING、COMMONS_LOGGING、STDOUT_LOGGING 
NO_LOGGING

1.1.8、资源加载模块 

对类加载器进行封装,确定类的使用顺序,提供加载类文件以及其他资源文件。

1.1.9、解析器模块 

主要提供两个功能:
1.对XPath进行封装,为MyBatis初始化时解析mybatis-config.xml配置文件以及映射配置文件提供支持;
2.为处理动态sql语句中的占位符提供支持。

1.2、核心处理层 

1.2.1、配置解析 

MyBatis 初始化时,会加载 mybatis-config.xml 配置文件、映射配置文件以及 Mapper 接口中的注解信息,解析后的配置信息会形成相应的对象并保存到 Configuration 对象中。

1.2.2、参数映射-SQL解析 

MyBatis 中的scripting模块会根据用户传入的实参,解析映射文件中定义的动态SQL节点,并形成数据库可执行的SQL 语句。
之后会处理 SQL 语句中的占位符,绑定用户传入的实参。

1.2.3、SQL执行 

SQL语句的执行中重要的组件:Executor、StatementHandler、ParameterHandler、ResultSetHandler。
Executor 主要负责维护一级缓存和二级缓存,并提供事务管理的相关操作,将数据库相关操作委托给 StatementHandler 完成。
StatementHandler 通过 ParamHandler 完成SQL语句的实参绑定,然后通过 java.sql.Statement 对象执行SQL语句并得到结果集,
最后通过 ResultSetHandler 完成结果集的映射,得到结果对象并返回。

1.2.4、插件

自定义插件也可以改变 Mybatis 的默认行为,如:可拦截 SQL 语句并对其重写。

1.3、MyBatis主要构件 

 1.SqlSession:
和数据库交互的会话,该对象中包含了执行SQL语句的所有方法。类似JDBC里的Connection。
 2.Executor:
MyBatis执行器,将根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。类似于JDBC里面的Statement/PrepareStatement。
 3.MappedStatement:
该对象是对映射SQL的封装,用于存储要映射的SQL语句的id、参数等信息。
 4.ResultSetHandler:
用于对返回的结果进行处理,最终得到自己想要的数据格式或类型。可以自定义返回类型。
 5.StatementHandler:
封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数、将Statement结果集转换成List集合。
 6.ParameterHandler:
对用户传递的参数转换成JDBC Statement 所需要的参数。资源加载模块
 7.TypeHandler:
java数据类型和jdbc数据类型之间的映射和转换。
 8.SqlSource:
根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回。
 9.BoundSql:
动态生成的SQL语句及相应的参数信息。
10.Configuration:
MyBatis 所有的配置信息都在 Configuration 对象之中。

1.4、MyBatis 的缓存 

1.4.1.一级缓存:SqlSession级别,默认开启,且不能关闭。

操作数据库时,需要创建 SqlSession 对象,对象中用 HashMap 存储缓存数据。
一级缓存的作用域是 SqlSession 范围的,当在同一个 SqlSession 中执行两次相同的SQL语句时,第一次执行完毕会将结果保存到缓存中,第二次查询时直接从缓存中获取。
如果SqlSession执行了DML操作(insert,update,delete),Mybatis必须将缓存清空以保证数据的准确性。
MyBatis的一级缓存最大范围是SqlSession内部,有多个SqlSession或者分布式的环境下,数据库写操作会引起脏数据,建议设定缓存级别为Statement。

1.4.2.二級緩存:Mapper级别,默认关闭,可以开启。

多个SqlSession使用同一个Mapper的sql语句操作数据库,数据会存在二级缓存区,用HashMap进行数据存储,多个SqlSession可以共用二级缓存。
在多表查询时,极大可能会出现脏数据,有设计上的缺陷,安全使用二级缓存的条件比较苛刻。
在分布式环境下,由于默认的MyBatis Cache实现都是基于本地的,分布式环境下必然会出现读取到脏数据,需要使用集中式缓存将MyBatis的Cache接口实现,有一定的开发成本,直接使用Redis、Memcached等分布式缓存可能成本更低,安全性也更高。

二、原理 

2.1、Mybatis 的基本流程 

1、定义一个Configuration对象,包含数据源、事务、mapper文件资源及影响数据库行为属性设置 settings。
2、通过配置对象,则可以创建一个SqlSessionFactoryBuilder对象。
3、通过 SqlSessionFactoryBuilder 获得SqlSessionFactory 的实例。
4、SqlSessionFactory 的实例可以获得操作数据的SqlSession实例,通过这个实例对数据库进行操作。
5、用户程序调用mybatis接口层 api(即Mapper接口中的方法)。
6、SqlSession通过调用api的Statement ID找到对应的MappedStatement对象。
7、通过Executor(负责动态SQL的生成和查询缓存的维护)将MappedStatement对象进行解析,sql参数转化、动态sql拼接,生成jdbc Statement对象。
8、JDBC执行sql。
9、借助MappedStatement中的结果映射关系,将返回结果转化成HashMap、JavaBean等存储结构并返回。

2.2、SqlSession(会话)

执行SQL操作,底层封装了JDBC连接,可用SqlSession实例直接执行被映射的SQL语句。每个线程都有自己的SqlSession实例,不能共享,线程不安全,用完后应关闭。

2.2.1 ​​SqlSession四大对象

Executor(执行器):  用来调度 StatementHandler、ParameterHandler、ResultHandler等来执行对应的SQL。
StatementHandler(数据库会话处理器): 使用数据库的Statement执行操作。
ParameterHandler: 对Sql参数的处理。
ResultSetHandler: 对ResultSet结果集封装返回处理的。
生成SqlSession时,DefaultSqlSessionFactory中调用openSession,又调openSessionFromDataSource方法。

2.2.2 生成SqlSession

生成SqlSession时,DefaultSqlSessionFactory中调用openSession,又调openSessionFromDataSource方法。

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {Transaction tx = null;try {final Environment environment = configuration.getEnvironment();final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);// 生成执行器final Executor executor = configuration.newExecutor(tx, execType);return new DefaultSqlSession(configuration, executor, autoCommit);} catch (Exception e) {closeTransaction(tx); // may have fetched a connection so lets call close();throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);} finally {ErrorContext.instance().reset();}
}
Configration的newExecutor方法中根据类型判断创建那种执行器,默认使用的是SimpleExecutor:
public class Configuration {public Executor newExecutor(Transaction transaction, ExecutorType executorType) {executorType = executorType == null ? defaultExecutorType : executorType;executorType = executorType == null ? ExecutorType.SIMPLE : executorType;Executor executor;// 根据类型判断创建哪种类型的执行器if (ExecutorType.BATCH == executorType) {// 批量执行所有更新语句executor = new BatchExecutor(this, transaction);} else if (ExecutorType.REUSE == executorType) {// 重用预处理语句executor = new ReuseExecutor(this, transaction);} else {// 默认的执行器executor = new SimpleExecutor(this, transaction);}if (cacheEnabled) {executor = new CachingExecutor(executor);}executor = (Executor) interceptorChain.pluginAll(executor);return executor;}
}

2.2.3 SqlSession接口 

public interface SqlSession extends Closeable {<T> T selectOne(String statement);<T> T selectOne(String statement, Object parameter);<E> List<E> selectList(String statement);<E> List<E> selectList(String statement, Object parameter);<E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds);<K, V> Map<K, V> selectMap(String statement, String mapKey);<K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey);<K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds);void select(String statement, Object parameter, ResultHandler handler);void select(String statement, ResultHandler handler);void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler);int insert(String statement);int insert(String statement, Object parameter);int update(String statement);int update(String statement, Object parameter);int delete(String statement);int delete(String statement, Object parameter);void commit();void commit(boolean force);void rollback();void rollback(boolean force);List<BatchResult> flushStatements();void close();void clearCache();Configuration getConfiguration();<T> T getMapper(Class<T> type);Connection getConnection();
}

三、日常的使用 

3.1、常用标签 及 标签属性

3.1.1、常用标签

3.1.1.1、select标签
<select id="findUserById" parameterType="int" resultMap="userResultMap"><include refid="sqlMsg"><property name="id" /></include>
</select><sql id="sqlMsg"> SELECT * FROM User WHERE ID = #{id}</sql><resultMap id="userResultMap" type="User"><id property="id" column="user_id" /><result property="username" column="user_name"/><result property="password" column="hashed_password"/>
</resultMap>
3.1.1.2、insert标签
<insert id="addUser">insert into User (id,name)  values (#{id},#{name})
</insert>
3.1.1.3、update标签
<update id="updateUser">update User setusername = #{username},password = #{password}where id = #{id}
</update>
3.1.1.4、delete标签
<delete id="deleteUser">delete from User where id = #{id}
</delete>
3.1.1.5、if 标签
<select id="findUser" >SELECT * FROM UserWHERE state = 0<if test="name != null and name!=''">AND name = #{name}</if>
</select>
3.1.1.6、choose、when、otherwise(类似于switch)标签:
<select id="findUser" >SELECT * FROM User WHERE state = 0<choose><when test="name != null">AND name like #{name}</when><when test="age != null">AND age = #{age}</when><otherwise>AND name like ''</otherwise></choose>
</select>
3.1.1.7、trim、where标签 
<select id="getUser" resultType="user">select * from user<trim prefix="where" prefixOverrides="and"><if test="lastName != null">name = #{name}</if><if test="age != null">and age = #{age}</if><if test="phone != null">and phone = #{phone}</if></trim>
</select>
3.1.1.8、foreach标签
<select id="queryUsers" >select * from user where id in<foreach collection="array" item="item" open="(" separator="," close=")" index="index">#{item}</foreach>
</select>
 3.1.1.9、bind标签
<!--使用bind元素进行模糊查询-->
<select id="queryUserByName" resultType="com.MyUser" parameterType= "com.MyUser">select * from user<trim prefix="where" prefixOverrides="and"><if test="name != null">]<bind name="bindName" value="'%' + name + '%'"/>name like #{bindName}</if></trim>
</select>
 3.1.1.10、selectKey标签
<insert id="insert"><selectKey keyProperty="id" resultType="int" order="BEFORE"><!-- Oracle中用Sequence获取主键 --><if test="_databaseId == 'oracle'">select seq_users.nextval from dual</if><!-- Mysql直接用sql查询最大主键 --><if test="_databaseId == 'mysql'">select(select max(u.id)+1 from t_user u)</if></selectKey>insert into t_user values (#{id}, #{name})
</insert>
 3.1.1.11、typeAliases标签
<typeAliases><typeAlias alias="myAuthor" type="com.bean.Author"/><typeAlias alias="myUser" type="com.bean.User"/><typeAlias alias="myCar" type="com.bean.Car"/><typeAlias alias="myHouse" type="com.bean.House"/>
</typeAliases>
<select id="selectUser" lang="myUser">SELECT * FROM user
</select>
3.1.2、标签属性 
3.1.2.1、select标签属性 
id           必选属性,绑定Sql语句与Mapper接口中的方法,。
parameterType 传入参数的类全限定名或别名。MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。
resultType   返回结果的类全限定名或别名。返回的是集合,则设置为集合包含的类型。
resultMap    对外部 resultMap 的命名引用。resultType 和 resultMap 之间只能同时使用一个。
flushCache   设为 true 后,只要语句被调用,会导致本地缓存和二级缓存被清空,默认值(对select):false。
useCache     设为 true 后,将会导致本条语句的结果被二级缓存缓存起来,默认值:对 select 元素为 true。
timeout          等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。
fetchSize    给驱动的建议值,让驱动程序每次批量返回的结果行数等于这个设置值。默认不设置(unset)(依赖驱动)。
statementType 可选 STATEMENT、PREPARED、CALLABLE。让 MyBatis 分别使用 Statement、PreparedStatement、CallableStatement,默认:PREPARED。
resultSetType 可选 FORWARD_ONLY、SCROLL_SENSITIVE、SCROLL_INSENSITIVE 或 DEFAULT(等价于 unset),默认值为 unset (依赖数据库驱动)。
databaseId   如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载不带 databaseId 属性和带有匹配当前数据库 databaseId 属性的所有语句;如果带和不带的语句都有,不带的会被忽略。
resultOrdered 仅针对嵌套结果 select 语句: 若为 true,将会假设包含了嵌套结果集或分组,返回一个主结果行时,不会产生对前面结果集的引用。获取嵌套结果集的时不至于内存不够,默认:false。
resultSets   仅适用于多结果集的情况。返回多个结果集并赋予每个结果集一个名称,多个名称之间以逗号分隔。
3.1.2.2、insert、update、delete标签属性
id              必选属性,绑定Sql语句与Mapper接口中的方法,。
parameterType    传入参数的类全限定名或别名。MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。
flushCache      设为 true 后,只要语句被调用,会导致本地缓存和二级缓存被清空,默认值:(对 insert、update 和 delete 语句)true。
timeout             等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。
statementType    可选 STATEMENT、PREPARED、CALLABLE。让 MyBatis 分别使用 Statement、PreparedStatement、CallableStatement,默认:PREPARED。
databaseId      如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载不带 databaseId 属性和带有匹配当前数据库 databaseId 属性的所有语句;如果带和不带的语句都有,不带的会被忽略。
useGeneratedKeys (仅insert、update)会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键,默认值:false。
keyProperty         (仅insert、update)指定能够唯一识别对象的属性,用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认:未设置(unset)。可用逗号分隔多个属性名。
keyColumn       (仅insert、update)设置生成键值在表中的列名,当主键列不是表中的第一列的时候,必须设置。如果生成列不止一个,可用逗号分隔多个属性名。
3.1.2.3、trim标签属性
prefix          拼接前缀。
suffix          拼接后缀。
prefixOverrides     去除sql语句前面的关键字或者字符。
suffixOverrides     去除sql语句后面的关键字或者字符。
3.1.2.4、foreach标签属性
collection  表示迭代集合的名称,可以使用@Param注解指定。
item        必选参数,集合中元素迭代时的别名。
index       在list和数组中,index是元素的序号,在map中,index是元素的key。
open        foreach代码的开始符号,一般是(和close=")"合用。
close       foreach代码的关闭符号,一般是)和open="("合用。
separator   元素之间的分隔符,separator=","会自动在元素中间用“,“。
3.1.2.5、selectKey标签属性
keyProperty    返回目标结果的key。
resultType     结果的类型。
order          设置为BEFORE或AFTER,设置为BEFORE,会先选择主键设置keyProperty,然后执行插入语句;设为AFTER,先执行插入语句,然后设置selectKey元素。
statementType  和前面的相同,MyBatis 支持 STATEMENT、PREPARED、CALLABLE语句的映射类型,分别代表PreparedStatement、CallableStatement 类型。

3.2、 Mybatis 常见问题

3.2.1、${} 与 #{} 的区别

#{}是占位符,有预编译处理,可防止SQL注入。
${}是拼接符,字符串替换,没有预编译处理,${} 不能防止SQL 注入。
Mybatis在处理#{}时,#{}传入参数是以字符串传入,会将SQL中的#{}替换为?号。

3.2.2、Mybatis的分页

分页方式:逻辑分页和物理分页。
逻辑分页:使用 MyBatis 自带的 RowBounds 进行分页,它是一次性查询很多数据,然后在数据中再进行检索。
物理分页:自己手写 SQL 分页或使用分页插件 PageHelper,去数据库查询指定条数的分页数据的形式。

3.2.3、转义符号

使用<![CDATA[内容]]>
<select id="selectById" resultMap="brandResultMap">select *from tb_brand where id <![CDATA[  >   ]]> #{id};
</select>

相关文章:

Mybatis 小结

一、Mybatis 基本构成 MyBatis的整体分为基础支持层、核心处理层、接口。 1.1、基础支持层 1.1.1、数据源模块 MyBatis自身提供了相应的数据源实现&#xff0c;也提供了与第三方接口数据源集成的接口&#xff0c;这些功能都位于数据源模块之中。 1.1.2、事务管理模块 …...

【Cartopy】库的安装和瓦片加载(天地图、高德等)

原文作者&#xff1a;我辈李想 版权声明&#xff1a;文章原创&#xff0c;转载时请务必加上原文超链接、作者信息和本声明。 Cartopy基础入门 【Cartopy】库的安装和天地图瓦片加载 【Cartopy】【Cartopy】如何更好的确定边界显示 【Cartopy】【Cartopy】如何丝滑的加载Geojso…...

TCPDF生成PDF文件,含jpjraph生成雷达图

TCPDF生成PDF文件&#xff0c;含jpjraph生成雷达图 依赖自行安装 "tecnickcom/tcpdf": "^6.6","amenadiel/jpgraph": "4"雷达图生成 中文字体添加安装 没有封装&#xff0c;只作为测试案例展示 // 创建新的PDF文档$pdf new \TCPD…...

Flink-串讲面试题

1. 概念 有状态的流式计算框架 可以处理源源不断的实时数据&#xff0c;数据以event为单位&#xff0c;就是一条数据。 2. 开发流程 先获取执行环境env&#xff0c;然后添加source数据源&#xff0c;转换成datastream&#xff0c;然后使用各种算子进行计算&#xff0c;使用s…...

如何培养对技术的热爱

这篇博文主要针对计算机专业相关的同学&#xff0c;对于理工科专业的同学有一定的借鉴意义&#xff0c;对于其他专业的同学&#xff0c;还请自行取舍。 背景 初学计算机&#xff0c;可能并不是每个人都能对其产生兴趣&#xff0c;更不要说从其中获得快乐。对于如何培养兴趣&a…...

Vue响应式数据的原理

在 vue2 的响应式中&#xff0c;存在着添加属性、删除属性、以及通过下标修改数组&#xff0c;但页面不会自动更新的问题。而这些问题在 vue3 中都得以解决。 vue3 采用了 proxy 代理&#xff0c;用于拦截对象中任意属性的变化&#xff0c;包括&#xff1a;属性的读写、属性的…...

pytest fixture 用于teardown工作

fixture通过scope参数控制setup级别&#xff0c;setup作为用例之前前的操作&#xff0c;用例执行完之后那肯定也有teardown操作。这里用到fixture的teardown操作并不是独立的函数&#xff0c;用yield关键字呼唤teardown操作。 举个例子&#xff1a; 输出&#xff1a; 说明&…...

39 printf 的输出到设备层的调试

前言 在前面 printf 的调试 我们只是调试到了 glibc 调用系统调用, 封装了参数 stdout, 带输出的字符缓冲, 以及待输出字符长度 然后内核这边 只是到了 write 的系统调用, 并未向下细看 我们这里 稍微向下 细追一下, 看看 到达设备层面 这里是怎么具体的 impl 的 测试用例…...

数字普惠金融、数字创新与经济增长—基于省级面板数据的实证考察(2011-2021年)

参照陈啸&#xff08;2023&#xff09;的做法&#xff0c;本对来自经济问题《数字普惠金融、数字创新与经济增长——基于省级面板数据的实证考察》一文中的基准回归部分进行复刻。数字普惠金融、数字创新已经成为驱动经济高质量发展的关键。利用省级面板数据&#xff0c;构建固…...

控制renderQueue解决NGUI与Unity3D物体渲染顺序问题

NGUI与Unity3D物体渲染顺序问题&#xff0c;做过UI的各位应该都遇到过。主要指的是UI与Unity制作的特效、3D人物等一同显示时的层次问题。 由于UI与特效等都是以transparent方式渲染&#xff0c;而Unity与NGUI在管理同是透明物体的render queue时实际上互相没有感知&#xff0…...

概率论与数理统计:第二、三章:一维~n维随机变量及其分布

文章目录 Ch2. 一维随机变量及其分布1.一维随机变量1.随机变量2.分布函数 F ( x ) F(x) F(x)(1)定义(2)分布函数的性质 (充要条件)(3)分布函数的应用——求概率3.最大最小值函数 2.一维离散型随机变量及其概率分布(分布律)3.一维连续型随机变量及其概率分布(概率密度)4.一般类型…...

BOLT- 识别和优化热门的基本块

在BOLT中&#xff0c;识别和优化热门的基本块之所以关键&#xff0c;是因为BOLT的主要目标是优化程序以更好地利用硬件特性&#xff0c;特别是指令缓存&#xff08;ICache&#xff09;。以下是BOLT如何识别和优化热门基本块的流程&#xff1a; 收集性能数据: BOLT开始的时候并不…...

Golang 中的 time 包详解(四):函数详解

在日常开发过程中&#xff0c;会频繁遇到对时间进行操作的场景&#xff0c;使用 Golang 中的 time 包可以很方便地实现对时间的相关操作。接下来的几篇文章会详细讲解 time 包&#xff0c;本文讲解一下 time 包中的函数。 func Now() Time 返回当前的系统时间。 package mai…...

【前端 | CSS】5种经典布局

页面布局是样式开发的第一步&#xff0c;也是 CSS 最重要的功能之一。 常用的页面布局&#xff0c;其实就那么几个。下面我会介绍5个经典布局&#xff0c;只要掌握了它们&#xff0c;就能应对绝大多数常规页面。 这几个布局都是自适应的&#xff0c;自动适配桌面设备和移动设备…...

腾讯云宣布VPC网络架构重磅升级,可毫秒级感知网络故障并实现自愈

8月11日&#xff0c;腾讯云宣布VPC&#xff08;Virtual Private Cloud&#xff0c;云私有网络&#xff09;架构重磅升级。新架构采用多项腾讯核心自研技术&#xff0c;能够支撑用户构建业界最大 300万节点超大规模单VPC网络&#xff0c;并将转发性能最大提升至业界领先的200Gbp…...

vue 路由页面跳转

从index.vue跳转到data.vue index.vue <el-table-column label"客户数" align"center" :show-overflow-tooltip"true"><template slot-scope"scope"><router-link :to"/system/enterprise-data/index/ scope.ro…...

Vue toRefs:在Vue中不失去响应式的情况下解构属性

Vue toRefs&#xff1a;在Vue中不失去响应式的情况下解构属性 文章目录 Vue toRefs&#xff1a;在Vue中不失去响应式的情况下解构属性什么是响应式&#xff1f;解构Props的挑战使用toRefs保持响应式结论 在Vue开发中&#xff0c;我们经常会在组件之间传递数据。这时候&#xff…...

自定义element-plus的弹框样式

项目中弹框使用频繁,需要统一样式风格,此组件可以自定义弹框的头部样式和内容 一、文件结构如下: 二、自定义myDialog组件 需求&#xff1a; 1.自定义弹框头部背景样式和文字 2.自定义弹框内容 3.基本业务流程框架 components/myDialog/index.vue完整代码&#xff1a; &…...

Linux:iptables防火墙

目录 绪论 1、防火墙 1.1 保护范围 1.2 网络协议划分 1.3 协议&#xff1a;tcp 1.4 四表 1.5 五链 1.6 iptables的规则 1.7 匹配顺序 流入本机&#xff1a;prerouting ------->iuput---------->用户进程(httpd服务)------请求--------响应--------->数据要返…...

MongoDB文档-进阶使用-spring-boot整合使用MongoDB---MongoTemplate完成增删改查

传送门&#xff1a; MongoDB文档--基本概念_一单成的博客-CSDN博客 MongoDB文档--基本安装-linux安装&#xff08;mongodb环境搭建&#xff09;-docker安装&#xff08;挂载数据卷&#xff09;-以及详细版本对比_一单成的博客-CSDN博客 MongoDB文档--基本安装-linux安装&…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker &#xff1b;并安装。 基础操作不再赘述。 打开 macOS 终端&#xff0c;开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...

使用SSE解决获取状态不一致问题

使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件&#xff0c;这个上传文件是整体功能的一部分&#xff0c;文件在上传的过程中…...

2025 后端自学UNIAPP【项目实战:旅游项目】7、景点详情页面【完结】

1、获取景点详情的请求【my_api.js】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http(/login/getWXSessionKey, {code,avatar}); };//…...

Angular中Webpack与ngx-build-plus 浅学

Webpack 在 Angular 中的概念 Webpack 是一个模块打包工具&#xff0c;用于将多个模块和资源打包成一个或多个文件。在 Angular 项目中&#xff0c;Webpack 负责将 TypeScript、HTML、CSS 等文件打包成浏览器可以理解的 JavaScript 文件。Angular CLI 默认使用 Webpack 进行项目…...