Java知识点大纲
文章目录
- 第一阶段:JavaSE
- 1、面向对象编程(基础)
- 1)面向过程和面向对象区别
- 2)类和对象的概述
- 3)类的属性和方法
- 4)创建对象内存分析
- 5)构造方法(Construtor)及其重载
- 6)对象类型的参数传递
- 7)this关键字详解
- 8)static关键字详解
- 9)局部代码块、构造代码块和静态代码块
- 10)package和import详解
- 11)JavaDoc生成API文档
- 12)递归
- 第五阶段:高级框架
- 1、mybatis
- 1)MyBatis概述
- 2)MyBatis入门配置
- 3)基本的CRUD操作
- 4)核心配置文件详解
- 5)Mapper.xml基础详解
- 6)模糊查询
- 7)分页的实现及插件PageHelper的使用
- 8)动态sql+sql片段的使用
- 9)一对多、多对一的关系处理
- 10)注解的使用
- 11)一级缓存和二级缓存说明及使用
- 12)Mybatis Log4j的使用
- 13)Mybatis slf4j的使用
- 14)Mybatis动态代理的使用
- 15)MyBatis Generator介绍
- 16)generatorConfig.xml讲解
- 17)MyBatis Generator序列化配置
- 18)MyBatis Generator生成toString()
- 19)MyBatis Generator的数据库设置
- 20)MyBatis Generator包设置
- 21)MyBatis Generator的表设置
- 22)基于MyBatis Generator的数据查询
- 23)基于MyBatis Generator的数据添加
- 24)基于MyBatis Generator的数据更新
- 25)基于MyBatis Generator的数据删除
第一阶段:JavaSE
1、面向对象编程(基础)
1)面向过程和面向对象区别
一、思想理念的不同
面向对象编程(Object-Oriented Programming,OOP)注重将问题分解为一组相互关联的对象,这些对象具有自己的属性和行为。OOP的核心思想是通过模拟真实世界的实体,以对象为中心进行设计和开发。对象之间通过消息传递进行通信和交互,实现系统功能的实现。
相比之下,面向过程编程(Procedural Programming,P)则更加关注问题的步骤和流程。它将问题分解为一系列的步骤或者函数,并按照特定的顺序执行。P过程性编程以算法为中心,强调问题的解决过程,将数据和功能分离,逐个处理步骤来实现程序的功能。
二、抽象程度的不同
面向对象编程通过封装、继承和多态等机制,可以将现实世界的复杂问题抽象成更简单、更易于理解的模型。它强调对象的概念,将数据和操作数据的方法封装在一起,以便更好地组织和管理代码。通过定义类和对象,OOP可以提供更高层次的抽象,使得代码的重用性和可维护性更强。
相反,面向过程编程的抽象程度较低。它将问题分解为一系列的步骤或函数,每个步骤都是按照特定的逻辑顺序执行的。P过程性编程更加直接和实际,处理问题的方式较为细节化。虽然可以使用函数来组织代码,但对于大型项目来说,代码的可读性和可维护性可能会受到挑战。
三、代码的复用性和可维护性不同
面向对象编程具有良好的代码复用性和可维护性。通过类的继承和多态等特性,可以将通用的行为和属性封装在父类中,子类可以继承和扩展这些特性。这种代码的组织方式使得代码结构清晰,易于理解和修改,提高了开发效率。
相比之下,面向过程编程的代码复用性和可维护性较差。由于函数和数据相分离的特点,代码的重用性较低。当需求发生变化时,可能需要修改多个函数,这会导致代码的可维护性下降。
四、团队协作和开发效率不同
面向对象编程在大型项目中具有良好的团队协作性。通过对象的封装和信息隐藏,不同的团队成员可以独立开发和测试各自的模块,减少了彼此之间的依赖。同时,OOP的抽象和封装特性可以提高代码的可读性和可维护性,进而提高开发效率。
相反,面向过程编程的团队协作性相对较差。由于函数和数据相分离的特点,不同的开发人员之间可能需要更多的沟通和协调,以确保代码的正确性和一致性。在大型项目中,代码的维护和扩展也相对困难,开发效率较低。
五、灵活性和可扩展性不同
面向对象编程具有较高的灵活性和可扩展性。由于对象之间的关系是通过消息传递实现的,可以在运行时动态地创建、销毁和修改对象。这种动态性使得系统能够更好地适应变化的需求,添加新功能或修改现有功能更加方便。
相对而言,面向过程编程的灵活性和可扩展性较低。由于代码的组织方式是基于函数和步骤的顺序执行,当需要添加新功能时,可能需要修改多个函数或步骤,可能会引发连锁反应,增加了代码的复杂性和风险。
六、封装和信息隐藏不同
面向对象编程强调封装和信息隐藏的概念。通过将数据和操作数据的方法封装在对象内部,对外部提供公共接口进行访问,实现了数据的隐藏和保护。这种封装性可以有效地防止数据被错误地修改,增强了代码的安全性和可靠性。
而面向过程编程的封装性较差,数据和功能之间的关系比较松散。数据通常被多个函数共享,可能会导致数据被错误地修改或误用,增加了代码出错的风险。
七、编程范式的应用领域不同
面向对象编程通常适用于大型软件系统的开发,例如企业级应用、图形界面程序等。OOP的思想和方法可以更好地应对复杂性和变化性,提供了更高层次的抽象和组织方式,便于团队协作和可维护性。
面向过程编程则更适用于较小规模、简单和直接的任务。例如编写一些简单的脚本、数据处理程序等。由于P过程性编程更注重问题的解决过程,适合于一步一步的逻辑操作。
综合考虑以上几个方面的区别,选择适合具体需求的编程范式是开发人员需要权衡的因素。面向对象编程强调代码的组织和抽象能力,适合大型项目和复杂系统的开发;而面向过程编程则更简单直接,适用于小规模任务和简单应用的开发。
延伸阅读1:面向对象程序设计的基本特征
面向对象程序设计(Object-Oriented Programming,OOP)具有以下基本特征:
一、封装(Encapsulation)
封装是指将数据和对数据的操作封装在一个单元内部,形成一个对象。对象对外部提供公共接口,隐藏了内部实现细节,通过接口访问对象的属性和方法。封装提供了信息隐藏和保护数据的能力,同时也提高了代码的可读性和可维护性。
二、继承(Inheritance)
继承是一种机制,允许一个对象(子类)继承另一个对象(父类)的属性和方法。通过继承,子类可以复用父类的代码,扩展或修改父类的功能。继承实现了代码的重用性和层次性,提供了面向对象编程的灵活性和可扩展性。
三、多态(Polymorphism)
多态是指同一个方法可以在不同的对象上产生不同的行为。通过多态,可以在父类引用的变量中存储子类对象,然后根据实际的对象类型来调用相应的方法。多态提供了代码的灵活性和可扩展性,能够处理不同类型的对象,提高了代码的可读性和可维护性。
四、抽象(Abstraction)
抽象是指从具体的事物中抽取出共同的特征和行为,形成一个抽象的类或接口。抽象类定义了一组相关的对象的通用特征,接口定义了一组操作的规范。抽象提供了问题领域的概念模型,使得程序设计更加高层次化和模块化。
这些基本特征共同构成了面向对象程序设计的基础。通过封装、继承、多态和抽象,面向对象编程可以提供更高层次的抽象和封装能力,实现代码的重用性、可维护性、可扩展性和灵活性。这种编程范式适用于大型软件系统的开发,能够提高开发效率和代码质量。
2)类和对象的概述
3)类的属性和方法
4)创建对象内存分析
5)构造方法(Construtor)及其重载
6)对象类型的参数传递
7)this关键字详解
8)static关键字详解
1、深度总结
引用一位网友的话,说的非常好,如果别人问你static的作用;如果你说静态修饰 类的属性 和 类的方法 别人认为你是合格的;如果是说 可以构成 静态代码块,那别人认为你还可以; 如果你说可以构成 静态内部类, 那别人认为你不错;如果你说了静态导包,那别人认为你很OK;
那我们就先在这几方面一一对static进行总结;然后说一些模糊的地方,以及一些面试中容易问道的地方;
1)static方法
static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。
但是要注意的是,虽然在静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成员方法中是可以访问静态成员方法/变量的。举个简单的例子:
在上面的代码中,由于print2方法是独立于对象存在的,可以直接用过类名调用。假如说可以在静态方法中访问非静态方法/变量的话,那么如果在main方法中有下面一条语句:
MyObject.print2();
此时对象都没有,str2根本就不存在,所以就会产生矛盾了。同样对于方法也是一样,由于你无法预知在print1方法中是否访问了非静态成员变量,所以也禁止在静态成员方法中访问非静态成员方法。
而对于非静态成员方法,它访问静态成员方法/变量显然是毫无限制的。
因此,如果说想在不创建对象的情况下调用某个方法,就可以将这个方法设置为static。我们最常见的static方法就是main方法,至于为什么main方法必须是static的,现在就很清楚了。因为程序在执行main方法的时候没有创建任何对象,因此只有通过类名来访问。
2)static变量
static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本【存放在方法区】,它当且仅当在类初次加载时会被初始化【加final和不加final的static变量初始化的位置不一样】。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
static成员变量的初始化顺序按照定义的顺序进行初始化。
3)static代码块
static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次【根据class加载原理 每个类加载一次 使用双亲委托加载】。
初始化的顺序 静态代码块 > 构造代码块 > 构造函数
为什么说static块可以用来优化程序性能,是因为它的特性:只会在类加载的时候执行一次。下面看个例子:
isBornBoomer是用来这个人是否是1946-1964年出生的,而每次isBornBoomer被调用的时候,都会生成startDate和birthDate两个对象,造成了空间浪费,如果改成这样效率会更好,其实就是利用了静态代码块在内存中值加载一次的机制:
因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。
4)静态内部类
这个地方不单独写静态内部类,通过和普通的内部类对比来加深对静态内部类的理解:
为何要用内部类?
-
内部类一般只为其外部类使用;【供外部类使用说的很好 举例 hashmap集合中 有一个内部类 Entry 就是 转为为 hashmap 存储来使用】
-
内部类提供了某种进入外部类的窗户,内部类存在外部类的引用,所以内部类可以直接访问外部类的属性;
-
也是最吸引人的原因,每个内部类都能独立地继承一个接口,而无论外部类是否已经继承了某个接口。因此,内部类使多重继承的解决方案变得更加完整。
定义在一个类内部的类叫内部类,包含内部类的类称为外部类。内部类可以声明public、protected、private等访问限制,可以声明 为abstract的供其他内部类或外部类继承与扩展,或者声明为static、final的,也可以实现特定的接口。
外部类按常规的类访问方式(以对象的方式)使用内部 类,唯一的差别是外部类可以访问内部类的所有方法与属性,包括私有方法与属性,外部类访问内部类,需要创建对象访问;有一点需要注意,内部类不能访问外部类所在的局部变量,只能访问final修饰的局部变量。
举例: 在方法中 定义内部类 然后内部类 调用方法的的入参 则 入参必须是 final 修饰
在方法内定义内部类时,如果内部类调用了方法中的变量,那么该变量必须申明为final类型,百思不得其解,后来想到应该是生命周期的原因,因为方法内定义的变量是局部变量,离开该方法,变量就失去了作用,也就会自动被消除,而内部类却不会离开它所在方法就失去作用,它有更广的生命周期,下面通过一个实例加以说明:
(1)创建实例
OutClass.InnerClass obj = outClassInstance.new InnerClass(); //注意是外部类实例.new,内部类
AAA.StaticInner in = new AAA.StaticInner();//注意是外部类本身,静态内部类
(2)内部类中的this
内部类中的this与其他类一样是指的本身。创建内部类对象时,它会与创造它的外围对象有了某种联系,于是能访问外围类的所有成员,不需任何特殊条件,可理解为内部类链接到外部类。 用外部类创建内部类对象时,此内部类对象会秘密的捕获一个指向外部类的引用,于是,可以通过这个引用来访问外围类的成员。
(3)外部类访问内部类
内部类类似外部类的属性,因此访问内部类对象时总是需要一个创建好的外部类对象。外部类对象通过‘外部类名.this.xxx'的形式访问内部类的属性与方法。如:
System.out.println("Print in inner Outer.index=" + pouter.this.index);
System.out.println("Print in inner Inner.index=" + this.index);
(4)内部类向上转型
内部类也可以和普通类一样拥有向上转型的特性。将内部类向上转型为基类型,尤其是接口时,内部类就有了用武之地。如果内部类是private的,只可以被它的外部类问,从而完全隐藏实现的细节。
(5)方法内的类
方法内创建的类(注意方法中也能定义类),不能加访问修饰符。另外,方法内部的类也不是在调用方法时才会创建的,它们一样也被事先编译了。
(6)静态内部类
定义静态内部类:在定义内部类的时候,可以在其前面加上一个权限修饰符static。此时这个内部类就变为了静态内部类。
通常称为嵌套类,当内部类是static时,意味着:
[1]要创建嵌套类的对象,并不需要其外围类的对象;
[2]不能从嵌套类的对象中访问非静态的外围类对象(不能够从静态内部类的对象中访问外部类的非静态成员);
嵌 套类与普通的内部类还有一个区别:普通内部类的字段与方法,只能放在类的外部层次上,所以普通的内部类不能有static数据和static字段, 也不能包含嵌套类。但是在嵌套类里可以包含所有这些东西。也就是说,在非静态内部类中不可以声明静态成员,只有将某个内部类修饰为静态类,然后才能够在这 个类中定义静态的成员变量与成员方法。
另外,在创建静态内部类时不需要将静态内部类的实例绑定在外部类的实例上。普通非静态内部类的 对象是依附在外部类对象之中的,要在一个外部类中定义一个静态的内部类,不需要利用关键字new来创建内部类的实例。静态类和方法只属于类本身,并不属于 该类的对象,更不属于其他外部类的对象。
(7)内部类标识符
每个类会产生一个.class文件,文件名即为类名。同样,内部类也会产生这么一个.class文件,但是它的名称却不是内部类的类名,而是有着严格的限制:外围类的名字,加上$,再加上内部类名字。
代码具体:
public class OutClassTest {static int a;int b;public static void test() {System.out.println("outer class static function");}public static void main(String[] args) {// new一个外部类OutClassTest oc1 = new OutClassTest();// 通过外部类的对象new一个非静态的内部类OutClassTest.InnerClass no_static_inner = oc1.new InnerClass();// 调用非静态内部类的方法System.out.println(no_static_inner.getKey());// 调用静态内部类的静态变量System.out.println(OutClassTest.InnerStaticClass.static_value);// 不依赖于外部类实例,直接实例化内部静态类OutClassTest.InnerStaticClass inner = new OutClassTest.InnerStaticClass();// 调用静态内部类的非静态方法System.out.println(inner.getValue());// 调用内部静态类的静态方法System.out.println(OutClassTest.InnerStaticClass.getMessage());}private class InnerClass {// 只有在静态内部类中才能够声明或定义静态成员// private static String tt = "0";private int flag = 0;public InnerClass() {// 三.非静态内部类的非静态成员可以访问外部类的非静态变量和静态变量System.out.println("InnerClass create a:" + a);System.out.println("InnerClass create b:" + b);System.out.println("InnerClass create flag:" + flag);//System.out.println("InnerClass call outer static function");// 调用外部类的静态方法test();}public String getKey() {return "no-static-inner";}}private static class InnerStaticClass {// 静态内部类可以有静态成员,而非静态内部类则不能有静态成员。private static String static_value = "0";private int flag = 0;public InnerStaticClass() {System.out.println("InnerClass create a:" + a);// 静态内部类不能够访问外部类的非静态成员// System.out.println("InnerClass create b:" + b);System.out.println("InnerStaticClass flag is " + flag);System.out.println("InnerStaticClass tt is " + static_value);}public int getValue() {// 静态内部类访问外部类的静态方法test();return 1;}public static String getMessage() {return "static-inner";}}public OutClassTest() {// new一个非静态的内部类InnerClass ic = new InnerClass();System.out.println("OuterClass create");}}
4)静态导包
静态导包就是java包的静态导入,用import static代替import静态导入包是JDK1.5中的新特性。
一般我们导入一个类都用 import com……ClassName;而静态导入是这样:import static com……ClassName.;这里的多了个static,还有就是类名ClassName后面多了个. ,意思是导入这个类里的静态方法。当然,也可以只导入某个静态方法,只要把 .* 换成静态方法名就行了。然后在这个类中,就可以直接用方法名调用静态方法,而不必用ClassName.方法名 的方式来调用。
好处:这种方法的好处就是可以简化一些操作,例如打印操作System.out.println(…);就可以将其写入一个静态方法print(…),在使用时直接print(…)就可以了。但是这种方法建议在有很多重复调用的时候使用,如果仅有一到两次调用,不如直接写来的方便
example:
在Java 5中,import语句得到了增强,以便提供甚至更加强大的减少击键次数功能,虽然一些人争议说这是以可读性为代价的。这种新的特性成为静态导入。当你想使用static成员时,可以使用静态导入(在API中的类和你自己的类上,都可以使用该特性)。下面是静态导入前后的代码实例:
在静态导入之前:
public class TestStatic {public static void main(String[] args) {System.out.println(Integer.MAX_VALUE);System.out.println(Integer.toHexString(42));}}
在静态导入之后:
import static java.lang.System.out;import static java.lang.Integer.*;public class TestStaticImport {public static void main(String[] args) {out.println(MAX_VALUE);out.println(toHexString(42));}}
让我们看一下使用静态导入特性的代码中将发生什么:
1、虽然该特性通常称为“静态导入”,但语法必须是import static,后面跟你想导入的static成员的完全限定名称,或者通配符。在本例中,我们在System类的out对象上进行静态导入。
2、在本例中,我们可能想使用java.lang.Integer类的几个static成员。该静态导入语句使用通配符来表达“我想在此类中的所有静态成员上进行静态导入”。
3、现在我们终于看到静态导入特性的好处!我们不必在System.out.println中键入System。太好了!另外,我们不必在Integer.MAX_VALUE中键入Integer。因此,在这行代码中,我们能够将快捷方式用于静态方法和一个常量。
4、最后,我们进行更多的快捷操作,这次针对Integer类的方法。
关于该特性,我们已经有点儿讽刺意味儿了,但不仅我们是这样的。我们不认为节省少量的击键次数会让代码
难于阅读一点,但许多开发人员要求将它添加到语言中。
下面是使用静态导入的几条原则:
你必须说import static, 不能说static import。
提防含糊不清的命名static成员。例如,如果你对Integer类和Long类执行了静态导入,引用MAX_VALUE将导致一个编译器错误,因为Integer和Long都有一个MAX_VALUE常量,并且Java不会知道你在引用哪个MAX_VALUE。
你可以在static对象引用、常量(记住,它们是static 或final)和static方法上进行静态导入。
二.static关键字的误区
1.static关键字会改变类中成员的访问权限吗?
有些初学的朋友会将java中的static与C/C++中的static关键字的功能混淆了。在这里只需要记住一点:与C/C++中的static不同,Java中的static关键字不会影响到变量或者方法的作用域。在Java中能够影响到访问权限的只有private、public、protected(包括包访问权限)这几个关键字。看下面的例子就明白了:
2.能通过this访问静态成员变量吗?
虽然对于静态方法来说没有this,那么在非静态方法中能够通过this访问静态成员变量吗?先看下面的一个例子,这段代码输出的结果是什么?
public class Main { static int value = 33;public static void main(String[] args) throws Exception{new Main().printValue();}private void printValue(){int value = 3;System.out.println(this.value);}
输出
这里面主要考察队this和static的理解。this代表什么?this代表当前对象,那么通过new Main()来调用printValue的话,当前对象就是通过new Main()生成的对象。而static变量是被对象所享有的,因此在printValue中的this.value的值毫无疑问是33。在printValue方法内部的value是局部变量,根本不可能与this关联,所以输出结果是33。在这里永远要记住一点:静态成员变量虽然独立于对象,但是不代表不可以通过对象去访问,所有的静态方法和静态变量都可以通过对象访问(只要访问权限足够)。
3.static能作用于局部变量么?
在C/C++中static是可以作用域局部变量的,但是在Java中切记:static是不允许用来修饰局部变量。不要问为什么,这是Java语法的规定。
三.常见的笔试面试题
下面列举一些面试笔试中经常遇到的关于static关键字的题目,仅供参考,如有补充欢迎下方留言。
1.下面这段代码的输出结果是什么?
public class Test extends Base{static{System.out.println("test static");}public Test(){System.out.println("test constructor");}public static void main(String[] args) {new Test();}
}class Base{static{System.out.println("base static");}public Base(){System.out.println("base constructor");}
}
至于为什么是这个结果,我们先不讨论,先来想一下这段代码具体的执行过程,在执行开始,先要寻找到main方法,因为main方法是程序的入口,但是在执行main方法之前,必须先加载Test类,而在加载Test类的时候发现Test类继承自Base类,因此会转去先加载Base类,在加载Base类的时候,发现有static块,便执行了static块。在Base类加载完成之后,便继续加载Test类,然后发现Test类中也有static块,便执行static块。在加载完所需的类之后,便开始执行main方法。在main方法中执行new Test()的时候会先调用父类的构造器,然后再调用自身的构造器。因此,便出现了上面的输出结果。
2.这段代码的输出结果是什么?
public class Test {Person person = new Person("Test");static{System.out.println("test static");}public Test() {System.out.println("test constructor");}public static void main(String[] args) {new MyClass();}
}class Person{static{System.out.println("person static");}public Person(String str) {System.out.println("person "+str);}
}class MyClass extends Test {Person person = new Person("MyClass");static{System.out.println("myclass static");}public MyClass() {System.out.println("myclass constructor");}
}
类似地,我们还是来想一下这段代码的具体执行过程。首先加载Test类,因此会执行Test类中的static块。接着执行new MyClass(),而MyClass类还没有被加载,因此需要加载MyClass类。在加载MyClass类的时候,发现MyClass类继承自Test类,但是由于Test类已经被加载了,所以只需要加载MyClass类,那么就会执行MyClass类的中的static块。在加载完之后,就通过构造器来生成对象。而在生成对象的时候,必须先初始化父类的成员变量,因此会执行Test中的Person person = new Person(),而Person类还没有被加载过,因此会先加载Person类并执行Person类中的static块,接着执行父类的构造器,完成了父类的初始化,然后就来初始化自身了,因此会接着执行MyClass中的Person person = new Person(),最后执行MyClass的构造器。
3.这段代码的输出结果是什么?
public class Test {static{System.out.println("test static 1");}public static void main(String[] args) {}static{System.out.println("test static 2");}
}
9)局部代码块、构造代码块和静态代码块
10)package和import详解
11)JavaDoc生成API文档
12)递归
第五阶段:高级框架
1、mybatis
1)MyBatis概述
2)MyBatis入门配置
3)基本的CRUD操作
4)核心配置文件详解
配置案例一:单个mybatis配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"> <!-- 其中 configuration 说明该 XML 文件的根,xxx.dtd 文件是 XML 对应的规范,用来说明该 XML 文件可以使用那些标签 --><configuration><settings><setting name="logImpl" value="STDOUT_LOGGING"/> <!-- 日志设置为 MyBatis 提供的标准日志 --></settings><!-- default 表示默认使用的环境 --><!-- 默认环境是什么?当使用 mybatis 创建 SqlSessionFactory 对象的时候,没有指定环境的话,默认使用那个环境 --><environments default="development"><!-- 一般一个数据库会对应一个SqlSessionFactory对象。--><!-- 一个环境 environment 会对应一个 SqlSessionFactory 对象--><environment id="development"><transactionManager type="JDBC"/> <!-- 事务管理设置为 JDBC 默认开启事务,需要手动提交 --><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/使用的数据库名"/><property name="username" value="用户名"/><property name="password" value="用户名对应的密码"/></dataSource></environment><!-- 这是mybatis的另一个环境,也就是链接的数据库是另一个数据库mybatis--><environment id="test"><transactionManager type="JDBC"/> <!-- 事务管理设置为 JDBC 默认开启事务,需要手动提交 --><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/使用的数据库名"/><property name="username" value="用户名"/><property name="password" value="用户名对应的密码"/></dataSource></environment></environments><mappers><!--sql映射⽂件创建好之后,需要将该⽂件路径配置到这⾥--><mapper resource="articleMapper.xml"/></mappers></configuration>
1)如何创建对应环境的 SqlSessionFactory对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();//这种方式创建的是默认环境的sqlSessionFactory
SqlSessionFactory sqlSessionFactory1 = builder.build(Resources.getResourceAsStream("mybatis-config.xml"));//这种方式创建的是指定环境的sqlSessionFactory
SqlSessionFactory sqlSessionFactory2 = builder.build(Resources.getResourceAsStream("mybatis-config.xml"), "test");
2.transactionManager标签详解
- 这个标签是用来配置事务管理器的,用来指定具体采用什么方式来管理事务的。
- 关于这个标签的详细知识可以参考我的博客 ===> MyBatis概述与MyBatis入门程序 中的 MyBatis事务管理深度剖析部分。
3.dataSource标签详解
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"> <!-- 其中 configuration 说明该 XML 文件的根,xxx.dtd 文件是 XML 对应的规范,用来说明该 XML 文件可以使用那些标签 --><configuration><settings><setting name="logImpl" value="STDOUT_LOGGING"/> <!-- 日志设置为 MyBatis 提供的标准日志 --></settings><!-- default 表示默认使用的环境 --><!-- 默认环境是什么?当使用 mybatis 创建 SqlSessionFactory 对象的时候,没有指定环境的话,默认使用那个环境 --><environments default="development"><!-- 一般一个数据库会对应一个SqlSessionFactory对象。--><!-- 一个环境 environment 会对应一个 SqlSessionFactory 对象--><environment id="development"><transactionManager type="JDBC"/> <!-- 事务管理设置为 JDBC 默认开启事务,需要手动提交 --><!--1.dataSource 被称为数据源2.dataSource 的作用是:为程序提供 Connection 对象。(但凡是给程序提供 Connection 对象的,都叫做数据源)3.数据源实际上是一套规范。JDK 中有这套规范:javax.sql.DataSource(这个数据源的规范,这套接口实际上是 JDK 规定的)4.我们自己也可以编写数据源组件,只要实现 Javax.sql.DataSource 接口就行了。实现接口当中的所有方法。这样就有了自己的数据怨怒。(数据库连接池是提供连接对象的,所有数据库连接池就是一个数据源)5.常见的连接池有:阿里巴巴的德鲁伊连接池:druidc3p0dbcp...6.type 属性用来指定数据源的类型,就是指定具体使用什么方式来获取 Connection 对象。type 属性有三个值,必须是三选一type= "[UNPOOLED | POOLED | JNDI]"UNPOOLED: 不使用数据库连接池技术。每一次请求过来之后,都是创建新的 Connection 对象。POOLED: 使用 mybatis 自己实现的数据库连接池。JNDI: 集成第三方的数据库连接池。JNDI 是一套规范。大部分 Web 容器都实现了 JNDI 规范。例如:Tomcat、Jetty、WebLogic、WebSphere.JNDI:是Java命名目录接口。--><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/springboot-blog"/><property name="username" value="root"/><property name="password" value="GDB20031104!"/></dataSource></environment><!-- 这是mybatis的另一个环境,也就是链接的数据库是另一个数据库mybatis--><environment id="test"><transactionManager type="JDBC"/> <!-- 事务管理设置为 JDBC 默认开启事务,需要手动提交 --><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/springboot-blog"/><property name="username" value="root"/><property name="password" value="GDB20031104!"/></dataSource></environment></environments><mappers><!--sql映射⽂件创建好之后,需要将该⽂件路径配置到这⾥--><mapper resource="articleMapper.xml"/></mappers></configuration>
注意:关于 type 属性的值不同,则每个属性可以使用的子标签不同,大家可以参考官方文档。 ===> mybatis中文网
(1)UNPOOLED
(2)POOLED
- 提醒:正常使用连接池的话,池中有很多参数是需要设置的。设置好参数,可以让连接池发挥的更好。事半功倍的效果。
- 具体连接池当中的参数如何配置呢?需要反复的根据当前业务情况进行测试。
二、properties标签 - 这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。
1.property标签
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><properties><property name="jdbc.driver" value="com.mysql.cj.jdbc.Driver"/><property name="jdbc.url" value="jdbc:mysql://localhost:3306/springboot-blog"/></properties><settings><setting name="logImpl" value="STDOUT_LOGGING"/></settings><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="root"/><property name="password" value="GDB20031104!"/></dataSource></environment></environments><mappers><!--sql映射⽂件创建好之后,需要将该⽂件路径配置到这⾥--><mapper resource="articleMapper.xml"/></mappers>
</configuration>
2.properties 属性配置文件
(1)xxx.properties属性配置文件
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springboot-blog
jdbc.username=root
jdbc.password=GDB20031104!
(2)mybatis-config.xml 配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><properties resource="jdbc.properties"> // 从根路径下引入属性配置文件</properties><settings><setting name="logImpl" value="STDOUT_LOGGING"/></settings><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment></environments><mappers><mapper resource="articleMapper.xml"/></mappers>
</configuration>
(3)配置文件的优先级
如果一个属性在不只一个地方进行了配置,那么,MyBatis 将按照下面的顺序来加载:
首先读取在 properties 元素体内指定的属性。
然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。
最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。
因此,通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的则是 properties 元素中指定的属性。
其中的 url 属性是使用绝对路径的方式来获取属性配置文件的。
配置案例二:整合spring
<?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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"default-lazy-init="true"><!-- 注解注入 --><context:component-scan base-package="com.itumpsub" /><!-- 数据连接事务 --><bean id="subTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="sub-dbcp" /></bean><bean id="reporterTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="reporter-dbcp" /></bean><bean id="omnibusTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="proxool" /></bean><bean id="warehousTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="warehous-dbcp" /></bean><bean id="sqlserverTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="sqlserver-dbcp" /></bean>
<!-- <bean id="sqlserverTransactionManager_zaibei" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="sqlserver-dbcp_zaibei" /></bean> --><!-- define the SqlSessionFactory --><bean id="subSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="sub-dbcp" /><property name="configLocation" value="classpath:/config/itumpsub/ibatis/sub-mybatis-config.xml" /><property name="typeAliasesPackage" value="com.itumpsub.dto.itrm" /> </bean><bean id="reporterSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="reporter-dbcp" /><property name="configLocation" value="classpath:/config/itumpsub/ibatis/reporter-mybatis-config.xml" /><property name="typeAliasesPackage" value="com.itumpsub.dto.reporter" /></bean><bean id="omnibusSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="proxool" /><property name="configLocation" value="classpath:/config/itumpsub/ibatis/omnibus-mybatis-config.xml" /><property name="typeAliasesPackage" value="com.itumpsub.dto.omnibus" /></bean><!-- 性能库sqlsessionFactoryBean--><bean id="warehousSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="warehous-dbcp" /><property name="configLocation" value="classpath:/config/itumpsub/ibatis/warehous-mybatis-config.xml" /><property name="typeAliasesPackage" value="com.itumpsub.dto.warehous" /></bean><!-- sql server sqlsessionFactoryBean--><bean id="sqlserverSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="sqlserver-dbcp" /><property name="configLocation" value="classpath:/config/itumpsub/ibatis/sqlserver-mybatis-config.xml" /><property name="typeAliasesPackage" value="com.itumpsub.dto.sqlserver" /></bean><!-- sql server sqlsessionFactoryBean-->
<!-- <bean id="sqlserverSqlSessionFactory_zaibei" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="sqlserver-dbcp_zaibei" /><property name="configLocation" value="classpath:/config/itumpsub/ibatis/sqlserver-zaibei-mybatis-config.xml" /><property name="typeAliasesPackage" value="com.itumpsub.dto.sqlserver_zaibei" /></bean> --><!-- mybatis接口 --><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.itumpsub.dao.itrm" /><property name="sqlSessionFactory" ref="subSqlSessionFactory" /></bean><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.itumpsub.dao.omnibus" /><property name="sqlSessionFactory" ref="omnibusSqlSessionFactory" /></bean><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.itumpsub.dao.reporter" /><property name="sqlSessionFactory" ref="reporterSqlSessionFactory" /></bean><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.itumpsub.dao.warehous" /><property name="sqlSessionFactory" ref="warehousSqlSessionFactory" /></bean><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.itumpsub.dao.sqlserver" /><property name="sqlSessionFactory" ref="sqlserverSqlSessionFactory" /></bean>
<!-- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.itumpsub.dao.sqlserver_zaibei" /><property name="sqlSessionFactory" ref="sqlserverSqlSessionFactory_zaibei" /></bean> --><!-- 连接事务的注解配置 --><tx:annotation-driven transaction-manager="subTransactionManager" /><tx:annotation-driven transaction-manager="reporterTransactionManager" /><tx:annotation-driven transaction-manager="omnibusTransactionManager" /><tx:annotation-driven transaction-manager="warehousTransactionManager" /><tx:annotation-driven transaction-manager="sqlserverTransactionManager" /><!-- <tx:annotation-driven transaction-manager="sqlserverTransactionManager_zaibei" /> --><!--ITTL Start --><bean id="ITTLTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="ITTL-dbcp" /></bean><bean id="ITTLSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="ITTL-dbcp" /><property name="configLocation" value="classpath:/config/itumpsub/ibatis/ittl_yhzq_db2-mybatis-config.xml" /><property name="typeAliasesPackage" value="com.itumpsub.dto.ittl" /></bean><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.itumpsub.dao.ittl" /><property name="sqlSessionFactory" ref="ITTLSqlSessionFactory" /></bean><tx:annotation-driven transaction-manager="ITTLTransactionManager" /><!--ITTL End --><!-- 数据库连接池 --><import resource="classpath:/config/common/spring-pool.xml" /><import resource="classpath:/config/itumpsub/spring/spring-quartz.xml" /><bean id="ticketWebService" class="com.itumpsub.component.alarm.webservice.client.impl.TicketWebServiceImpl"></bean></beans>
5)Mapper.xml基础详解
6)模糊查询
7)分页的实现及插件PageHelper的使用
8)动态sql+sql片段的使用
9)一对多、多对一的关系处理
10)注解的使用
11)一级缓存和二级缓存说明及使用
12)Mybatis Log4j的使用
13)Mybatis slf4j的使用
14)Mybatis动态代理的使用
15)MyBatis Generator介绍
16)generatorConfig.xml讲解
17)MyBatis Generator序列化配置
18)MyBatis Generator生成toString()
19)MyBatis Generator的数据库设置
20)MyBatis Generator包设置
21)MyBatis Generator的表设置
22)基于MyBatis Generator的数据查询
23)基于MyBatis Generator的数据添加
24)基于MyBatis Generator的数据更新
25)基于MyBatis Generator的数据删除
相关文章:

