初始MyBatis ,详细步骤运行第一个MyBatis程序,同时对应步骤MyBatis底层剖析

news2024/11/25 10:57:23

1. 初始MyBatis ,详细步骤运行第一个MyBatis程序,同时对应步骤MyBatis底层剖析

文章目录

  • 1. 初始MyBatis ,详细步骤运行第一个MyBatis程序,同时对应步骤MyBatis底层剖析
  • 每博一文案
  • 2. 前沿知识
    • 2.1 框架(framework)
    • 2.2 三层架构
    • 2.3 分析 JDBC 的缺点
  • 3. 初始了解MyBatis
  • 4. MyBatis第一个入门程序
    • 4.1 MyBatis下载
    • 4.2 MyBatis入门程序开发步骤
    • 4.3 MyBatis 的第一个入门程序的细节问题
  • 5. 关于MyBatis核心配置文件的名字和路径详解
  • 6. 关于 mybatis 的事务管理机制(深度剖析)
  • 7. MyBatis第一个比较完整的代码写法
  • 8. MyBatis 引入日志框架
    • 8.1 使用 MyBatis 自带的日志框架
    • 8.2 引入 logback 日志框架
  • 9. 总结:
  • 10. 最后:


每博一文案

才华果然比金钱更耀眼

2. 前沿知识

2.1 框架(framework)

Java当中常见的框架:

  • SSM三大框架:Spring + SpringMVC + MyBatis
  • SpringBoot
  • SpringCloud

框架其实就是对通用代码的封装,被提前写好的一大堆接口和类(供你使用),我们可以在做项目的时候直接引入这些接口和类(引入框架),基于这些现有的接口和类进行开发,可以大大提高开发效率。

框架一般都是以jar 包的形式存在。(jar 包中有 class 文件以及各种配置文件等。)

SSM三大框架的学习顺序:MyBatis,Spring,SpringMVC 。因为 MyBatis 框架和后面两个 Spring,SpringMVC 比较的独立开来了,可以先学。

关于Spring 框架的内容,大家感兴趣的可以移步至:✏️✏️✏️ Spring_ChinaRainbowSea的博客-CSDN博客

2.2 三层架构

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 表示层(直接跟前端进行交互的,一是接受前端 AJAX 请求,二是返回 JSON 数据给前端)
  • 业务逻辑层:一是处理表现层转发过来的前端请求(也就是具体的业务),二是将从持久层获取的数据返回到表示层。
  • 数据访问层:直接操作数据库完成CRUD,并获得数据返回到上一层(也就是业务逻辑层)
  • Java持久层框架:

关于持久层的框架有如下这些:

  • MyBatis
  • Hibernate(实现了JPA规范)
  • jOOQ
  • Guzz
  • Spring Data(实现了JPA 规范)
  • ActiveJDBC

更多关于三层架构的内容,大家可以移步至:✏️✏️✏️ MVC 三层架构案例详细讲解_mvc三层架构-CSDN博客

2.3 分析 JDBC 的缺点

我们先观察,分析如下代码的

示例1:

// ......
// sql语句写死在java程序中
String sql = "insert into t_user(id,idCard,username,password,birth,gender,email,city,street,zipcode,phone,grade) values(?,?,?,?,?,?,?,?,?,?,?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
// 繁琐的赋值:思考一下,这种有规律的代码能不能通过反射机制来做自动化。
ps.setString(1, "1");
ps.setString(2, "123456789");
ps.setString(3, "zhangsan");
ps.setString(4, "123456");
ps.setString(5, "1980-10-11");
ps.setString(6, "男");
ps.setString(7, "zhangsan@126.com");
ps.setString(8, "北京");
ps.setString(9, "大兴区凉水河二街");
ps.setString(10, "1000000");
ps.setString(11, "16398574152");
ps.setString(12, "A");
// 执行SQL
int count = ps.executeUpdate();
// ......

示例2:

// ......
// sql语句写死在java程序中
String sql = "select id,idCard,username,password,birth,gender,email,city,street,zipcode,phone,grade from t_user";
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
List<User> userList = new ArrayList<>();
// 思考以下循环中的所有代码是否可以使用反射进行自动化封装。
while(rs.next()){
    // 获取数据
    String id = rs.getString("id");
    String idCard = rs.getString("idCard");
    String username = rs.getString("username");
    String password = rs.getString("password");
    String birth = rs.getString("birth");
    String gender = rs.getString("gender");
    String email = rs.getString("email");
    String city = rs.getString("city");
    String street = rs.getString("street");
    String zipcode = rs.getString("zipcode");
    String phone = rs.getString("phone");
    String grade = rs.getString("grade");
    // 创建对象
    User user = new User();
    // 给对象属性赋值
    user.setId(id);
    user.setIdCard(idCard);
    user.setUsername(username);
    user.setPassword(password);
    user.setBirth(birth);
    user.setGender(gender);
    user.setEmail(email);
    user.setCity(city);
    user.setStreet(street);
    user.setZipcode(zipcode);
    user.setPhone(phone);
    user.setGrade(grade);
    // 添加到集合
    userList.add(user);
}
// ......

JDBC的不足点:

SQL语句写牢在了Java程序当中了,不灵活,改SQL的话,就要改Java代码,违背了开闭原则OCP。

? 占位符传值是繁琐的,不能自动化

将结果集封装成Java对象也是比较繁琐的,不能自动化

