文章目录
- 第一阶段:JavaSE
- 1、面向对象编程(基础)
- 7.IO流
- 1.IO流的概念
- 2.IO流的分类及其原理分析
- 3.文件流FileInputStream、FileOutputStream
- 4.缓冲流BufferedInputStream、BufferedOutputStream
- 5.数据流DataInputStream、DataOutputStream
- 6.对象流ObjectInputStream、ObjectOutputStream
- 7.序列化和反序列化
- 8.转换流InputStreamReader、OutputStreamWriter
- 9.打印流PrintWriter和PrintStream
- 10.数组流ByteArrayOutputStream、ByteArrayInputStream
- 11.随机访问流
- 12.使用IO流复制文件夹
- 13.Apache IO包简介
- 14.Apache IO包FileUitls的使用
- 15.什么时候用字节流,字符流
- 第二阶段:数据库
- 第三阶段:web前端
- 第四阶段:javaEE
- 第五阶段:高级框架
- 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的数据删除
- 2、Spring
- 3、SpringMVC 5.2.2
- 1)MVC架构模式
- 2)SpringMVC简介
- 3)SpringMVC运行原理
- 4)基于配置文件方式搭建环境
- 5)基于注解方式搭建环境
- 6)SpringMVC的跳转及视图解析器的配置
- 7)SpringMVC和Ajax的交互
- 8)Spring 参数注入
- 9)SpringMVC作用域传值
- 10)视图解析器
- 11)文件下载
- 12)文件上传
- 13)Spring拦截器/拦截器栈
- 14)登录状态验证
- 15)SpringMVC容器和Spring容器介绍
- 16)异常处理4种方式
- 17)SpringMVC5其他常用注解
- 18)SpringMVC访问静态资源
- 19)SSM整合
- 20)基于Maven整合SSM
- 21)Spring MVC 与 Spring + MyBatis 的应用案例或者应用场景区别
- 4.RBAC
- 5.Shiro
- 6.设计模式
- 第六阶段:框架强化
- 第七阶段:分布式架构
- 第八阶段:微服务架构
- 第九阶段:项目分析设计
第一阶段: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)递归
7.IO流
1.IO流的概念
2.IO流的分类及其原理分析
3.文件流FileInputStream、FileOutputStream
4.缓冲流BufferedInputStream、BufferedOutputStream
5.数据流DataInputStream、DataOutputStream
6.对象流ObjectInputStream、ObjectOutputStream
7.序列化和反序列化
8.转换流InputStreamReader、OutputStreamWriter
9.打印流PrintWriter和PrintStream
10.数组流ByteArrayOutputStream、ByteArrayInputStream
11.随机访问流
12.使用IO流复制文件夹
13.Apache IO包简介
14.Apache IO包FileUitls的使用
15.什么时候用字节流,字符流
在Java中,字节流(Byte Streams)和字符流(Character Streams)的选择取决于你要处理的数据类型以及你的具体需求。下面是一些指导原则,帮助你决定何时使用字节流或字符流:
15.1 使用字节流的情况:
处理二进制数据:当你需要处理非文本数据(如图片、音频、视频文件或任何二进制格式的数据)时,应该使用字节流。字节流能够按字节读取或写入数据,非常适合处理这些类型的文件。
不关心数据内容:如果你不关心数据的具体内容,只需要将原始字节从一个地方传输到另一个地方(例如,文件复制或网络传输),那么字节流是更好的选择。
字符编码不明确:当你不确定数据的字符编码,或者数据本身就是以字节为单位(如加密数据)时,字节流是更合适的选择。
15.2 使用字符流的情况:
处理文本数据:当你需要处理文本数据时,应该使用字符流。字符流会处理字符编码和解码,确保读取或写入的文本数据正确无误。
需要字符级别的操作:如果你需要对文本数据进行字符级别的操作(如读取、写入、修改等),字符流提供了更直观的API来支持这些操作。
提高可读性:对于人类可读的文本数据,使用字符流可以提高代码的可读性和可维护性。字符流使得处理文本数据更加直观和方便。
15.3 注意事项:
字符编码:在使用字符流时,需要特别注意字符编码。不同的编码方式可能导致乱码问题。因此,在读取或写入文本数据时,应确保使用正确的字符编码。
性能考虑:虽然字符流在处理文本数据时更加方便,但在处理大量二进制数据时,字节流可能会提供更好的性能。因为字符流在读取或写入字符时需要进行编码或解码操作,这可能会增加额外的开销。
包装流:Java提供了许多包装流(如BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter等),它们可以包装在字节流或字符流之上,提供额外的功能(如缓冲、字符编码转换等)。这些包装流可以进一步简化数据的读写操作。
综上所述,选择字节流还是字符流主要取决于你要处理的数据类型以及你的具体需求。在处理文本数据时,字符流是更好的选择;而在处理二进制数据或需要高性能的场景下,字节流可能更合适。
第二阶段:数据库
第三阶段:web前端
第四阶段:javaEE
1.网络协议
2.XML技术
3.servlet
4. JSP
5.EL+JSTL+过滤器+监听器
6.Ajax和JSON
第五阶段:高级框架
1、mybatis
1)MyBatis概述
2)MyBatis入门配置
3)基本的CRUD操作
4)核心配置文件详解
配置案例一:单个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 说明该 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 configuration
PUBLIC "-//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.常见的连接池有:
阿里巴巴的德鲁伊连接池:druid
c3p0
dbcp
...
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 configuration
PUBLIC "-//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 configuration
PUBLIC "-//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.xsd
http://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.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://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的数据删除
2、Spring
1)Spring框架简介
2)Spring官方压缩包目录介绍
3)Spring环境搭建
4)IoC/DI容器详解
5)Spring创建Bean的三种方式
6)scope属性讲解
7)Spring中几种注入方式
8)静态代理设计模式
9)动态代理设计模式
10)AOP详解
11)AOP中几种通知类型
12)AOP两种实现方式
13)自动注入
14)声明式事务
15)事务传播行为
16)事务隔离级别
17)只读事务
18)事务回滚
19)基于注解式配置
20)常用注解
21)Spring 整合MyBatis
22)Spring整合Junit
23)理解为什么使用Spring框架
3、SpringMVC 5.2.2
1)MVC架构模式
2)SpringMVC简介
3)SpringMVC运行原理
4)基于配置文件方式搭建环境
5)基于注解方式搭建环境
6)SpringMVC的跳转及视图解析器的配置
7)SpringMVC和Ajax的交互
8)Spring 参数注入
9)SpringMVC作用域传值
10)视图解析器
11)文件下载
12)文件上传
13)Spring拦截器/拦截器栈
14)登录状态验证
15)SpringMVC容器和Spring容器介绍
16)异常处理4种方式
17)SpringMVC5其他常用注解
18)SpringMVC访问静态资源
19)SSM整合
20)基于Maven整合SSM
21)Spring MVC 与 Spring + MyBatis 的应用案例或者应用场景区别
Spring MVC 是一个用于构建 Web 应用程序的 MVC 框架,它提供了一种分离 Web 层、业务逻辑层和数据持久层的方法。Spring MVC 广泛应用于各种类型的 Web 应用程序,包括但不限于:
- 企业级应用:Spring MVC 提供了一套完整的 Web 开发解决方案,适用于构建复杂的业务逻辑和数据处理的企业级应用程序。
- 电子商务网站:Spring MVC 可以用来构建高性能、可扩展的电子商务网站,支持在线购物车、订单处理、用户管理等。
- 内容管理系统(CMS):Spring MVC 适用于构建内容管理系统,允许用户管理网站内容和结构。
- RESTful 服务:Spring MVC 支持构建 RESTful 风格的 Web 服务,适用于前后端分离的项目,提供 JSON 或 XML 格式的数据接口。
==Spring + MyBatis ==通常用于需要复杂 SQL 查询和数据库操作的应用程序,MyBatis 提供了比 Hibernate 更细粒度的 SQL 控制能力。这种组合适用于以下场景:
- 金融系统:在金融系统中,经常需要进行复杂的数据库操作和报表生成,MyBatis 提供了灵活的 SQL 映射和查询能力。
- 大型电子商务系统:在大型电子商务系统中,需要对大量的商品信息、订单信息等进行高效的数据访问和管理,MyBatis 可以提供高性能的数据操作。
- 数据仓库和报表系统:MyBatis 的灵活性使得它特别适合用于数据仓库和报表系统,这些系统通常需要执行复杂的 SQL 查询来处理大量的数据。
- 遗留系统迁移:对于需要迁移遗留系统的项目,MyBatis 允许开发人员逐步迁移,而不需要完全重写现有的数据访问代码。
Spring MVC 和 Spring + MyBatis 经常结合使用,以构建完整的 Web 应用程序,它们可以提供高度定制性和灵活性,适用于各种规模和复杂度的项目。
SSM是指Spring、Spring MVC和MyBatis这三个开源框架的集合,它们通常一起使用来构建Java企业级应用。这三个框架分别负责不同的层面:
- Spring:核心容器框架,负责管理应用程序的组件和生命周期,提供依赖注入(DI)和面向切面编程(AOP)的功能。
- Spring MVC:Web层的框架,用于构建Web应用程序,处理HTTP请求和响应,提供前端控制器和视图解析等功能。
- MyBatis:持久层框架,用于数据库操作和SQL映射,提供了一种半自动化的ORM实现,允许开发者自定义SQL语句。
SSM框架组合的应用场景包括:
- 企业级应用:SSM适合构建复杂的业务逻辑和数据交互的企业级应用,能够处理大量的数据和复杂的业务流程。
- 互联网应用:包括电子商务网站、社交媒体平台、在线教育系统等,SSM能够提供高性能和可扩展的Web服务。
- 管理系统:例如内容管理系统(CMS)、客户关系管理系统(CRM)、企业资源规划系统(ERP)等,SSM可以帮助构建管理后台和数据处理中心。
- RESTful服务:SSM支持构建RESTful风格的Web服务,适用于前后端分离的应用程序,提供JSON或XML格式的数据接口。
- 移动应用后台:随着移动应用的普及,SSM可以作为移动应用的后台服务,处理移动端发送的请求并提供数据处理能力。
- 遗留系统改造:对于需要改造的遗留系统,SSM提供了一种逐步迁移的方案,可以在不彻底重构的情况下提升系统的性能和可维护性。
- 大数据应用:虽然MyBatis主要用于关系型数据库,但SSM也可以与大数据技术结合,例如通过Spring Data与NoSQL数据库集成,处理大规模的数据分析任务。
- 微服务架构:虽然微服务通常与轻量级的框架如Spring Boot和Spring Cloud结合使用,但SSM仍然可以用于构建微服务中的某些服务,尤其是在需要复杂事务管理和细粒度数据控制的情况下。
SSM框架因其成熟、稳定且易于集成的特点,在Java EE领域有着广泛的应用。随着技术的发展,一些新的框架和工具(如Spring Boot和Spring Cloud)逐渐流行,但SSM仍然是许多企业和开发者的首选技术栈。
Spring Boot 是一个开源的 Java-based 微服务框架,用于创建独立的、生产级别的基于 Spring 的应用程序。它旨在简化 Spring 应用的初始搭建以及开发过程,它使用“约定优于配置”的原则,减少了项目的配置量。以下是 Spring Boot 的一些主要应用场景: - 微服务架构:Spring Boot 是创建微服务的理想选择,因为它可以快速搭建独立的服务,并且与 Spring Cloud 完美集成,后者提供了在分布式系统环境中服务发现、配置管理、负载均衡等微服务支持功能。
- RESTful Web 服务:Spring Boot 内置了多种 Web 容器支持,如 Tomcat、Jetty 和 Undertow,可以轻松创建提供 RESTful 接口的 Web 服务。
- 自动化配置:Spring Boot 的自动化配置特性使得它可以快速启动和运行 Spring 应用程序,减少了手动配置的需要,特别适合快速原型开发和项目启动。
- 企业级应用:Spring Boot 可以用于构建复杂的、全栈的企业级 Java 应用程序,支持事务管理、安全性、监控、日志记录等功能。
- 数据库访问:Spring Boot 提供了简化的数据库访问配置,支持 JPA、JDBC、NoSQL 数据库等多种数据访问技术。
- 命令行应用:Spring Boot 可以创建独立的命令行应用程序,这些应用程序可以打包为 JAR 并运行在任何支持 Java 的平台上。
- 云应用:Spring Boot 应用程序可以很容易地部署到云环境中,如 Pivotal Cloud Foundry、Amazon Web Services、Google Cloud Platform 等。
- IoT 应用:Spring Boot 可以用于构建 IoT(物联网)设备后端,处理设备数据、执行业务逻辑并与设备通信。
- 整合第三方库:Spring Boot 有着丰富的 starter 依赖,可以轻松地整合第三方库和框架,如 Kafka、RabbitMQ、MongoDB、Redis 等。
- 容器化应用:Spring Boot 应用程序非常适合容器化,可以与 Docker、Kubernetes 等容器技术无缝集成,实现应用的自动化部署和扩展。
Spring Boot 的设计目标是简化开发、提高开发速度,并使 Java 应用程序的部署变得更加容易。它适用于各种规模的项目,从简单的单体应用到复杂的微服务架构都可以胜任。
4.RBAC
5.Shiro
6.设计模式
根据项目来描述,用了哪些设计模式:
-
spring静态代理,动态代理。例如:静态代理,在javaweb中就用一个典型的例子,我们可以将service层看做是dao层的代理,dao层需要专注于纯粹的数据库交互。动态代理,Spring 框架中的AOP,主要基于两种方式:JDK 及 CGLIB 的方式。这两种方式的代理目标都是被代理类中的方法,在运行期,动态的织入字节码生成代理类。
-
单例模式,例如:推送指标项目里
public static SystemConfig newInstance(Map<String, String> confMap) {
if (systemConfig == null) {
systemConfig = new SystemConfig();
init(confMap);
}
return systemConfig;
}
- 工厂模式,例如:spring-common.xml配置各种数据库封装在底层
- 观察者模式,例如:微信公众号:微信公众号是被观察者对象,粉丝是观察者对象。当公众号发布了新的文章或消息时,系统会发送消息给关注该公众号的粉丝。
第六阶段:框架强化
第七阶段:分布式架构
第八阶段:微服务架构
第九阶段:项目分析设计
老程序员欢迎加入扣扣组织,783092701