Java知识点大纲
文章目录 第一阶段:JavaSE1、面向对象编程(基础)1)面向过程和面向对象区别2)类和对象的概述3)类的属性和方法4)创建对象内存分析5)构造方法(Construtor)及其重载6)对象类型的参数传递7)this关键字详解8)static关键字详解9)局部代码块、构造代码块和静态代码块10)pac…...

【Kafka】记录一次Kafka消费者重复消费问题
文章目录 现象业务背景排查过程Push与Pull 现象 用户反馈消费者出现消息积压,并且通过日志看,一直重复消费,且没有报错日志。 业务背景 用户的消费者是一个将文件做Embedding的任务,(由于AI技术的兴起,大…...

Android使用http加载自建服务器静态网页
最终效果如下图,成功加载了电脑端的静态网页内容,这是一个xml文件。 电脑端搭建http服务器 使用“Apache Http Server”,下载地址是:https://httpd.apache.org/download.cgi。 安装启动步骤,参考:Apach…...
python解耦重构,提高程序维护性
一、重构思想 思路来源 java spring设计模式学习,强调低耦合的思想,通过解耦来提高程序的可维护性。 二、代码重构 解决方案 通过单独配置文件来控制变量的改变。 spring的话可以读取xml或者是springboot 读取application.properties 来获取变量值。…...
深入解析 Laravel 事件系统:架构、实现与应用
Laravel 的事件系统是框架中一个强大且灵活的功能,它允许开发者在应用程序中定义和使用自定义事件和监听器。这个系统基于观察者模式,使得代码解耦和可维护性大大提高。在本文中,我们将深入探讨 Laravel 事件系统的工作原理、如何实现自定义事…...

视频怎么制作gif动态图片?GIF制作方法分享
视频怎么制作gif动态图片?视频制作GIF动态图片,不仅保留了视频的生动瞬间,还赋予了图像循环播放的魔力。这一技能不仅让创意表达更加丰富多彩,还极大地提升了视觉传播的效率和趣味性。在快节奏的数字时代,GIF动图以其小…...

js 使用 lodash-es 检测某个值是否是函数
import { isFunction } from lodash-eslet isA isFunction(() > {}) console.log(isA) //true https://www.lodashjs.com/docs/lodash.isFunction#_isfunctionvalue https://lodash.com/docs/4.17.15#isFunction 人工智能学习网站 https://chat.xutongbao.top...

[go-zero] goctl 生成api和rpc
文章目录 1.goctl 概述2.go-zero 需要安装的组件3.生成 api4.生成 rpc 1.goctl 概述 goctl支持多种rpc,较为流行的是google开源的grpc,这里主要介绍goctl rpc protoc的代码生成与使用。protoc是grpc的命令,作用是将proto buffer文件转化为相…...

docker -run hello-world超时
主要原因就是尝试拉取库的时候没有从阿里云镜像里拉,所以设置一下就好了 这里使用的是ubuntu系统(命令行下逐行敲就行了) sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-EOF {"registry-mirrors": [&quo…...
拓扑学习系列(8)黎曼度量曲面与高斯曲率
黎曼度量 黎曼度量是黎曼几何中的一个重要概念,它用来描述流形上的切向量之间的长度和角度。黎曼度量赋予了流形一个内积结构,使得我们可以定义切向量的长度、夹角和内积,从而引入了度量空间的概念。让我更详细地解释一下黎曼度量࿱…...
汽车IVI中控开发入门及进阶(三十四):i.MX linux BSP
开发板: 汽车IVI中控开发入门及进阶(三十三):i.MX linux开发之开发板-CSDN博客 linux 开发项目: 汽车IVI中控开发入门及进阶(三十二):i.MX linux开发之Yocto-CSDN博客 前言: 有了开发板,linux BSP编译项目yocto,接下来就可以在i.MX平台上构建和安装i.MX Linux …...

【Python机器学习】算法链与管道——构建管道
目录 1、首先,我们构建一个由步骤列表组成的管道对象。 2、向任何其他scikit-learn估计器一样来拟合这个管道 3、调用pipe.score 我们来看下如何使用Pipeline类来表示在使用MinMaxScaler缩放数据后,再训练一个SVM的工作流程(暂时不用网格搜…...
Postman 高级用法学习
Postman 高级用法 Postman 是一款强大的 API 调试和开发工具,广泛应用于 API 开发、测试、调试和自动化流程中。除了基本的 API 请求发送和响应查看功能,Postman 还提供了许多高级功能。以下是详细的讲解,包括具体示例和操作步骤。 一、环境…...
从新手到高手:Scala函数式编程完全指南,Scala 访问修饰符(6)
1、Scala 访问修饰符 Scala 访问修饰符基本和Java的一样,分别有:private,protected,public。 如果没有指定访问修饰符,默认情况下,Scala 对象的访问级别都是 public。 Scala 中的 private 限定符ÿ…...

IDEA 一键部署Docker
以部署示例服务(sevnce-demo)为例。 配置服务器 地址、账号、密码根据实际情况填写 配置镜像仓库 地址、账号、密码根据实际情况填写 编写Dockerfile 在sevnce-demo根目录下右键,选择创建Dockerfile。 # 基础镜像 FROM sevnce-registry.c…...

linux centos tomcat 不安全的HTTP请求方法
1、页面查看 2、在linux主机可使用此命令查看 curl -v -X OPTIONS http://实际地址 3、进入tomcat conf目录vim web.xml,增加以下内容 <!-- close insecure http methods --> <security-constraint><web-resource-collection><web-resource…...
深入Django(六)
Django的表单系统 引言 在前五天的教程中,我们介绍了Django的基本概念、模型、视图、模板和URL路由。今天,我们将讨论Django的表单系统,它是处理用户输入、验证数据和与模型交互的重要组件。 Django表单系统概述 Django的表单系统提供了一…...

PHP房产小程序微信小程序系统源码
🏠—— 购房租房,一“指”搞定🏡 🔍【开篇:房产新视界,尽在掌握】 在这个信息爆炸的时代,找房子不再是一场漫长的奔波。有了“房产微信小程序”,无论是购房还是租房,都…...
vscode 历史便携版下载方法
vscode 历史版本地址 https://code.visualstudio.com/updates/v1_75#_remote-developmentexe 信息 下载链接 https://vscode.download.prss.microsoft.com/dbazure/download/stable/5437499feb04f7a586f677b155b039bc2b3669eb/VSCodeUserSetup-x64-1.90.2.exe需要使用的 com…...

深入理解计算机系统 CSAPP 家庭作业8.19
假设n1 会打印 2行 hello 假设n2 会打印 4行 hello 假设n3 会打印 8行 hello 答案 2的n次方...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...

Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...
ubuntu22.04 安装docker 和docker-compose
首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...

java高级——高阶函数、如何定义一个函数式接口类似stream流的filter
java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用(Math::max) 2 函数接口…...
6.9本日总结
一、英语 复习默写list11list18,订正07年第3篇阅读 二、数学 学习线代第一讲,写15讲课后题 三、408 学习计组第二章,写计组习题 四、总结 明天结束线代第一章和计组第二章 五、明日计划 英语:复习l默写sit12list17&#…...
【大厂机试题+算法可视化】最长的指定瑕疵度的元音子串
题目 开头和结尾都是元音字母(aeiouAEIOU)的字符串为元音字符串,其中混杂的非元音字母数量为其瑕疵度。比如: “a” 、 “aa”是元音字符串,其瑕疵度都为0 “aiur”不是元音字符串(结尾不是元音字符) “…...
Async-profiler 内存采样机制解析:从原理到实现
引言 在 Java 性能调优的工具箱中,async-profiler 是一款备受青睐的低开销采样分析器。它不仅能分析 CPU 热点,还能精确追踪内存分配情况。本文将深入探讨 async-profiler 实现内存采样的多种机制,结合代码示例解析其工作原理。 为什么需要内…...