后端框架(1):Mybatis

什么是框架?

盖高楼,框架结构。

框架结构就是高楼的主体,基础功能。

把很多基础功能已经实现了(封装了)。

在基础语言之上,对各种基础功能进行封装,方便开发者,提高开发效率。

mybatis:对jdbc进行封装

spring:对整个java后端架构进行管理的

springweb:对servlet层进行封装

springboot:对spring框架的搭建进行封装

Mybatis

介绍:

        mybatis原来是Apache下main的一个开源项目,名为ibatis

        后转移到谷歌旗下,改名为mybatis

        mybatis是一个优秀的数据持久层框架(数据持久层:dao层 数据访问层)

        mybatis是对jdbc进行的封装,避免了jdbc中手动设置参数,手动映射结果的操作

        mybatis将jdbc中的接口进行封装,提供了他自己的类和接口实现

        mybatis可以使用xml配置和注解的方式,将数据库中记录自动映射到java对象中,是一种ORM实现(对象关系映射)将可以自动将数据映射到对象中的这种框架,也称为orm框架

        mybatis还提供了动态sql 和 数据缓存

mybatis搭建

Mybatis 中文官网 mybatis – MyBatis 3 | 简介

1、创建一个maven项目

2、在pom.xml导入mabatis依赖的jar

        

<!--mybatis--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.2</version></dependency><!--mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.16</version></dependency>​

3、创建一个全局的mybatis配置文件

        在main文件夹中的recources里面创建一个名为mybatis.xml文件

                               

        在mybatis.xml文件中配置核心全局相关信息等操作

        配置数据库连接

​<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTDConfig3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><!--配置数据库连接相关信息--><environments default="development"><environment id="development"><transactionManager type="JDBC"/><!--type="POOLED" 使用数据库连接池功能,默认创建10个连接对象,减少频繁创建销毁连接对象--><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://127.0.0.1:3306/ssmdb?serverTimezone=Asia/Shanghai"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment></environments></configuration>​​

4、创建数据库,创建表,准备数据

        在mysql中创建例如名为ssmdb的数据库,在此库中创建名为admin的表

5、创建一个访问接口,定义方法

        在java中先创建好每个层所需要的包

                

        然后在dao层中创建AdminDao的接口

public interface AdminDao {Admin findAdminById(int id);
}

6、创建接口对应的sql映射文件,编写sql

        依旧在recources里面先创建名为mappers的文件夹(里面都放着一些sql映射文件),在mappers里创建一个名为AdminMapper.xml文件并编写sql

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTDMapper3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
​
<mapper namespace = "com.ffyc.mabatispro.dao.AdminDao"><select id="findAdminById" parameterType="int" resultType="com.ffyc.mybatis.model.Admin">select * from admin where id = #{id}</select>
</mapper>

        再在mybatis.xml文件中将AdminMapper.xml文件注册配置

<!--注册映射文件--><mappers><mapper resource="mappers/AdminMapper.xml"></mapper></mappers>

7、测试mybatis

单表查询

        创建一个test类

public class Test1 {public static void main(String[] args) throws IOException {//1.mybatis读取配置文件Reader resourceAsReader = Resources.getResourceAsReader("mybatis.xml");//2.创建 SqlSessionFactory,负责创建SqlSession对象(连接数据库的会话对象,类似Connection)//sqlSessFactory对象也是只需要创建一个,创建后不需要销毁SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsReader);//3.创建SqlSession对象SqlSession sqlSession = sqlSessionFactory.openSession();//4.创建接口的代理对象AdminDao adminDao = sqlSession.getMapper(AdminDao.class);//5.调用Admin admin = adminDao.findAdminById(1);//让代理对象帮我们调用映射文件在与此接口中相同名称的方法System.out.println(admin);//6.关闭会话对象sqlSession.close();//关闭与数据库的连接对象}
}

控制台所展现的是实现了日志功能后的结果(后面有日志功能的配置)

        7.1增加

        在AdminDao中写方法        

void insertAdmin(Admin admin);

        在AdminMapper.xml中写sql映射语句