关于这些自动化的问题,以及OCP开闭原则,运用下面我们正在学习的MyBatis 可以得到一个很好的解决方案。

关于JDBC的更多详细内容,大家可以移步至:✏️✏️✏️ JDBC_ChinaRainbowSea的博客-CSDN博客

3. 初始了解MyBatis

MyBatis 本质上就是对JDBC的封装,通过MyBatis完成CRUD。

MyBatis 在三层架构中负责持久层,属于持久层框架。

MyBatis的发展历程:这里【引用百度百科】

  • MyBatis本是apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了[google code](https://baike.baidu.com/item/google code/2346604?fromModule=lemma_inlink),并且改名为MyBatis。2013年11月迁移到Github。
  • iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)。
  • 当前,最新版本是MyBatis 3.5.13,其发布时间是2023年03月11日。

打开MyBatis 代码可以看到它的包结构中包含:ibatis

在这里插入图片描述

ORM :对象关系映射。

O (object) :Java虚拟机中的Java对象。

R(Relational):关系型数据库

M(Mapping):将Java虚拟机中的Java对象映射到数据库表中一行记录,或是将数据库表中一行记录映射成Java虚拟机中的一个Java对象。

ORM示图:

在这里插入图片描述

在这里插入图片描述

MyBatis 框架就是一个ORM框架。

MyBatis可以干啥?

java 对象 < ------ > 数据库表中的一条记录

在这里插入图片描述

User 这样在图中,有特殊的称呼:
有的人把它叫做:pojo(普通Java)
有的叫做: JavaBean (咖啡豆)
有的叫做: domain(领域模型)

MyBatis 是一个半自动化的ORM,因为MyBatis 框架中SQL语句是需要程序员自己写的。

Hibernate 框架是一个全自动化的ORM 使用Hibenrnate 框架的时候,不需要程序员手动编写SQL语句,SQL语句可以自动生成,所以Hibernate 是一个完全的全自动化的ORM框架。

这里我们的主题是 MyBatis 。

MyBatis 框架特点:

  1. 支持定制化SQL,存储过程,基本映射以及高级映射
  2. 避免了几乎所有的 JDBC代码中手动设置参数以及获取结果集。
  3. 支持XML 开发,也支持注解开发。【为了保证 SQL 语句的灵活,所有MyBatis 大部分采用 XML方式开发。
  4. 将接口和 Java 的 POJOs(Plain Ordinary Java Object ,简单普通的Java对象)映射成数据库中的记录
  5. 体积小,好学,两个jar 包,两个 XML 配置文件
  6. 完全做到 SQL 解耦合
  7. 提供了基本映射标签
  8. 提供了高级映射标签
  9. 提供了XML标签,支持动态SQL的编写。

4. MyBatis第一个入门程序

4.1 MyBatis下载

  • 从github上下载,地址:https://github.com/mybatis/mybatis-3

在这里插入图片描述

在这里插入图片描述

将框架以及框架的源码都下载下来,下载框架后解压,打开mybatis目录

在这里插入图片描述

  • 通过以上解压可以看到,框架一般都是以jar包的形式存在。我们的mybatis课程使用 maven,所以这个jar我们不需要。

  • 官方手册需要。但是,这个官方文档是英文的,对应英文不好的朋友,大家可以来的这个网站:https://mybatis.net.cn/ 是一个 mybatis 的中文网站。

  • 在这里插入图片描述

4.2 MyBatis入门程序开发步骤

首先我们先准备好数据库信息

准备数据库表:汽车表t_car,字段包括:

id:主键(自增)【bigint】
car_num:汽车编号【varchar】
brand:品牌【varchar】
guide_price:厂家指导价【decimal类型,专门为财务数据准备的类型】
produce_time:生产时间【char,年月日即可,10个长度,‘2022-10-11’】
car_type:汽车类型(燃油车、电车、氢能源)【varchar】

