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自身提供了相应的数据源实现,也提供了与第三方接口数据源集成的接口,这些功能都位于数据源模块之中。 1.1.2、事务管理模块 …...

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

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

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

如何培养对技术的热爱
这篇博文主要针对计算机专业相关的同学,对于理工科专业的同学有一定的借鉴意义,对于其他专业的同学,还请自行取舍。 背景 初学计算机,可能并不是每个人都能对其产生兴趣,更不要说从其中获得快乐。对于如何培养兴趣&a…...
Vue响应式数据的原理
在 vue2 的响应式中,存在着添加属性、删除属性、以及通过下标修改数组,但页面不会自动更新的问题。而这些问题在 vue3 中都得以解决。 vue3 采用了 proxy 代理,用于拦截对象中任意属性的变化,包括:属性的读写、属性的…...

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

39 printf 的输出到设备层的调试
前言 在前面 printf 的调试 我们只是调试到了 glibc 调用系统调用, 封装了参数 stdout, 带输出的字符缓冲, 以及待输出字符长度 然后内核这边 只是到了 write 的系统调用, 并未向下细看 我们这里 稍微向下 细追一下, 看看 到达设备层面 这里是怎么具体的 impl 的 测试用例…...
数字普惠金融、数字创新与经济增长—基于省级面板数据的实证考察(2011-2021年)
参照陈啸(2023)的做法,本对来自经济问题《数字普惠金融、数字创新与经济增长——基于省级面板数据的实证考察》一文中的基准回归部分进行复刻。数字普惠金融、数字创新已经成为驱动经济高质量发展的关键。利用省级面板数据,构建固…...
控制renderQueue解决NGUI与Unity3D物体渲染顺序问题
NGUI与Unity3D物体渲染顺序问题,做过UI的各位应该都遇到过。主要指的是UI与Unity制作的特效、3D人物等一同显示时的层次问题。 由于UI与特效等都是以transparent方式渲染,而Unity与NGUI在管理同是透明物体的render queue时实际上互相没有感知࿰…...

概率论与数理统计:第二、三章:一维~n维随机变量及其分布
文章目录 Ch2. 一维随机变量及其分布1.一维随机变量1.随机变量2.分布函数 F ( x ) F(x) F(x)(1)定义(2)分布函数的性质 (充要条件)(3)分布函数的应用——求概率3.最大最小值函数 2.一维离散型随机变量及其概率分布(分布律)3.一维连续型随机变量及其概率分布(概率密度)4.一般类型…...
BOLT- 识别和优化热门的基本块
在BOLT中,识别和优化热门的基本块之所以关键,是因为BOLT的主要目标是优化程序以更好地利用硬件特性,特别是指令缓存(ICache)。以下是BOLT如何识别和优化热门基本块的流程: 收集性能数据: BOLT开始的时候并不…...
Golang 中的 time 包详解(四):函数详解
在日常开发过程中,会频繁遇到对时间进行操作的场景,使用 Golang 中的 time 包可以很方便地实现对时间的相关操作。接下来的几篇文章会详细讲解 time 包,本文讲解一下 time 包中的函数。 func Now() Time 返回当前的系统时间。 package mai…...

【前端 | CSS】5种经典布局
页面布局是样式开发的第一步,也是 CSS 最重要的功能之一。 常用的页面布局,其实就那么几个。下面我会介绍5个经典布局,只要掌握了它们,就能应对绝大多数常规页面。 这几个布局都是自适应的,自动适配桌面设备和移动设备…...
腾讯云宣布VPC网络架构重磅升级,可毫秒级感知网络故障并实现自愈
8月11日,腾讯云宣布VPC(Virtual Private Cloud,云私有网络)架构重磅升级。新架构采用多项腾讯核心自研技术,能够支撑用户构建业界最大 300万节点超大规模单VPC网络,并将转发性能最大提升至业界领先的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:在Vue中不失去响应式的情况下解构属性 文章目录 Vue toRefs:在Vue中不失去响应式的情况下解构属性什么是响应式?解构Props的挑战使用toRefs保持响应式结论 在Vue开发中,我们经常会在组件之间传递数据。这时候ÿ…...

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

Linux:iptables防火墙
目录 绪论 1、防火墙 1.1 保护范围 1.2 网络协议划分 1.3 协议:tcp 1.4 四表 1.5 五链 1.6 iptables的规则 1.7 匹配顺序 流入本机:prerouting ------->iuput---------->用户进程(httpd服务)------请求--------响应--------->数据要返…...
MongoDB文档-进阶使用-spring-boot整合使用MongoDB---MongoTemplate完成增删改查
传送门: MongoDB文档--基本概念_一单成的博客-CSDN博客 MongoDB文档--基本安装-linux安装(mongodb环境搭建)-docker安装(挂载数据卷)-以及详细版本对比_一单成的博客-CSDN博客 MongoDB文档--基本安装-linux安装&…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...

Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...

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

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

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

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

2025 后端自学UNIAPP【项目实战:旅游项目】7、景点详情页面【完结】
1、获取景点详情的请求【my_api.js】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http(/login/getWXSessionKey, {code,avatar}); };//…...
Angular中Webpack与ngx-build-plus 浅学
Webpack 在 Angular 中的概念 Webpack 是一个模块打包工具,用于将多个模块和资源打包成一个或多个文件。在 Angular 项目中,Webpack 负责将 TypeScript、HTML、CSS 等文件打包成浏览器可以理解的 JavaScript 文件。Angular CLI 默认使用 Webpack 进行项目…...