    <!--useGeneratedKeys="true" 返回自增主键keyProperty="id" 定义接收属性keyColumn="id" 定义主键列-->
<insert id="insertAdmin" parameterType="Admin" useGeneratedKeys="true" keyProperty="id" keyColumn="id">insert into admin(account,password,gender) values (#{account},#{password},#{gender})</insert>
    @Testpublic void insert(){Admin admin = new Admin();admin.setAccount("ccc");admin.setPassword("123");admin.setGender("男");SqlSession sqlSession = MybatisUtil.getSqlSession();AdminDao adminDao = sqlSession.getMapper(AdminDao.class);adminDao.insertAdmin(admin);//保存数据后端,需要立刻拿到这条数据在数据库的主键sqlSession.commit();sqlSession.close();}

@Test:单元测试,程序员使用的测试方式,以方法为单位进行测试 使用junit组件实现单元测试

        在maven中配置junit组件

<!--junit--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>provided</scope></dependency>
sqlSession.commit();//提交数据库事务,当我们的程序代码执行没有任何问题时,再向数据库发送提交事务操作,数据库真正执行sql,出现异常则不提交事务(新增,修改,删除完毕后,都需要手动提交事务)/*数据库事务:是数据库的一种管理的机制,是对一次连接数据库过程的管理保证一次操作中,执行的多条sql,要么都成功执行,要么都不执行提交事务    数据库才会真正的在数据库执行这一次操作中的多条sql*/

        7.2删除

void deleteAdmin(int id);
<delete id="deleteAdmin" parameterType="int">delete from admin where id = #{id}</delete>

        7.3修改

void updateAdmin(Admin admin);
<update id="updateAdmin" parameterType="Admin">update admin set account=#{account},password=#{password} where id = #{id}</update>

        7.4查找

Admin findAdminByAccount(String account);
<select id="findAdminByAccount" parameterType="string" resultType="Admin">select * from admin where account = #{account}</select>

搭建补充:

1、在idea中安装mybatisX插件

        在setting中找到MybatisX插件并下载下来,若没显示相关图标重启Idea即可

2、数据库连接池

链接数据库 每次访问数据库时候,创建一个Connection,用完关闭,但是访问量大了之后,每次都要创建新的连接对象,用完关闭,比较耗时

使用数据库连接池,在池(集合)中先创建一些连接对象

用户访问时,就直接在池中获取一个连接对象

用完不销毁,还回到池中

这样就减少频繁创建销毁连接对象

<dataSource type="POOLED">
<!--type="POOLED" 使用数据库连接池功能,默认创建10个连接对象,减少频繁创建销毁连接对象-->

3、配置日志功能

<!--配置日志功能-->
<settings><setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

4、为类配置别名

<!--为类配置别名-->
<typeAliases><!--<typeAlias type="com.ffyc.mybatispro.model.Admin" alias="Admin"></typeAlias>--><package name="com.ffyc.mybatispro.model"/>
</typeAliases>

对象映射

如果表中的类名与类中的属性名完全相同,mybatis会自动将查询结果封装 到POJO对象中.

如果java中使用标准驼峰命名,数据库中使用下划线连接命名,可以开始全局 设置实现自动转换

<!--设置驼峰命名自动映射--><setting name="mapUnderscoreToCamelCase" value="true"/>

#{}:是占位符,是采用预编译方式向sql中传值,可以防止sql注入,如果我们往sql中传值,就使用#{}

${}:是将内容直接拼接到sql语句中,一般不用于向sql中传值,用于向sql中动态传递列名

#{}与${}之间的区别:    

1、底层实现不同

        #{} 采用预编译方式,防止sql注入,更加安全

        ${} 采用字符串拼接,直接将值拼接到sql中

2、使用场景不同

        #{} 一般我们用于向sql中的列传值

        ${} 一般用于向sql动态传递列名

                例如:排序时,order by 后面的列名是可以改变

                           select时,后面的列名也可以自由选择

List<Admin> findAdmins1(@Param("Column") String Column);
<!--${}的实用案例--><select id="findAdmins1" resultType="Admin" parameterType="string">select * from admin order by ${Column} desc</select>
@Testpublic void find3 (){SqlSession sqlSession = MybatisUtil.getSqlSession();AdminDao adminDao = sqlSession.getMapper(AdminDao.class);adminDao.findAdmins1("id");//${}的用法sqlSession.commit();sqlSession.close();}

                       

多表查询

关联查询(一对一)

         以学生和专业为例

        方式一:直接多表关联查询

(1)当查询一个学生和他所在的专业时(返回的为一个学生对象)

	<!--关联查询方式1:直接多表关联查询出我们需要的数据(一对一)--><select id="findStudentById" resultMap="studentMap">selects.id,s.num,s.name,s.gender,m.name mnamefrom student s inner join major m on s.majorid = m.id where s.id = #{id}</select>
<!--对关联查询到的学生信息进行自定义映射封装--><resultMap id="studentMap" type="student"><id column="id" property="id"></id><result column="num" property="num"></result><result column="name" property="name"></result><result column="gender" property="gender"></result><!--映射关联数据  专业名称  首先会创建一个Major对象,然后将专业名称封装到Major对象,最后将Major对象封装到Student对象中去--><association property="major" javaType="Major"><result column="mname" property="name"></result></association></resultMap>

                

(2)查询所有学生(返回的为多个学生对象,应创建一个学生类集合存放)可以共用resultMap

<select id="findStudents" resultMap="studentMap">selects.id,s.num,s.name,s.gender,m.name mnamefrom student s inner join major m on s.majorid = m.id</select>

                

        方式二:嵌套查询
<!--关联查询方式2:嵌套查询  先查询主表(学生表)(一对一)--><select id="findStudentById1" resultMap="studentMap1">select id,num,name,gender,majorid from student where id = #{id}</select><!--嵌套查询学生关联的专业--><select id="findMajorById" resultType="Major">select name from major where id = #{majorid}</select>
	<resultMap id="studentMap1" type="Student"><id column="id" property="id"></id><result column="num" property="num"></result><result column="name" property="name"></result><result column="gender" property="gender"></result><!--封装关联表数据--><association property="major" javaType="Major" select="findMajorById" column="majorid"></association></resultMap>

              

在一对一查询时,resultMap中要用到<association>标签用于想要关联的表上

        <association>中:property=""  表示所要映射到的哪个成员变量上

                                      javaType=""  表示所映射的成员变量的数据类型

                                      select=""  表示映射的成员变量的查询语句

                                      column=""  表示映射的成员变量要以上一个查询的某一列数据作为查询条件

关联查询(一对多)

        方式一:直接多表关联查询

        (1)查询一个专业时,可以将查询到的多个学生封装到一个集合中

<select id="findMajorById" resultMap="majorMap">selectm.id,m.name,s.num,s.name snamefrom major m inner join student s on m.id = s.majorid where m.id = #{id}</select>
<resultMap id="majorMap" type="Major"><id column="id" property="id"></id><result column="name" property="name"></result><!--将查询关联到的多个结果封装到集合--><collection property="students" javaType="List" ofType="Student"><result column="num" property="num"></result><result column="sname" property="name"></result></collection></resultMap>

                        

        (2)查询所有专业和每个专业的学生

        有些专业目前还没有学生,所以关联要用left join

<select id="findMajors" resultMap="majorMap">selectm.id,m.name,s.num,s.name snamefrom major m left join student s on m.id = s.majorid</select>

                        

        方式二:分成两次查询
<select id="findMajors1" resultMap="majorMap1">select id,name from major</select><select id="findStudents" resultType="Student">select num,name from student where majorid = #{id}</select>
<resultMap id="majorMap1" type="Major"><id column="id" property="id"></id><result column="name" property="name"></result><collection property="students" javaType="List" ofType="Student" select="findStudents" column="id"></collection></resultMap>

在一对多查询时,resultMap中要用到<collection>标签用于想要关联的表上

        <collection>标签中:property=""  表示所要映射到的哪个成员变量上

                                          javaType=""  表示映射的成员变量的类型

                                          ofType=""  表示映射的成员变量的类型里的数据类型

                                          select=""  表示映射的成员变量的查询语句

                                          column=""  表示映射的成员变量要以上一个查询的某一列数据作为查询条件

动态SQL问题

        以前在写sql查询语句时,难免会遇到一些多个条件一起查询的时候,当我们将每个条件都输入时才会出现一条结果。但如果在其中一个条件不成立时,就要修改sql语句,非常痛苦!

        在之前的动态sql语句中,例如:(借助Mybatis去展示原始动态sql问题)

<!--原始动态sql-->
<select id="teachers" resultType="Teacher">select * from teacherwhere <if test="num!=null">num = #{num}</if><if test="name!=null">and name = #{name}</if><if test="gender!=null">and gender = #{gender}</if></select>

当其中一个条件不成立或者多个条件不成立就会出现以下结果:

你的sql语句参差不齐,要么多关键字,要么关键字之间无sql语句

在之前对动态sql语句解决的办法就是在where后面自己加一个判断条件,让它永远成立,保证不管条件有没有成立,sql语句优先保证无误

<!--以前解决动态sql问题的解法--><select id="teachers" resultType="Teacher">select * from teacherwhere 1=1<if test="num!=null">num = #{num}</if><if test="name!=null">and name = #{name}</if><if test="gender!=null">and gender = #{gender}</if></select>

现在,在Mybatis里就增加了多种标签用于解决动态SQL问题

        1、if标签

                test属性条件成立 执行if标签体,不成立就不执行    

<select id="teachers" resultType="Teacher">select * from teacherwhere 1=1<if test="num!=null">num = #{num}</if><if test="name!=null">and name = #{name}</if><if test="gender!=null">and gender = #{gender}</if></select>

        2、where标签  

                当where标签 if语句有条件成立时,就会动态添加where关键字 还可以删除where后面紧跟着的关键字,例如and、or

<select id="teachers" resultType="Teacher">select * from teacher<where><if test="num!=null">num = #{num}</if><if test="name!=null">and name = #{name}</if><if test="gender!=null">and gender = #{gender}</if></where></select>

        3、trim标签

                当条件判断有成立时,可以自定义前缀关键字和后缀关键字

                        prefix="" 自定义关键字

                        prefixOverrides="" 覆盖指定的关键字

<select id="teachers" resultType="Teacher">select * from teacher<trim prefix="where" prefixOverrides="and|or"><if test="num!=null">num = #{num}</if><if test="name!=null">name = #{name}</if><if test="gender!=null">gender = #{gender}</if></trim></select>

        4、foreach标签

<select id="findTeacher" resultType="Teacher">select<foreach item="col" collection="list" separator=",">${col}</foreach>from teacher</select>

        <foreach>标签中:item=""  表示col变量存储遍历到当前的值

                                       collection=""  表示遍历集合类型

 特殊字符的转义

        在编写XML文件时,有些内容可能不想让解析引擎解析执行,而是当作原始内容处理。

        遇到此种情况,可以把这些内容放在CDATA区里,对于CDATA区域内的内容,XML解析程序不会处理,而是直接原封不动的输出。

语法:<![CDATA[ 内容 ]]><![CDATA[<itcast><br/></itcast>]]>

        对于一些单个字符,若想显示其原始样式,也可以使用转义的形式予以处理。

特殊字符替代符号
&&amp;
<&lt;
>&gt;
"&quot;
,&apos;

缓存    

        数据缓存 让数据离我们的执行程序更近。让程序能够更快速的获取到数据

        手机缓存,浏览器缓存......cpu缓存等等

   有缓存,查询下的查询流程
   先从缓存中查询,缓存中如果没有,去数据库查询,查询到后把数据放到缓存中,下次直接从缓存中获取

mybatis一级缓存

    mybatis一级缓存,默认是SqlSession级别的,在同一个SqlSession中查询到数据先缓存到SqlSession对象中
    第二次查询数据时,先从SqlSession中查询,如果有直接返回,没有,再去查询数据库

一级缓存生命周期:

    开始于SqlSession创建

    结束于SqlSession关闭。如果期间执行了新增、修改、删除操作也会清空当前SqlSession对象中的缓存数据

mybatis二级缓存

    二级缓存是SqlSessionFactory级别的,可以让多个SqlSession共享数据

    mybatis默认没有开启二级缓存,使用时需要配置开启

    如果开启了二级缓存,当SqlSession关闭时,会将一级缓存中的数据存储到二级缓存中。
    其他的SqlSession就可以查询二级缓存之前SqlSession查询的数据

    二级缓存的配置:

        1、在mybatis.xml配置文件中设置二级缓存的开关

<!--全局二级缓存开关--><setting name="cacheEnabled" value="true"/>

        2、在对应的模型类里去实现 Serializable 接口

import java.io.Serializable;public class Teacher implements Serializable

        3、在SQL 映射文件中添加一行:

<cache></cache>
<!--映射语句文件中的所有 select 语句的结果将会被缓存。映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。-->

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

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

相关文章

ubuntu20.04系统搭建k8s1.28集群-docker作为容器运行时

ubuntu系统搭建 ubuntu-22.04.5-desktop-amd64.iso映像文件--->实际却是20.4focal版本。 【安装过程没有特别指出的默认回车下一步】 【用户和密码设置】 【网络连接】 【在vmware上安装的话&#xff0c;网络配置如下】【在vm里配置选择nat或者桥接即可】 【国内源配置】&…

软件I2C

软件I2C 注意&#xff1a; SDA&#xff08;串行数据线&#xff09;和SCL&#xff08;串行时钟线&#xff09;都是双向I/O线&#xff0c;接口电路为开漏输出。需通过上拉电阻接电源VCC。 软件I2C说明 说明&#xff0c;有的单片机没有硬件I2C的功能&#xff0c;或者因为电路设计…

C++性能测试工具——Vtune的使用

一、Intel Vtune的安装 在前面初步认识了一下几个性能的测试工具&#xff0c;本篇重点介绍一下Intel VTune Profiler&#xff0c;VTune是一个强大的性能分析工具&#xff0c;它属于Intel oneAPI工具包中工具的一种。VTune的安装只介绍在Linux平台下的场景&#xff08;Windows安…

互联网大厂Java求职面试:优惠券服务架构设计与AI增强实践-6

互联网大厂Java求职面试&#xff1a;优惠券服务架构设计与AI增强实践-6 场景设定&#xff1a;技术总监张总坐在会议室里&#xff0c;郑薪苦带着自信的微笑走了进来。今天他们要围绕优惠券服务的架构设计及如何结合AI进行增强展开讨论。 第一轮面试&#xff1a;基础架构设计 …

nginx模块使用、过滤器模块以及handler模块

一、如何使用nginx的模块 1.ngx_code.c: #include "ngx_config.h" #include "ngx_conf_file.h" #include "nginx.h" #include "ngx_core.h" #include "ngx_string.h" #include "ngx_palloc.h" #include "n…

【Odoo】Pycharm导入运行Odoo15

【Odoo】Pycharm导入运行Odoo15 前置准备1. Odoo-15项目下载解压2. PsrtgreSQL数据库 项目导入运行1. 项目导入2. 设置项目内虚拟环境3. 下载项目中依赖4. 修改配置文件odoo.conf 运行Pycharm快捷运行 前置准备 1. Odoo-15项目下载解压 将下载好的项目解压到开发目录下 2. …

网络安全-等级保护(等保) 2-5 GB/T 25070—2019《信息安全技术 网络安全等级保护安全设计技术要求》-2019-05-10发布【现行】

################################################################################ GB/T 22239-2019 《信息安全技术 网络安全等级保护基础要求》包含安全物理环境、安全通信网络、安全区域边界、安全计算环境、安全管理中心、安全管理制度、安全管理机构、安全管理人员、安…

【SpringBoot】✈️整合飞书群机器人发送消息

&#x1f4a5;&#x1f4a5;✈️✈️欢迎阅读本文章❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;本篇文章阅读大约耗时3分钟。 ⛳️motto&#xff1a;不积跬步、无以千里 &#x1f4cb;&#x1f4cb;&#x1f4cb;本文目录如下&#xff1a;&#x1f381;&#x1f381;&am…

我的多条件查询

背景&#xff1a;2个表&#xff0c;是一对多的关系&#xff0c;一个实时视频帧可以出现多个检测结果 要求&#xff0c;可以根据&#xff0c;ids&#xff0c;起始时间&#xff0c;识别出的鸟的种类&#xff0c;来进行删除。 出现的问题&#xff0c; 一致性没有实现&#xff1a…

关于网站提交搜索引擎

发布于Eucalyptus-blog 一、前言 将网站提交给搜索引擎是为了让搜索引擎更早地了解、索引和显示您的网站内容。以下是一些提交网站给搜索引擎的理由&#xff1a; 提高可见性&#xff1a;通过将您的网站提交给搜索引擎&#xff0c;可以提高您的网站在搜索结果中出现的机会。当用…

【Oracle专栏】扩容导致数据文件 dbf 丢失,实操

Oracle相关文档,希望互相学习,共同进步 风123456789~-CSDN博客 1.背景 同事检查扩容情况,发现客户扩容后数据盘后,盘中原有文件丢失,再检查发现数据库没有启动。通过检查发现数据盘中丢失的是oracle的 dbf 表空间文件。数据库无法启动。 检查情况:1)没有rman备份 …

负载均衡—会话保持技术详解

一、会话保持的定义 会话保持&#xff08;Session Persistence&#xff09;是一种负载均衡策略&#xff0c;其核心机制是确保来自同一客户端的连续请求&#xff0c;在特定周期内被定向到同一台后端服务器进行处理。这种机制通过记录和识别客户端的特定标识信息&#xff0c;打破…

CSRF攻击 + 观测iframe加载时间利用时间响应差异侧信道攻击 -- reelfreaks DefCamp 2024

参考: https://0x90r00t.com/2024/09/30/3708/ 题目信息 有些事情最好还是保持低调。当然&#xff0c;除非你是个真正的怪胎。 注意&#xff1a;该网站通过HTTPS提供服务 标志格式&#xff1a;DCTF&#xff5b;&#xff5d;题目实现了一个类似视频网站的东西 在其提供的数据库中…

JS逆向-某易云音乐下载器

文章目录 介绍下载链接Robots文件搜索功能JS逆向**函数a&#xff1a;生成随机字符串****函数b&#xff1a;AES-CBC加密****函数c&#xff1a;RSA公钥加密** 歌曲下载总结 介绍 在某易云音乐中&#xff0c;很多歌曲听是免费的&#xff0c;但下载需要VIP&#xff0c;此程序旨在“…

黑马k8s(十)

1.Pod生命周期-钩子函数 2.Pod生命周期-容器探测 因为没有hello.txt文件 查看详情&#xff1a; 修改为查看命令&#xff1a; 查看一下详情&#xff1a; 因为只有一个80端口&#xff0c;没有8080&#xff0c;所以会重启 查看详情&#xff1a; 修改成80&#xff1a; 因为没有…

每日算法刷题Day9 5.17:leetcode定长滑动窗口3道题,用时1h

9. 1652.拆炸弹(简单&#xff0c;学习) 1652. 拆炸弹 - 力扣&#xff08;LeetCode&#xff09; 思想 为了获得正确的密码&#xff0c;你需要替换掉每一个数字。所有数字会 同时 被替换。 如果 k > 0 &#xff0c;将第 i 个数字用 接下来 k 个数字之和替换。如果 k < 0…

Java IO及Netty框架学习小结

Netty netty官网: Netty 什么是Netty&#xff1f; Netty 是 一个异步事件驱动的网络应用程序框架&#xff0c;用于快速开发可维护的高性能协议服务器和客户端。Netty 是一个 NIO 客户端服务器框架&#xff0c;可以快速轻松地开发网络应用程序&#xff08;例如协议服务器和客…

计算机网络笔记(二十七)——4.9多协议标签交换MPLS

4.9.1MPLS的工作原理 一、MPLS基本工作原理 MPLS&#xff08;Multiprotocol Label Switching&#xff09;是一种介于数据链路层和网络层之间的转发技术&#xff0c;通过固定长度的标签进行高速数据转发。其核心特点是通过预建立的标签交换路径&#xff08;Label Switching Pa…

AI 赋能 Copula 建模:大语言模型驱动的相关性分析革新

技术点目录 R及Python语言及相关性研究初步二元Copula理论与实践&#xff08;一&#xff09;二元Copula理论与实践&#xff08;二&#xff09;【R语言为主】Copula函数的统计检验与选择【R语言为主】高维数据与Vine Copula 【R语言】正则Vine Copula&#xff08;一&#xff09;…

【洛谷P3386】二分图最大匹配之Kuhn算法/匈牙利算法:直观理解

题目&#xff1a;洛谷P3386 【模板】二分图最大匹配 &#x1f955; 匈牙利算法本来是针对带权图最大匹配的&#xff0c;这里由于题目只是求最大匹配的边数&#xff0c;所以我们也只考虑无权的情况。 &#x1f680; 本文旨在服务于看了别的关于匈牙利算法的文章但不甚理解的童…