DROP TABLE IF EXISTS `t_car`;
CREATE TABLE `t_car`  (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键,和业务没有关系,自增',
  `car_num` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '汽车编号',
  `brand` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '汽车品牌',
  `guide_price` decimal(10, 2) NULL DEFAULT NULL COMMENT '厂商指导价格',
  `produce_time` char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '生产日期',
  `car_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '汽车类型,燃油车,氢能源',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 33 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;
INSERT INTO `t_car` VALUES (1, '1001', '宝马520Li', 10.00, '2020-10-11', '燃油车');
INSERT INTO `t_car` VALUES (2, '1002', '奔驰E300L', 55.00, '2020-11-11', '新能源');
INSERT INTO `t_car` VALUES (5, '1003', '丰田霸道', 30.00, '2000-10-11', '燃油车');

在这里插入图片描述

在这里插入图片描述

创建Project:建议创建Empty Project,设置Java版本以及编译版本等。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

创建Module:普通的Maven Java模块

第一步:通过maven 在 pom.xml 文件当中引入相关依赖。

mybatis依赖 ,mysql依赖

在这里插入图片描述

<!--mybatis核心依赖-->
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.5.10</version>
</dependency>

<!--mysql驱动依赖-->
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.30</version>
</dependency>
<?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>

    <groupId>com.ranbowsea</groupId>
    <artifactId>mybatis-001-introduction</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>


    <dependencies>
        <!--mybatis核心依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.10</version>
        </dependency>
        
        <!--mysql驱动依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
        </dependency>
    </dependencies>



</project>

第二步:在 resources 根(类)目录下新建 mybatis-config.xml(文件名随意)配置文件(可以参考mybatis手册拷贝 (https://mybatis.net.cn/getting-started.html))

注意:

  1. 第一,这个文件名不是必须叫 mybatis-config.xml,可以用其他的名字,只是大家都采用这个名字。
  2. 这个文件存放的位置也不是固定的,可以随意,但一般情况下,会放到类的根路径下

关于这两点的注意事项,该文章的后面,会详细说明。请继续看下去。
在这里插入图片描述

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/powernode"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--sql映射文件创建好之后,需要将该文件路径配置到这里-->
        <mapper resource=""/>
    </mappers>
</configuration>

第三步:编写XxxMapper.xml 文件

在这个配置文件当编写SQL语句。

这个文件名也不是固定的,放的位置也不是固定的,我们这里给它起个名字,叫做:CarMapper.xml (mapper 英文单词是“映射”的意思),把它暂时放到类的根路径下。

在resources根目录下新建CarMapper.xml配置文件(可以参考mybatis手册拷贝)

在这里插入图片描述

同时我们在其中编写一条SQL语句,一条insert 插入的SQL语句。

注意编写的是 insert 插入的SQL语句所以,在该 xml 文件中用,<insert> 标签进行定义编写。如下:

在这里插入图片描述

而在<insert> 标签当中,需要定义一个 id 属性的值,该

insert语句,id是这个条SQL语句的唯一标识,这个id就代表了这条SQL语句

在这里插入图片描述

<!--	insert语句,id是这个条SQL语句的唯一标识,这个id就代表了这条SQL语句 -->
	<insert id="insertCar">
		insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
		values (null,'1003','丰田霸道',30.0,'2000-10-11','燃油车')
	</insert>
// 因为我们的 id 是主键,自增的,所以可以不赋值。为 null ,让其进行一个自增的效果。

因为我们的 id 是主键,自增的,所以可以不赋值。为 null ,让其进行一个自增的效果。

注意1:sql语句最后结尾可以不写“;”

注意2:CarMapper.xml文件的名字不是固定的。可以使用其它名字。

注意3:CarMapper.xml文件的位置也是随意的。这里选择放在resources根下,相当于放到了类的根路径下。

注意4:将CarMapper.xml文件路径配置到mybatis-config.xml:

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
		PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
		"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace先随意写一个-->
<mapper namespace="fas">

<!--	insert语句,id是这个条SQL语句的唯一标识,这个id就代表了这条SQL语句 -->
	<insert id="insertCar">
		insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
		values (null,'1003','丰田霸道',30.0,'2000-10-11','燃油车')
	</insert>
</mapper>

第四步: 在mybatis-config.xml 文件中指定XxxMapper.xml 文件的路径

就是将我们上面配置的 XxxMapper.xml(这里是 CarMapper.xml) 的SQL语句的映射文件创建好,将该文件所在位置的路径,填入到 <mapper resource="xxx"> 当中,让MyBatis 框架可以顺利的找到它,并执行其中的SQL语句。注意:resource 属性会自动从类的根路径下开始查找资源。

<mapper resource="CarMapper.xml">

注意:resource 属性会自动从类的根路径下开始查找资源。

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
<!--            MANAGED 没有用第三框架管理的话,都是会被提交的,没有事务上的管理了。-->
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="MySQL123"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>

        <!--sql映射文件创建好之后,需要将该文件路径配置到这里-->
<!--        执行XxxMapper.xml 文件的路径-->
<!--        resource 属性自动会从类的根路径下开始查找资源-->
        <mapper resource="CarMapper.xml"/>
    </mappers>

</configuration>

第五步: 编写MyBatis 测试程序(使用MyBatis的类库,编写myBatis 程序,该数据库,做增删改查就行了)

首先我们需要知道,在MyBatis 当中,负责执行SQL语句的是哪个对象,同时又该如何获取到该对象。

负责执行 SQL语句的对象是: SqlSession

在这里插入图片描述

SqlSession 是专门来执行 SQL语句的,是一个Java程序和数据库之间的一次会话

在这里插入图片描述

想要获取到 SqlSession 对象,就需要先获取SqlSessionFactory 对象,通过SqlSessionFactory 工厂的openSession( ) 方法,来生产 SqlSession 对象。

在这里插入图片描述

在这里插入图片描述

那怎么湖获取SqlSessionFactory 对象

通过SqlSessionFactoryBuilder 对象的 build( ) 方法,来获取一个SqlSessionFactory 对象。

在这里插入图片描述

在这里插入图片描述

总结:

MyBatis的核心对象包括:
SqlSessionFactoryBuilder
SqlSessionFactory
SqlSession

SqlSessionFactoryBuilder–>SqlSessionFactory–>SqlSession

注意事项:

int count = sqlSession.insert("insertCar"); // 这个"insertCar"必须是sql的id

该insert(id) 就是,我们上面 CarMapper.xml SQL映射文件当中编写的 SQL 语句(这里是 <insert> 标签当中的 id 的属性值,保持一致)

在这里插入图片描述

同时需要:

执行 sqlSession.commit(); 提交数据给数据库(和JDBC是一样的); 提交(mybatis默认采用的事务管理器是JDBC,默认是不提交的,需要手动提交。)

以及执行: sqlSession.close(); 关闭资源,注意:仅仅是关闭资源,并不会提交数据的。

// 5. 提交(mybatis默认采用的事务管理器是JDBC,默认是不提交的,需要手动提交。)
sqlSession.commit();
// 6. 关闭资源(只关闭是不会提交的)
sqlSession.close();

在这里插入图片描述

完整执行代码:

在这里插入图片描述


import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;


import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class MyBatisIntroductionTest {

    public static void main(String[] args) {
        // 1. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // 2. 创建SqlSessionFactory对象
        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
        // 3. 创建SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 4. 执行sql
        int count = sqlSession.insert("insertCar"); // 这个"insertCar"必须是sql的id
        System.out.println("插入几条数据:" + count);
        // 5. 提交(mybatis默认采用的事务管理器是JDBC,默认是不提交的,需要手动提交。)
        sqlSession.commit();
        // 6. 关闭资源(只关闭是不会提交的)
        sqlSession.close();

    }
}

运行结果:

在这里插入图片描述

在这里插入图片描述

MyBatis 第一个入门程序小总结:

第一: 在MyBatis中一定是有一个很重要的对象,这个对象是:SqlSessionFactory对象

第二: SqlSessionFactory 对象的创建需要 xml
xml 是什么?它是一个配置文件

MyBatis中有两个主要的配置文件:

  1. mybatis-config.xml ,这是核心配置文件,主要配置连接数据库的信息等(一般是第一个数据库一个),同样的与之对应的通过mybatis-config.xml 的配置文件创建的对象 SqlSessionFactoryBuilder,SqlSessionFactory 也是一个数据库一个对象
  2. XxxMapper.xml ,这个是专门用来编写SQL语句的配置文件(一个数据表一个)。

t_user 表,一般会对应一个UserMapper.xml

t_student 表,一般会对应一个StudentMapper.xml

4.3 MyBatis 的第一个入门程序的细节问题

  1. 在MyBatis 中的SQ语句的结尾“;” 可以省略的。

在这里插入图片描述

  1. 在 MyBatis 当中的 SQL语句错误的,异常信息是:java.sql.SQLSyntaxErrorException 该异常表示是你的SQL语句写的不对,SQL语法可能存在问题。

在这里插入图片描述

  1. 在MyBatis 当中的工具类: Resource.getResourceAsStream( ) 方法。

在这里插入图片描述

小技巧:以后凡是遇到 resource 这个单词,大部分情况下,这种加载资源的方式就是从(resource)类路径下开始检索加载的。

例如: 下面三种获取 IO流文件的,检索方式都是从类路径下开始的。

 InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatis-config.xml");
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("mybatis-config.xml");  // 使用类加载器

采用从 (resource)类路径 加载文件的优点:

采用这种方式,从类的路径当种加载资源,项目的移植性很强,项目从Windwos移植到Linux,没有路径上的问题

而下面这个是:从系统的绝对路径开始加载的

InputStream stream = new FileInputStream("E:\\mybatis-config.xml");

采用系统的绝对路径加载文件资源的缺点:

可移植性差,程序不够健壮,可能移植到其他的操作系统当中,导致以上路径无效,比如Linux,因为Linux系统是没有所谓的D盘,C盘之类的说法。所以想要移植到Linux当中运行的话,还需要修改Java代码才行。这样就违背了OCP原则了。

5. 关于MyBatis核心配置文件的名字和路径详解

MyBatis 的核心配置文件就是,我们上述的名为 mybatis-config.xml 的配置文件。

在这里插入图片描述

已经验证过了,mybatis 核心配置文件的名字,不一定是:mybatis-config.xml 。mybatis 核心配置文件存放的路径,也不一定是类的根路径,可以放到其他的位置,但是为了项目的移植性。健壮性,最好将这个配置文件放到类路径下面。

同理的对应的 SQL 映射文件 XxxMapper.xml 文件的路径也可以不放在根(类)路径下,不过如果 SQL 映射文件 XxxMapper.xml 文件是根据 系统的绝对路径 来的话,需要用 <url> 标签。如下:

在这里插入图片描述

重点:注意的是,无论是 MyBatis 的核心配置文件,还是对应的 SQL 映射文件 XxxMapper.xml 文件,如果文件含义目录的话,一定要带上目录才行如下:
在这里插入图片描述

在这里插入图片描述

源码解析:MyBatis 工具类的:InputStream is = Resources.getResourceAsStream(“mybatis-config.xml”) 的底层调用的机制。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


> InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("mybatis-config.xml")
> ClassLoader.getSystemClassLoader() 获取系统的类加载器。
> 系统类加载器有一个方法叫做:getResourceAsSteam
> 它就是从类路径当中加载资源的
> 通过源代码分析发现:
>   InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
>   底层的源代码其实现就是:
> InputStream is = ClasLoader.getSystemClassLoader().getResourceAsStream("mybatis-config.xml");
> 

6. 关于 mybatis 的事务管理机制(深度剖析)

关于 mybatis 的事务管理机制:

在mybatis-config.xml 文件中,可以通过以下的配置进行 mybatis 的事务处理。

通过:**<transactionManager type=“JDBC”> ** 标签进行设置即可。

在这里插入图片描述

type 的属性值包括两个:

  • JDBC (jdbc)
  • MANGED(managed)

type 后面的值,只有以上两个值可以选择,不区分大小写。

在mybatis 中提供了两种事务管理机制。

  1. 第一种 JDBC事务管理器

MyBatis 框架自己管理事务,自己采用原生的JDBC 代码去管理事务

> conn.setAutoCommit(false);开启事务,false 是默认的,可以不用写
> ...业务处理...
> conn.commit(); 手动提交事务

使用JDBC事务管理器的话,底层创建的事务管理器对象,jdbcTransaction对象。

如果你编写的代码是下面的代码:
  SqlSession sqlSession = sqlSessionFactory.openSession(true);
  表示没有开启事务,因为这种方式压根不会执行,com.setAutoCommit(false)
  在JDBC事务中,没有执行com.setAutoCommit(false);那么autoCommit就是true.
  如果autoCommit 是 true ,就表示没有开启事务,只要执行任意一条DML语句就提交了一次

我们可以进行一个 Debug 调试,进行一个检查

这里我们用默认的 false ,也可以不填,都是 false

在这里插入图片描述

  SqlSession sqlSession = sqlSessionFactory.openSession();
  SqlSession sqlSession = sqlSessionFactory.openSession(false);

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

下面我们设置为:true
在这里插入图片描述

在这里插入图片描述

在 JDBC事务管理器 下,SqlSession sqlSession = sqlSessionFactory.openSession( 不填,或者 false); 表示开启事务了(需要自己手动提交,sqlSession.commit()😉,填 true 表示关闭了事务,自动就会提交了

  1. 第二种 MANAGED 是事务管理器

在 mybatis 不再负责事务的管理了,事务管理交给其他容器来负责,例如:Spring

<!--            MANAGED 没有用第三框架管理的话,都是会被提交的,没有事务上的管理了。-->
            <transactionManager type="MANAGED"/>

在这里插入图片描述

在这里插入图片描述

MyBatis 说,我不管事务了(会自动提交数据给数据库),你来负责吧(Spring)

如果对于我们当前的单纯的只有 MyBatis 的情况下,如果配置为:MANAGED ,那么事务这块是没人管的,没有人管理事务标识,事务压根没有开启,后面我们可以配合使用Spring 进行事务上的管理。

关于 MyBatis 配合Spring 开启事务的详细内容,大家可以移步至:✏️✏️✏️ Spring6 对 集成MyBatis 开发运用(附有详细的操作步骤)-CSDN博客

7. MyBatis第一个比较完整的代码写法

resources 的配置文件下的信息。

CarMapper.xml SQL 语句的映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
		PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
		"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace先随意写一个-->
<mapper namespace="fas">

<!--	insert语句,id是这个条SQL语句的唯一标识,这个id就代表了这条SQL语句 -->
	<insert id="insertCar">
		insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
		values (null,'1003','丰田霸道',30.0,'2000-10-11','燃油车');
	</insert>
</mapper>

mybatis-config.xml 的MyBatis 的核心配置文件。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--    开启mybatis 对标准日志的实现-->
<!--    如果导入的第三方框架的日志,没有下面这个 settings 也是可以的-->
<!--    <settings>-->
<!--        <setting name="logImpl" value="STDOUT_LOGGING"/>-->
<!--    </settings>-->
    <environments default="development">
        <environment id="development">
<!--            MANAGED 没有用第三框架管理的话,都是会被提交的,没有事务上的管理了。-->
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="MySQL123"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>

        <!--sql映射文件创建好之后,需要将该文件路径配置到这里-->
<!--        执行XxxMapper.xml 文件的路径-->
<!--        resource 属性自动会从类的根路径下开始查找资源-->
<!--        <mapper resource="CarMapper.xml"/>-->
        <mapper resource="com/CarMapper2.xml"/>

<!--        url属性: 从绝对路径当中加载资源。-->
<!--        语法格式:file:///绝对路径-->
<!--        <mapper url="file:///e:/CarMapper.xml"></mapper>-->
    </mappers>

</configuration>

运行测试程序:

package com.rainbowsea.mybatis.test;

import com.ranbowsea.mybatis.utils.SqlSessionUtil;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.IOException;

public class MyBatisCompleteTest {
    public static void main(String[] args) {
        // 获取到SqlSessionFactoryBuilder 对象
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSession sqlSession = null;

        try {
            // 获取到SqlSessionFactoryBuilder 一个数据库对应一个 SqlSessionFactoryBuilder
            SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsReader("mybatis-config.xml"));

            // 获取到SqlSession对象
            sqlSession = sqlSessionFactory.openSession();


            sqlSession.insert("insertCar");// 对应 执行SQL语句对应的数据表的 XxxMapper.xml当中,对应SQL语句的id

            // 执行到这里,提交事务,终止事务
            sqlSession.commit();
        } catch (IOException e) {
            if(sqlSession != null) {  // 上面可能 sqlSession 还是为空
                // 回滚事务
                sqlSession.rollback();
            }
            throw new RuntimeException(e);
        } finally {
            if(sqlSession != null) {

                // 关闭会话
                sqlSession.close();
            }
        }




    }

}

在这里插入图片描述

8. MyBatis 引入日志框架

8.1 使用 MyBatis 自带的日志框架

引入日志框架的目的:是为了看清楚MyBatis执行的具体的 SQL语句,以及赋值内容。

启动MyBatis 自带的标准日志组件,只需要在mybatis-config.xml MyBatis 的核心配置文件中添加配置文件【可参考mybatis 手册https://mybatis.net.cn/logging.html】在这里插入图片描述

关于mybatis 集成日志组件,让我们调试起来更加方便。
mybatis常见的集成的日志组件有哪些呢?
SLF4J(沙拉风)
LOG4J
LOG$J2
STDOUT_LOGGING

注意:log4j log4j2 logback都是同一个作者开发的。
其中STDOUT_LOGGING 是标准日志,mybatis已经实现了这种标准日志,mybatis框架本身已经实现了这种
标准。只要开启即可,怎么开启呢?在mybatis-config.xml文件中使用settings标签进行配置开启。

在这里插入图片描述

<settings>
  <setting name="logImpl" value="STDOUT_LOGGING" />
</settings>

注意:

这个标签在编写的时候要注意,它必须在 environments 标签之前(不然会报错的),注意顺序,当然,不需要记忆这个顺序。
因为有dtd文件进行约束呢。我们只要参考did约束即可

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--    开启mybatis 对标准日志的实现-->
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <environments default="development">
        <environment id="development">
<!--            MANAGED 没有用第三框架管理的话,都是会被提交的,没有事务上的管理了。-->
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="MySQL123"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>

        <!--sql映射文件创建好之后,需要将该文件路径配置到这里-->
<!--        执行XxxMapper.xml 文件的路径-->
<!--        resource 属性自动会从类的根路径下开始查找资源-->
<!--        <mapper resource="CarMapper.xml"/>-->
        <mapper resource="com/CarMapper2.xml"/>

<!--        url属性: 从绝对路径当中加载资源。-->
<!--        语法格式:file:///绝对路径-->
<!--        <mapper url="file:///e:/CarMapper.xml"></mapper>-->
    </mappers>

</configuration>

运行测试:

在这里插入图片描述

在这里插入图片描述

8.2 引入 logback 日志框架

上述的MyBatis 自带的日志框架,这种实现也是可以的,可以看到一些信息,比如:连接对象什么时候创建,什么时候关闭,sql语句是怎样的
但是没有详细的日期,线程名字,等,如果你想使用更加丰富的配置,可以集成第三方Log组件。

同时配置也不够灵活,我们可以集成其他的日志组件,例如:log4j,logback等。

  • logback是目前日志框架中性能较好的,较流行的,所以我们选它。
  • 引入logback的步骤:

logback 日志框架实现了slf4j标准(沙拉风,日志门面,日志标准)

第一步: 引入logback的依赖

我们需要在项目的 pom.xml 配置文件当中,引入 logbakc 的依赖,通过 maven 进行导入。

在这里插入图片描述

<!--        引入 logback的依赖,这个日志框架实现了slf4j 规范-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.11</version>
        </dependency>
<?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>

    <groupId>com.ranbowsea</groupId>
    <artifactId>mybatis-001-introduction</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>


    <dependencies>
        <!--mybatis核心依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.10</version>
        </dependency>
        <!--mysql驱动依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
        </dependency>

<!--        junit 依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>

<!--        引入 logback的依赖,这个日志框架实现了slf4j 规范-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.11</version>
        </dependency>
    </dependencies>



</project>

第二步:如logback所必须的 xml 配置文件

注意:这个配置文件的名字必须叫做:logback.xml 或者 logback-test.xml 不能是其他的名字
并且这个配置文件必须放到类的根路径下,不能是其他位置。

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>

<configuration debug="false">
    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>
    <!-- 按照每天生成日志文件 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${LOG_HOME}/TestWeb.log.%d{yyyy-MM-dd}.log</FileNamePattern>
            <!--日志文件保留天数-->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
        <!--日志文件最大的大小-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>100MB</MaxFileSize>
        </triggeringPolicy>
    </appender>

    <!--mybatis log configure-->
    <logger name="com.apache.ibatis" level="TRACE"/>
    <logger name="java.sql.Connection" level="DEBUG"/>
    <logger name="java.sql.Statement" level="DEBUG"/>
    <logger name="java.sql.PreparedStatement" level="DEBUG"/>

    <!-- 日志输出级别,logback日志级别包括五个:TRACE < DEBUG < INFO < WARN < ERROR -->
    <root level="DEBUG">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="FILE"/>
    </root>

</configuration>

在这里插入图片描述

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>

<configuration debug="false">
    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>

    <!--mybatis log configure-->
    <logger name="com.apache.ibatis" level="TRACE"/>
    <logger name="java.sql.Connection" level="DEBUG"/>
    <logger name="java.sql.Statement" level="DEBUG"/>
    <logger name="java.sql.PreparedStatement" level="DEBUG"/>

    <!-- 日志输出级别,logback日志级别包括五个:TRACE < DEBUG < INFO < WARN < ERROR -->
    <root level="ERROR">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="FILE"/>
    </root>

</configuration>

在这里插入图片描述

配置好以后,我们运行看看。

在这里插入图片描述

package com.rainbowsea.mybatis.test;

import com.ranbowsea.mybatis.utils.SqlSessionUtil;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.IOException;

public class MyBatisCompleteTest {
    public static void main(String[] args) {
        // 获取到SqlSessionFactoryBuilder 对象
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSession sqlSession = null;

        try {
            // 获取到SqlSessionFactoryBuilder 一个数据库对应一个 SqlSessionFactoryBuilder
            SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsReader("mybatis-config.xml"));

            // 获取到SqlSession对象
            sqlSession = sqlSessionFactory.openSession();


            sqlSession.insert("insertCar");// 对应 执行SQL语句对应的数据表的 XxxMapper.xml当中,对应SQL语句的id

            // 执行到这里,提交事务,终止事务
            sqlSession.commit();
        } catch (IOException e) {
            if(sqlSession != null) {  // 上面可能 sqlSession 还是为空
                // 回滚事务
                sqlSession.rollback();
            }
            throw new RuntimeException(e);
        } finally {
            if(sqlSession != null) {

                // 关闭会话
                sqlSession.close();
            }
        }




    }

}

在这里插入图片描述

9. 总结:

  1. MyBatis 本质上就是对JDBC的封装,通过MyBatis完成CRUD。MyBatis 在三层架构中负责持久层,属于持久层框架。

  2. MyBatis 的包目录,路径是 ibatis 。不是 mybatis 。这一点需要注意清楚明白。

  3. mybatis 核心配置文件的名字,不一定是:mybatis-config.xml 。mybatis 核心配置文件存放的路径,也不一定是类的根路径,可以放到其他的位置,但是为了项目的移植性。健壮性,最好将这个配置文件放到类路径下面。

  4. MyBatis 的SQL 映射文件XxxMapper.xml 和MyBatis 的核心配置文件, mybatis-config.xml 都尽量放到类(resources) 根路径下 ,为了项目的移植性。健壮性,最好将这个配置文件放到类路径下面。

  5. 小技巧:以后凡是遇到 resource 这个单词,大部分情况下,这种加载资源的方式就是从(resource)类路径下开始检索加载的。

    例如: 下面三种获取 IO流文件的,检索方式都是从类路径下开始的。

    InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
    InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatis-config.xml");
    InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("mybatis-config.xml");  // 使用类加载器
    
  6. 在mybatis 中提供了两种事务管理机制

    1. 第一种 JDBC事务管理器

      MyBatis 框架自己管理事务,自己采用原生的JDBC 代码去管理事务

      > conn.setAutoCommit(false);开启事务,false 是默认的,可以不用写
      > ...业务处理...
      > conn.commit(); 手动提交事务
      

      使用JDBC事务管理器的话,底层创建的事务管理器对象,jdbcTransaction对象。

      在 JDBC事务管理器 下,SqlSession sqlSession = sqlSessionFactory.openSession( 不填,或者 false); 表示开启事务了(需要自己手动提交,sqlSession.commit()😉,填 true 表示关闭了事务,自动就会提交了

    2. 第二种 MANAGED 是事务管理器

    在 mybatis 不再负责事务的管理了,事务管理交给其他容器来负责,例如:Spring 。

    如果对于我们当前的单纯的只有 MyBatis 的情况下,如果配置为:MANAGED ,那么事务这块是没人管的,没有人管理事务标识,事务压根没有开启,后面我们可以配合使用Spring 进行事务上的管理。

  7. 引入日志框架的目的:是为了看清楚MyBatis执行的具体的 SQL语句,以及赋值内容。

    启动MyBatis 自带的标准日志组件,只需要在mybatis-config.xml MyBatis 的核心配置文件中添加配置文件

    <settings>
      <setting name="logImpl" value="STDOUT_LOGGING" />
    </settings>
    

    setting 这个标签在编写的时候要注意,它必须在 environments 标签之前(不然会报错的),注意顺序,当然,不需要记忆这个顺序。

  8. 引入 logback 日志框架。导入的依赖

<!--        引入 logback的依赖,这个日志框架实现了slf4j 规范-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.11</version>
        </dependency>

如logback所必须的 xml 配置文件**

注意:这个配置文件的名字必须叫做:logback.xml 或者 logback-test.xml 不能是其他的名字
并且这个配置文件必须放到类的根路径下,不能是其他位置。

10. 最后:

“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”

在这里插入图片描述

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

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

相关文章

Oracle递归查询笔记

目录 一、创建表结构和插入数据 二、查询所有子节点 三、查询所有父节点 四、查询指定节点的根节点 五、查询指定节点的递归路径 六、递归子类 七、递归父类 一、创建表结构和插入数据 CREATE TABLE "REGION" ( "ID" VARCHAR2(36) DEFAULT SYS_GUI…

jdk17安装教程详细(jdk17安装超详细图文)

2021年9月14日JDK17 发布&#xff0c;其中不仅包含很多新语言功能&#xff0c;而且与旧版 JDK 相比&#xff0c;性能提升也非常明显。与之前 LTS 版本的 JDK 8 和 JDK 11 相比&#xff0c;JDK17 的性能提升尤为明显&#xff0c;本文将教你如何安装 相比于JDK1.8&#xff0c;JD…

信号:MSK调制和GMSK调制

目录 一、MSK信号 1. MSK信号的第k个码元 2.MSK信号的频率间隔 3.MSK信号的相位连续性 3.1 相位路径 3.2初始相位ψk 4.MSK信号的产生 原理框图 5.MSK信号的频谱图 二、高斯最小频移键控(GMSK) 1.频率响应 2.GMSK调制产生方式 2.1 高斯滤波器法 2.2 正交调制器法…

《MySQL怎样运行的》—InnoDB数据页结构

在上一篇文章中我们讲了&#xff0c;InnoDB的数据页是InnoDB管理存储空间的基本单位&#xff0c;一个页的大小基本为16kb 那你有没有疑问&#xff0c;就是说这个InnoDB的数据页的结构是什么样的&#xff0c;还有他这些结构分别有那些功能~接下来我们一一讲解 数据页的总览结构…

内部类知识点

什么是内部类&#xff1f; 内部类何时出现&#xff1f;B类是A类的一部分&#xff0c;且B单独存在无意义 内部类分类 成员内部类&#xff1a; 当内部类被private修饰后&#xff0c;不能用方法2 调用外部类成员变量 内部类里面有隐藏的outer this来记录 静态内部类 创建对象&…

路由引入实验(华为)

思科设备参考&#xff1a;路由引入实验&#xff08;思科&#xff09; 技术简介 路由引入技术在网络通信中起着重要的作用&#xff0c;能够实现不同路由协议之间的路由传递&#xff0c;并在路由引入时部署路由控制&#xff0c;实现路径或策略的控制 实验目的 不同的路由协议之…

用Intellij实现web登录页面时,servlet已经配置好了,但是还是报404

今天看到一个404问题&#xff1a; 用Intellij实现web登录页面时&#xff0c;代码如下图所示。点击运行后会跳转到浏览器&#xff0c;但是输入/login时&#xff0c;浏览器显示404&#xff0c;且无法在控制面板上打印内容&#xff1b;输入/index时&#xff0c;也无法在浏览器上显…

html+css 驾考首页设计

效果 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>17sucai - A Pen by Mark Boots</title><!-- <link rel"stylesheet" href"./style.css"> --></head>…

【源码分享】简单的404 HTML页面示例,该页面在加载时会等待2秒钟,然后自动重定向到首页

展示效果 源码 html <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><title>404 页面未找到</title><meta http-equiv"refresh" content"2;url/"> <!-- 设置2秒后跳转到首…

[安洵杯 2019]crackMe

直接就退出程序了 找到关键函数了&#xff0c;好像用到了 hook 还有一个 嘿嘿&#xff0c;看着就是像 base64 只是 补‘’改成了‘ &#xff01; ’ 交叉引用啊&#xff0c;翻到一个应该是最后比较函数 1UTAOIkpyOSWGv/mOYFY4R!! 那一坨对 a1数组的操作没看懂 先总结一下就是…

Golang的基本使用

目录 变量的声明 Golang常用容器 defer 有趣的多态 结构体标签和reflect 反射 Golang最强的协程 channel go可能造成的内存泄露 变量的声明 方法 1:有类型,有var,不赋值 在Golang中默认值为0 方法 2:无类型,有var,赋值 方法 3:无类型,无var,赋值 多变量声明 多变…

C语言 数组——查找算法的函数实现

目录 线性查找&#xff08;Linear Search&#xff09; 线性查找的性能 猜数游戏 二分查找&#xff08;Binary Search&#xff09; 并非吹毛求疵&#xff0c;鸡蛋里挑骨头 二分查找的性能 线性查找&#xff08;Linear Search&#xff09; 不 要求数据表是已排好序的  …

AI巨头争相与Reddit合作:为何一个古老的论坛成为AI训练的“宝藏”?

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

这种电脑原来这么耗电……震惊了粉丝小姐姐

前言 在今年1月份的时候&#xff0c;一位来自重庆的小姐姐加了小白&#xff0c;咨询电脑的问题&#xff1a; 哦豁&#xff0c;这个电脑看着确实闪闪发光&#xff0c;是真的很漂亮&#xff5e;&#xff08;嗯&#xff0c;小姐姐也很漂亮&#xff09; 电脑无法开机&#xff0c;按…

华为云发布ServiceStage:内置优秀业界实践「云应用管理和运维」模板

迅猛发展的业务让企业IT系统架构愈加复杂&#xff0c;为满足业务快速迭代的需求&#xff0c;重点企业完成从传统单体应用架构到分布式微服务架构的升级。微服务架构虽可提升研发效率&#xff0c;但数量庞大的微服务实例间错综复杂的依赖关系无疑增加了部署运维难度。 同时&…

Go源码--sync库(1)sync.Once和

简介 这篇主要介绍 sync.Once、sync.WaitGroup和sync.Mutex sync.Once once 顾名思义 只执行一次 废话不说 我们看源码 英文介绍直接略过了 感兴趣的建议读一读 获益匪浅 其结构体如下 Once 是一个严格只执行一次的object type Once struct {// 建议看下源码的注解&#xf…

汇编语言(STC89C52)

指令是计算机计算CPU根据人的意图来执行某种操作的命令。一台计算机所执行的全部指令的集合&#xff0c;称为这个CPU的指令系统。而想要使计算机按照人们的要求完成一项工作&#xff0c;就必须让CPU按顺序执行预设的操作&#xff0c;即逐条执行人们编写的指令。这种按照人民要求…

暴雨信息液冷计算解决方案亮相CCIG 2024

5月24日&#xff0c;2024中国图象图形大会&#xff08;CCIG&#xff09;在陕西西安正式开幕。作为涵盖图像图形各专业领域的综合性的全国性学术会议&#xff0c;CCIG面向开放创新、交叉融合的发展趋势&#xff0c;为图像图形相关领域的专家学者和产业界的同仁&#xff0c;搭建了…

本是梦中人,常作花下客。心中自往来,知我有几个。

我们总是喜欢拿“顺其自然”来敷衍人生道路上的荆棘坎坷&#xff0c;却很少承认&#xff0c;真正的顺其自然&#xff0c; 其实是竭尽所能之后的不强求&#xff0c; 而非两手一摊的不作为。 一花凋零荒芜不了整个春天&#xff0c; 一次挫折也荒废不了整个人生。 多年后&#x…