企业基础知识点汇总
面向对象
面向对象三大特征

String,StringBuilder,StringBuffer

简要的说, String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象, 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,这样不仅效率低下,而且大量浪费有限的内存空间,所以经常改变内容的字符串最好不要用 String
String:字符串常量
StringBuffer:字符串变量;线程安全的
StringBuilder:字符串变量;线程非安全的
StringBuilder与StringBuffer二者的区别主要是在运行速度和线程安全这两方面。
1、StringBuffer 与 StringBuilder 中的方法和功能完全是等价的
2、只是StringBuffer 中的方法大都采用了 synchronized 关键字进行修饰,因此是线程安全的,而 StringBuilder 没有这个修饰,可以被认为是线程不安全的。
3、在单线程程序下,StringBuilder效率更快,因为它不需要加锁,不具备多线程安全,而StringBuffer则每次都需要判断锁,效率相对更低。
三者使用的总结:1.如果要操作少量的数据用 = String 2.单线程操作字符串缓冲区 下操作大量数据 = StringBuilder 3.多线程操作字符串缓冲区 下操作大量数据 = StringBuffer
重写与重载
重写(override)
遵循运行期绑定
什么时候使用重写?
1、当父类方法无法满足子类需求,此时可以在子类中重写父类方法
2、如果开发时,需要对父类方法功能拓展,此时还不想修改父类程序则使用继承(定义一个类继承父类),然后通过子类重写该方法,然后其他类进行调用这个子类方法;
两同两小一大方法名相同,参数列表相同。派生类方法的返回值必须小于等于超类的派生类方法抛出的异常小于或等于超类的派生类方法的访问权限大于或等于超类的
重载(overload)
发生在一个类中,方法名相同,参数列表不同,方法体不同
遵循 “编译期绑定”,看参数/引用类型来绑定方法
this和super
this指代当前对象,哪个对象调用方法,它就指向哪个对象this.成员变量名————访问成员变量this.方法名()————调用方法this()————调用构造方法
super指代当前对象的超类对象super.成员变量名————访问超类的成员变量super.方法名————调用超类的方法super()————调用超类的构造方法
静态Static
static 声明方法为静态方法(静态方法只能访问静态成员。(非静态既可以访问静态,又可以访问非静态)),声明属性为静态属性;
static 关键词:1、static 修饰方法,该方法叫做静态方法(也叫做类方法),可直接通过这个类的类名打点直接调用;2、静态方法中不能使用this/super关键词,静态方法不能直接调用当前类中的非静态方法(或非静态属性),必须通过new实例化后在调用。3、static声明的方法和属性,该对象已经被实例化,且只能被实例化一次(单例模式)4、static修饰的属性,被相同类的不同实例所共享;
如果某个成员变量时被所有对象所共享的,那么这个成员变量就可以定义为静态变量。
流程控制语句
break 跳出上一层循环,不再执行循环(结束当前的循环体)
continue 跳出本次循环,继续执行下次循环
return 程序返回,不再执行下面的代码(结束当前方法,直接返回)
类与接口
抽象类和接口的对比
抽象类是用来捕捉子类的通用特性。接口是抽象方法的集合。
从设计层面来说,抽象类是对类的抽象,是一种模板设计,接口是行为的抽象,是一种行为的规范
相同点
接口和抽象类都不能实例化
都位于继承的顶端,用于被其他类实现或继承
都包含抽象方法,其子类都必须重写这些抽象方法
不同点

构造方法
概述:构造方法存在于类中,给对象数据(属性)初始化;
特点:方法名与类名一样;无返回值无void;
默认构造方法:我们不创建一个构造方法时,系统默认提供一个无参构造;当我们创建一个构造方法时,系统不再提供无参构造,所以在实际项目中,全部手动给出无参构造
主要作用是完成对类对象的初始化工作。
内部类
将一个类的定义放在另外一个类的定义内部,这就是内部类。内部类本身就是类的一个属性,与其他属性定义方式一致。
内部类四种:
成员内部类定义在类内部,成员位置上的非静态。可以访问外部类所有的变量和方法,包括静态和非静态,私有和共有。成员内部类依赖外部类的实例
局部内部类定义在方法中的内部类,就是局部内部类
匿名内部类没有名字的内部类必须继承一个抽象类或者实现一个接口不能定义任何静态成员和静态方法当所在的方法的形参需要被匿名内部类使用时,必须声明为final匿名内部类不能是抽象的,它必须实现继承的类或实现的接口所有抽象方法
静态内部类定义在类内部的静态类,可以访问外部类所有的静态变量,而不可访问外部类的非静态变量。
优点:
一个内部对象可以访问创建它的外部类对象的内容
内部类不为同一包的其他类所见,有很好的封装性
内部类有效实现了多继承。
匿名内部类可以很方便的定义回调
异常
1.Throwable是Java语言中所有错误与异常的超类
包含两个子类:Error和Exception
2.Error(错误):非代码性错误,运行应用程序的错误
3.Exception(异常):程序本身可以捕获并且可以处理的异常
运行时异常:RuntimeException
ClassCastException(类转换异常)
IndexOutOfBoundsException(数组越界)
NullPointerException(空指针)
编译时异常:ClassNotFoundException,IOException
异常处理:throw抛出,try-catch捕获
throws在方法上声明要抛出的异常
throw在方法内部抛出异常对象
内存管理
1.堆
存储new出来的对象(包括实例变量)
2.栈
存储正在调用的方法中的所有局部变量(包括方法的参数)
调用方法时会在栈中为该方法分配一块对应的栈帧,栈帧中存储方法中的局部变量(包括参数),方法调用结束,栈帧自动被清楚,局部变量(参数)一并被清楚
3.方法区
存储.class字节码文件(包括静态变量,方法)
方法只有一份,通过this来区分具体的调用对象
集合
集合框架
java.util.Collection接口,该接口是所有集合的顶级接口
里面规定了所有集合都要具备的功能。
集合与数组一样,用来保存一组元素,但是集合有多种不同的数据
结构,和各自的特点
1.集合与数组的区别
长度区别:数组是固定长度,集合时可变长度。
内容区别:数组可以是基本类型,也可以是引用类型。 集合只能是引用类型
元素内容:数组只能存储同一种类,集合可以存储不同类型(其实集合一般存储的也是同一种类型)
2.集合的方法
Boolean add(E e)在集合末尾添加元素
Boolean remove(Object o)若本类集合中有值与o的值相等的元素,则删除该元素,并返回true
void clear() 清除本集合中所有元素,调用该方法后本集合将为空
boolean contains(Object o)判断集合中是否包含某元素
boolean isEmpty()判断集合是否为空
int size()返回集合中元素个数
boolean addAll(Collection c)将一个集合c中的所有元素添加到另一个集合
Object[ ]toArray()返回一个包含了本集合中所有元素的数组,数组类型为Object
数组转List:使用Arrays.asList(array)进行转换
Interator iterator()迭代器,集合专用遍历方式
sort java.util.Collection提供了一个静态方法sort,可以对List集合进行自然排序(从小到大)
3.常用集合的分类
Connection接口:
一.List 有序,可重复
ArrayList优点:底层数据结构是数组,查询快,增删慢缺点:线程不安全,效率高
Linkedlist优点:底层数据结构是链表,查询慢,增删快缺点:线程安全,效率低
二.Set 无序,唯一
HashSet底层数据结构是哈希表(无序,唯一)依赖hashCode()和equals()来保证元素唯一性
TreeSet底层数据结构是红黑树。(唯一,有序)通过自然排序,比较器排序根据比较的返回值是否为0来决定元素唯一性
Map接口:
HashMap: JDK1.8之前HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的(“拉链法”解决冲突).JDK1.8以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间
LinkedHashMap:LinkedHashMap 继承自 HashMap,所以它的底层仍然是基于拉链式散列结构即由数组和链表或红黑树组成。另外,LinkedHashMap 在上面结构的基础上,增加了一条双向链表,使得上面的结构可以保持键值对的插入顺序。同时通过对链表进行相应的操作,实现了访问顺序相关逻辑。
HashTable: 数组+链表组成的,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的
TreeMap: 红黑树(自平衡的排序二叉树)
Queue接口 队列
offer入队操作,元素会添加到队列末尾
poll出队操作,获取队首元素并将其从队列中删除
peek是引用队首元素,获取后元素仍在队列中Deque接口,双端队列
Deque继承自Queue,双端队列的特点是队列两端都可以做
出入对的操作 offerFirst和offerLast
栈
栈是经典的数据结构之一,可以保存一组元素,但是存取元素必须
遵循先进后出原则。
一般使用栈来实现“后退”这样的功能 方法push
迭代器Iterator
Iterator接口提供遍历任何Collection的接口。迭代器允许在迭代过程中移出元素
二.List和Set集合详解
1.List和Set的区别
有序性
List保证按插入顺序排序
Set存储和取出顺序不一致
唯一性
List可以重复
Set元素唯一
获取元素
List可以通过索引直接操作元素
Set不能根据索引获取元素
2.List
(1)ArrayList:底层数据结构是数组,查询快,增删慢,线程不安全,效率高,可以存储重复元素(2)LinkedList 底层数据结构是链表,查询慢,增删快,线程不安全,效率高,可以存储重复元素
3.Set
(1)HashSet底层数据结构采用哈希表实现,元素无序且唯一,线程不安全,效率高,可以存储null元素,元素的唯一性是靠所存储元素类型是否重写hashCode()和equals()方法来保证的,如果没有重写这两个方法,则无法保证元素的唯一性。
(2)LinkedHashSet底层数据结构采用链表和哈希表共同实现,链表保证了元素的顺序与存储顺序一致,哈希表保证了元素的唯一性。线程不安全,效率高。
(3)TreeSet底层数据结构采用二叉树来实现,元素唯一且已经排好序;唯一性同样需要重写hashCode和equals()方法,二叉树结构保证了元素的有序性。
(4)小结:Set具有与Collection完全一样的接口,因此没有任何额外的功能,不像前面有两个不同的List。实际上Set就是Collection,只 是行为不同。(这是继承与多态思想的典型应用:表现不同的行为。)Set不保存重复的元素。Set 存入Set的每个元素都必须是唯一的,因为Set不保存重复元素。加入Set的元素必须定义equals()方法以确保对象的唯一性。Set与Collection有完全一样的接口。Set接口不保证维护元素的次序。
4.List和Set总结
(1)、List,Set都是继承自Collection接口,Map则不是(2)、List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉,(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的,加入Set 的Object必须定义equals()方法 ,另外list支持for循环,也就是通过下标来遍历,也可以用迭代器,但是set只能用迭代,因为他无序,无法用下标来取得想要的值。)(3).Set和List对比:Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。(4)、ArrayList与LinkedList的区别和适用场景Arraylist:优点:ArrayList是实现了基于动态数组的数据结构,因为地址连续,一旦数据存储好了,查询操作效率会比较高(在内存里是连着放的)。缺点:因为地址连续, ArrayList要移动数据,所以插入和删除操作效率比较低。
LinkedList:优点:LinkedList基于链表的数据结构,地址是任意的,所以在开辟内存空间的时候不需要等一个连续的地址,对于新增和删除操作add和remove,LinedList比较占优势。LinkedList 适用于要头尾操作或插入指定位置的场景缺点:因为LinkedList要移动指针,所以查询操作性能比较低。适用场景分析:当需要对数据进行对此访问的情况下选用ArrayList,当需要对数据进行多次增加删除修改时采用LinkedList。
三.Map详解
Map用于保存具有映射关系的数据,Map里保存着两组数据:key和value,它们都可以使任何引用类型的数据,但key不能重复。所以通过指定的key就可以取出对应的value。
java.util.Map 接口 查找表
Map体现的样子是一个多行两列的表格,其中左列称为Key
右列称为Value。 map总是成对的保存数据,并且总是根据
key去获取对应的value。因此保存数据时,我们经常将查询
的条件作为key,查询的结果作为value保存到Map中方便提取
数据。
Map中的key是不允许重复的(equsls判断)
Map的常用实现类:
java.util.HashMap:散列表,使用散列算法实现的Map,
当今查询速度最快的数据结构。
TreeMap:二叉树实现的Map
(1)、请注意!!!, Map 没有继承 Collection 接口, Map 提供 key 到 value 的映射,你可以通过“键”查找“值”。一个 Map 中不能包含相同的 key ,每个 key 只能映射一个 value 。 Map 接口提供 3 种集合的视图, Map 的内容可以被当作一组 key 集合,一组 value 集合,或者一组 key-value 映射。
(2)Map:
(3)HashMap和HashTable的比较:
(4)TreeMap:
适用场景分析:HashMap和HashTable:HashMap去掉了HashTable的contains方法,但是加上了containsValue()和containsKey()方法。HashTable同步的,而HashMap是非同步的,效率上比HashTable要高。HashMap允许空键值,而HashTable不允许。
HashMap:适用于Map中插入、删除和定位元素。Treemap:适用于按自然顺序或自定义顺序遍历键(key)。
5.线程安全集合类与非线程安全集合类LinkedList、ArrayList、HashSet是非线程安全的,Vector是线程安全的;HashMap是非线程安全的,HashTable是线程安全的;StringBuilder是非线程安全的,StringBuffer是线程安全的。
数据结构ArrayXxx:底层数据结构是数组,查询快,增删慢LinkedXxx:底层数据结构是链表,查询慢,增删快HashXxx:底层数据结构是哈希表。依赖两个方法:hashCode()和equals()TreeXxx:底层数据结构是二叉树。两种方式排序:自然排序和比较器排序
进程与线程
什么是进程
进程是操作系统中运行的一个任务(一个应用程序运行在一个进程中)。
进程是一块包含了某些资源的内存区域。操作系统利用进程把它的工作划分为一些功能单元。
进程中所保护的一个或多个执行单元称为线程。
线程只能归属一个进程,并且他只能访问该进程所拥有的资源。当操作系统创建一个进程后,该进程会自动申请一个名为主线程或首要线程的线程。
什么是线程
一个线程是进程的一个顺序执行流
同类的多个线程共享一块内存空间或一组系统资源,线程本身有一个供程序执行的堆栈。线程在切换时负荷小,因此,线程也被称为轻负荷进程。一个进程中可以包含多个线程。
进程与线程的区别
一个进程至少有一个线程。线程的划分尺度小于进程,使得多线程程序的并发性高。另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大的提高了程序的运行效率。线程在执行过程中与进程的区别在于每个独立的线程有一个程序运行的入口,顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
线程使用的场合
线程通常用于在一个程序中,需要同时完成多个任务的情况。我们可以将每个任务定义为一个线程,使他们得以一同工作。
也可以用于在单一线程中可以完成,但是使用多线程可以更快的情况。比如下载文件。
并发原理
多个线程"同时"运行只是我们感官上的一种表现。事实上线程是并发运行的,OS将时间划分为很多时间片段(时间片),尽可能均匀分配给每一个线程,获取时间片段的线程被CPU运行,而其他线程全部等待。所以微观上是走走停停的,宏观上都在运行。这种现象叫并发,但不是绝对意义上的”同时发生“。
创建线程
继承Thread并重写run方法
Thread类是线程类,其每一个实例表示一个可以并发运行的线程。我们可以通过继承该类并重写run方法来定义一个具体的线程。其中重写run方法的目的是定义该线程要执行的逻辑。启动线程时调用start()方法而非直接调用run()方法。start()方法会将当前线程纳入线程调度,使当前线程可以开始并发运行。当线程获取时间片段后,会自动开始执行run方法中的逻辑。
实现Runnable接口单独定义线程任务
实现Runnable接口并重写run方法来定义线程体,然后在创建线程的时候将Runnable的实例传入并启动线程。
第二种创建的好处在于可以将线程与线程要执行的任务分离开,减少耦合,同时java是单继承的,定义一个类实现Runnable接口的做法,可以更好的去实现其他父类或接口。
获取线程信息
long getID():返回该线程的标识符
String getName():返回该线程的名称
int getPriority():返回线程的优先级
Thread.state.getState():获取线程的状态
boolean isAlive():测试线程是否处于活动状态
boolean isDaemon():测试线程是否为守护线程
boolean isInterrupted():测试线程是否已经中断
线程的优先级
线程的切换是由线程调度控制的,我们无法通过代码来干涉,但是可以通过线程的优先级来最大程度的改善线程获取时间片的几率。
线程的优先级为10级,1-10,其中1最低,10最高。线程提供了3个常量来表示最低,最高,以及默认优先级:Thread.MIN_PRIORITY,Thread.MAX_PRIORITY,Thread.NROM_PRIORITY,void setPriority(int priority):设置线程的优先级
守护线程
sleep方法
Thread的静态方法sleep 用于使当前线程进入阻塞状态:static void sleep(long ms)
该方法会使当前线程进入阻塞状态指定毫秒,当阻塞指定毫秒后,当前线程会重新进入Runnable状态,等待分配时间片。
该方法声明会抛出一个InterruptException。所以在使用该方法时,需要捕获这个异常。
yield()
Thread的静态方法yield:static void yield()
该方法用于使当前线程主动让出当次CPU时间片回到Runnable状态,等待分配时间片
join方法
void join()
该方法用于等待当前线程结束。声明抛出InterruptException。
线程同步
synchronized关键字
多个线程并发读写同一个临界资源时,会发生"线程并发安全问题"。
常见的临界资源:多线程共享实例变量,多线程共享静态公共变量。
解决方法,需要将异步操作,变为同步操作。
异步操作:多线程并发的操作,相当于各干各的。
同步操作:有先后顺序的操作,相当于你干完我再干
synchronized是java中的同步锁
锁机制
/*
* 线程池
* 线程池是管理线程的机制,主要解决两个问题:
* 1:控制线程数量:线程数量过多会占用更多系统资源并可能出现
* CPU过度切换,造成并发性性能降低和内存溢出等风险
* 2:重用线程:频繁的创建和销毁线程会给线程调度带来额外的
* 开销,因此应当延长线程的生命周期。
*
*/
public class ThreadPoolDemo {
public static void main(String[] args) {
//创建一个固定大小的线程池,这里容量是2.
ExecutorService threadPool
=Executors.newFixedThreadPool(2);
for(int i=0;i<5;i++) {
Runnable r=new Runnable() {
public void run() {
try {
Thread t=Thread.currentThread();
System.out.println(t+"正在执行一个任务...");
Thread.sleep(3000);
System.out.println(t+"执行任务完毕!");
} catch (Exception e) {
}
}
};
threadPool.execute(r);
System.out.println("交给线程池一个任务...");
}
System.out.println("结束线程池");
threadPool.shutdown();
//立刻停止线程池
//threadPool.shutdownNow();
}
反射
JAVA反射机制是在运行状态中,对任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息,调用对象的方法的功能,称为反射。
反射就是把java类中的各种成分映射成一个个的Java对象
/*
* java反射机制
*
* 反射是一种动态机制,允许我们实例化对象,调用方法,操作
* 属性从编码期间确定,转移到程序运行期确定。
* 因此反射提高了程序的灵活度,但是随之带来的是更多的系统开销
* 和较慢的运行效率。因此反射机制不能过度的使用。
*/
public class ReflectDemo1 {
public static void main(String[] args) {
/*
* 反射的第一步,获取要利用反射操作的类的类对象
* Class类的实例
* JVM中每个被加载的类都有且只有一个Class的实例
* 与之对应,通过类对象(Class的实例)我们可以得知
* 其表示的类的一切信息,例如:类名,有哪些属性,哪些
* 方法,哪些构造器等等。并利用这些在程序运行期间操作
* 他们。
*
* 获取一个类的类对象有三种方式:
* 1.类名.class
* 例如:
* Class cls=String.class;
* Class cls=int.class;
*
* 2.Class.forName(String className)
* 例如:
* Class cls=Class.forName("java.lang.String:);
* 这里forName方法传入的是类的完全限定名,格式为:包名.类名
*
* 3.使用对象的getClas()获取
Class cls=new Class();
Class c=cls.getClass();
*/
//优点:简单,直接 缺点:硬编码获取,不灵活
// Class cls=String.class;
// Class cls1=int.class;
try {
/*
* java.util.ArrayList
* java.util.HashMap
* java.io.FileOutputStream
*/
//cls = Class.forName("java.lang.String");
Scanner sca=new Scanner(System.in);
System.out.println("请输入一个类名:");
String className=sca.nextLine();
Class cls=Class.forName(className);
String name=cls.getName();
System.out.println(name);
//获取String中所有公开方法
//Method[]methods=cls.getMethods();
/*
* 获取到本类自己定义的方法,包括私有方法
*/
Method[]methods=cls.getDeclaredMethods();
for(Method method:methods) {
System.out.println(method.getName());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
反射API
Java反射API提供了动态执行能力
ClassAPI:
——java.long.Class类,用于加载类和获取类的相关信息
Constructor:用来描述一个类的成员变量
Field:用来描述一个类的方法
Method:用来描述一个类的方法
Modifier:用来描述类内各元素的修饰符
动态加载类
Class.forName():
Class cls=Class.forName(类名)
1.类名是运行期间动态输入的类名,可以是任何类名
2.返回值是一个引用,利用这个引用指向的对象可以访问方法区中的类信息
3.如果类名是错误的将出现“类没有找到”的异常
动态创建对象
newInstance()
Object newInstance()
1.newInstance方法将调用类信息中的无参构造器创建对象,如果没有无参构造器,将抛出没有方法的异常。
2.如果需要调用有参构造器,可以利用Constructor API实现。
3.返回值引用动态创建的对象,因为可以是任何类型的对象,所有其类型为Object。
动态调用方法
动态发现方法
Method[]getDeclaredMethods()
1.Method代表方法信息,可以利用Method API获取方法对详细信息,如:方法名,返回值类型,参数类型列表
2.这个方法返回对数组代表当前类中对全部方法信息,每个元素代表一个方法信息。
动态执行方法
Object invoke(Object obj,Object...args)
IO流
IS与OS
InputStream是所有字节输入流的父类,其定义了基础的读取方法
int read()
OutputStream是所有字节输出流的父类,其定义了基础的写出方法
void write()
文件流
FileOutputStream是文件的字节输出流,使用该流可以以字节为单位将数据写入文件
FileOutputStream(File file)
FileInputStream是文件的字节输入流,使用该流可以以字节为单位从文件中读取数据。
read()和write(int d)方法
●FileInputStream 继承自InpuStream,其提供了以字节为单位读取文件数据的方法read
●int read()从此输出流中读取一个数据字节,若返回-1则表示(End Of File)读到了文件末尾int read(byte[]b)批量读取
●FileOutputStream继承自OutputStream,其提供了以字节为单位向文件写数据的方法write
●void write(int d)
●void write(byte[]d) 批量写入将指定字节写入此文件输出流。这里只写给定的int 值的“低八位”。
缓冲流
BOS基本工作原理
●使用缓冲输出流来一次批量写出若干数据减少写出次数,来提高写出效率
●BufferOutputStream缓冲输出流内部维护着一个缓冲区,每当向该流写数据时,都会先将数据存入缓冲区,当缓冲区已满时,缓冲流会将数据一次性全部写出。
BOS的flush方法
●void flush() 清空缓冲区,将缓冲区的数据强制写出。
BIS基本工作原理
●通过提高一次读取的字节数量减少读写次数来提高读取的效率
●BufferInputStream是缓冲字节输入流。其内部维护着一个缓冲区(字节数组),使用该流在读取一个字节时,该流会尽可能多的一次性读取若干字节并存入缓冲区,然后逐一的将字节返回,直到全部读取完毕。
●BIS是一个处理流
对象流
●对象是存在于内存中的。有时我们需要将对象保存到硬盘上,或者传输到另一台机器。这时我们需要将对象转换为一个字节序列,而这个过程就称为对象序列化。相反,将字节序列转换为对应的对象,称为对象的反序列化。
使用OOS实现对象序列化
●ObjectOutputStream是用来对对象进行序列化的输出流
●void writeObject(Object o) 该方法可以将给定的对象转换为一个字节序列后写出。
使用OIS实现对象反序列化
●ObjectputStream是用来对对象进行反序列化的输入流
●Object readObject() 该方法可以从流中读取字节并转换为对应的对象。
transient关键字
●被该关键字修饰的属性在序列化时,其值将被忽略
字符流原理
●Reader是字符输入流的父类
●Write是字符输出流的父类
●字符流是以字符(char)为单位读写数据的,一次处理一个Unicode。
●字符流的底层仍然是基本的字节流。
●字符流封装了字符的编码解码算法。
Reader的常用方法:
int read():读取一个字符,返回的int值"低16位"有效
int read(char[]chs):从该流中读取一个字符数组的length个字符存入该数组,返回值为实际读取的字符量
Write的常用方法:
void write
转换流
字符转换流原理
●InputStreamReader:字符输入流使用该流可以设置字符集,并按照指定的字符集从流中按照编码将字节数据转换为字符并读取。
●OutputStreamWrite:字符输出流使用该流可以设置字符集,并按照指定的字符集将字符转换为对应字节后通过该流写出。
PrintWriter
创建PW对象
●PrintWriter是具有自动行刷新的缓冲字符输出流。其提供了比较丰富的构造方法。
BufferedReader
构建BufferedReader
●BufferedReader是缓冲字符输入流,其内部提供了缓冲区,可以提供读取效率
IO流总结
一、IO流的三种分类方式:
1.按照流向来分:输入流:只能从中读取字节数据,不能向其写出数据输出流:只能向其写入字节数据,不能从中读取数据2.按照流所处理的数据类型划分:可分为:字节流:用于处理字节数据。字符流:用于处理Unicode字符数据。3.按照格式可以分为:节点流(低级流)可以从向一个特定的IO设备(如磁盘,网络)读写数据的流。处理流(高级流):可以对一个已存在的流的连接和封装,通过所封装的流的功能实现数据读写功能的流。
二.按操作方式分类
三.按照操作对象
WEB
1.web前端(学习如何开发网站页面)
2.数据库
3.Servlet
Web前端
1.HTML(如何搭建页面结构和内容 类似于盖房子 毛坯房)
2.CSS(美化页面 类似装修)
3.JavaScript(给页面添加动态效果)
4.JQuery(JavaScript语言框架,简化JavaScript代码)
5.Bootstrap前端页面的综合框架,作用:让前端页面开发变得更高效
HTML
●Hyper Text Markup Language: 超文本标记语言
●超文本:不仅仅是纯文本,还包括字体相关,以及多媒体内容(图片/音频/视频)
●XML也是标记语言 , 区别就是 XML是可扩展标记语言, HTML里面的标签是预设好的,学习HTML实际上就是学习有哪些HTML标签 以及标签和标签之间的关系
CSS
●Cascading Style Sheet: 层叠样式表 , 作用: 美化页面
●在html页面中添加样式代码(引入方式),总共有三种方式:1.内联样式:在标签的style属性中添加样式代码,不能复用。2.内部样式:在head标签里面添加style,在标签体内写样式代码,仅可以在当前页面复用,不可以多页面复用3.外部样式:在单独的css样式文件中写样式代码,在html页面通过link标签引入,可以实现多页面复用,并且可以将html代码和css样式代码分离开
●三种引入方式的优先级:内联优先级最高,内部和外部优先级一样,后执行的覆盖先执行的。
CSS的三大特点
1.继承性:元素可以继承上级元素的文本和字体相关样式,部分标签自带效果不受继承影响,比如:超链接的字体颜色,h1-h6字体大小不受继承影响
2.层叠性:多个选择器有可能选择到同一个元素,如果添加的样式不同则全部层叠生效,如果样式相同则由优先级决定哪个生效
3.优先级:选择器作用范围越小优先级越高。
JavaScript
作用:给页面添加动态效果
语言特点:
●属性脚本语言,不需要编译直接执行
●基于面向对象
●属于弱类型语言强类型:int x=10;String name="张三";int y;弱类型:var x=10; var name="张三";
●安全性高:js语言只能访问浏览器内部的数据,不能访问浏览器以外的数据。
●交互性高:js语言可以直接嵌入到html页面中,可以让用户脱离后端服务器只在前段页面和页面内容进行交互。
在html页面中引入JavaScript代码
●内联:在标签的事件属性中添加js代码,当事件触发时执行事件:就是系统提供的一些特定时间点,点击事件:就是元素被点击时的时间点
●内部:在html页面中任意位置写Script标签,在标签体内写js代码
●外部:在单独的js文件中写js代码,在HTML页面中通过Script标签的src属性引入,使用最多的。好处是可以多个页面复用同一个文件,可以将html代码和js代码分离便于维护和升级。
JavaScript对象分类
1.内置对象:number/string/boolean等
2.浏览器相关对象BOM:Browser Object Model 浏览器对象模型
3.页面相关对象DOM: Document Object MOdel 文档对象模型
JQuery框架
●作用:一个JavaScript框架,轻量级的JS库,封装了JS,CSS,DOM,提供了一致的,简洁的API。js:var d=document.getElementById("id");jQuery:$("#id")
●引入方式:由于JQuery就是通过JavaScript语言所写,框架本身就是一个js文件,所以和引入普通的js文件一样通过Script标签的src属性引入到HTML页面即可。
●通过id获取元素对象,此时获取到的是jQuery对象和js对象不一样 $("#id")
js对象和jq对象互相转换
●js对象和jq对象不是一种对象,各自的方法不能混着调用1.js转jq:var jq=$(js);2.jq转js:var js=jq[0]; jq对象实际上就是一个数组,里面装着js对象
BootStrap
●此框架是目前比较流行的前端框架,基于HTML/css/JavaScript/jQuery实现, 由Twitter公司研发, 框架作用: 提高前端页面的开发效率
●工作原理: boostrap框架提供了n种常见的样式(提前写好了市面上常见的样式代码), 在开发页面的时候如果需要使用框架中所提供的效果只需要给元素添加相应的class,样式会自动添加到元素上,文档中提供了各种样式对应的class值.
响应式布局
●响应式布局就是不同的设备显示不同的样式
●媒体查询:这是Bootstrap中实现响应式布局的实现方式.、
MySql
数据库分类
1.关系型数据库:MySQL
●格式一致,都是表数据
2.非关系数据库:Redis
●格式灵活,可以是key,value形式,文档形式,图片形式
事务的四大特性
事务是指对系统进行的一组操作,为了保证系统的完整性,事务需要具有ACID特性,具体如下:
●原子性:事务的最小执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么全都不完成。
●一致性:执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的;
●隔离性:并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的
●持久性:一个事务被提交之后,它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
SQL分类
●DDL : 数据定义语言, 负责数据库和表相关的操作
●DML: 数据操作语言, 负责数据增删改查
●DQL: 数据查询语言, 只包括查询
●TCL: 事务控制语言,处理事务相关
●DCL: 数据控制语言, 负责控制用户权限相关
基础语法
1.数据库相关
●创建数据库:格式: create database 数据库名;
●查询所有数据库:show databases;
●查看数据库详情:show create database 数据库名;
●删除数据库:drop database 数据库名;
●使用数据库:use 数据库名;
2.表相关
●创建表:created table 表名(字段1名 类型,字段2名 类型);
●查询所有表:show tables;
●查询表详情:show create table 表名;
●查询表字段:desc 表名;
●删除表:drop table 表名;
●修改表名:rename table 原名 to 新名;
●添加表字段:最后面添加 alter table 表名 add 字段名 类型; 最前面添加 alter table 表名 add 字段名 类型 first; 在某字段后添加 alter table 表名 add 字段名 类型 after 字段名;
●删除表字段:alter table 表名 drop 字段名;
●修改表字段:alter table 表名 change 原名 新名 新类型;
3.DML数据操作语言(增删查改)
●插入数据
全表插入格式: insert into 表名 values(值1,值2);
值的数量和顺序必须和表字段数量和顺序一致
insert into person values('Tom',18);
指定字段插入格式: insert into 表名(字段1名,字段2名) values(值1,值2);
值的数量和顺序必须和指定的字段一致
insert into person (name) values('Jerry');
批量插入格式: insert into 表名 values(值1,值2),(值1,值2);
insert into person values('Lucy',20),('Lily',21);
insert into person(name) values('AAA'),('BBB');
插入中文问题
insert into person values('刘德华',20);
●查询数据:select 字段信息 from 表名 where条件;
●修改数据:update 表名set字段1名=值,字段2名=值 where条件;
●删除数据:delete from 表名 where条件;
主键约束 primary key
●主键:表示数据唯一性的字段称为主键
●主键约束:唯一且非空
●create table t1(id int primary key,name varchar(10));
主键约束+自增
●给字段添加自增后,赋值为null则触发自增
●自增规则:从历史最大值+1
●create table t2(id int primary key auto_increment,name varchar(10));
is null 和is not null
●如果查询字段的值为null,是is null 不为null 则使用 is not null
去重distinct
●select distinct job from emp;
and和or
●and类似java中的&&,查询多个条件同时满足使用and
●or类似java中的||,查询多个条件满足一个即可使用or
in关键字
●当查询的某个字段的值为多个值的时候使用in关键字
●select ename,sal from emp where sal in(3000,5000,8000);
●select*from emp where sal not in (3000,5000);
between x and y 关键字
●当查询某个字段的值在两者之间时使用
●select*from emp where sal between 2000 and 3000;
模糊查询
●% :代表0或多个未知字符
●_ :代表1个未知字符
●举例:
a以x开头 x%
b以x结尾 %x
c包含x %x%
d第二个字符是x _x%
e倒数第三个字符是x %x__
f第二个是x最后一个是y _x%y
g查询姓孙的员工信息select * from emp where ename like '孙%';
h查询工作中包含销售的员工姓名和工作select ename,job from emp where job like '%销售%';
i查询名字中以精结尾的员工姓名select ename from emp where ename like '%精';
j查询工作名称第二个字是序的员工姓名和工作名称.select ename,job from emp where job like '_序%';
排序
●让查询结果按照某个字段升序或者降序排序
●格式:order by 字段名 asc(默认,升序)/desc(降序)
分页查询
●如果查询数据只查询满足条件的一部分而不是全部的时候,使用limit分页查询
●格式:limit 跳过的条数,请求的条数(每页条数)
1查询所有员工中工资升序,只查询前3条数据(请求第一页数据 每页3条)select * from emp order by sal limit 0,3;
2查询所有员工中工资升序,查询第三页的3条数据(第三页就是跳过去2页 跳过去2*3条数据)select * from emp order by sal limit 6,3;
3查询员工表第四页的2条数据select * from emp limit 6,2;
4查询员工表中工资最高的员工信息select * from emp order by sal desc limit 0,1;
5查询3号部门工资最低的员工信息select * from emp where deptno=3 order by sal limit 0,1;
别名
●给查询的字段起一个别名
●select ename as '名字' from emp;
●select ename '名字' from emp;
●select ename 名字 from emp;
字段的数值计算
1查询每个员工的姓名,工资和年终奖(年终奖=5*工资)select ename,sal,5*sal 年终奖 from emp;
2查询每个员工的姓名,工资和涨薪5块钱之后的工资select ename,sal,sal+5 from emp;
聚合函数
●聚合函数就是对查询的多条数据进行统计查询
●统计的方式:1.平均值 2.最大值 3.最小值 4.求和 5.计数
1平均值avg(字段名)
○查询2号部门的平均工资select avg(sal) from emp where deptno=2;
○查询程序员的平均工资select avg(sal) from emp where job='程序员';
2最大值max(字段名)
○查询1号部门的最高工资select max(sal) from emp where deptno=1;
3最小值min(字段名)
○查询有领导的员工中的最低工资select min(sal) from emp where mgr is not null;
4求和sum(字段名)
○查询3号部门的工资总和select sum(sal) from emp where deptno=3;
5计数count(字段名) count(*)
○查询3号部门的人数select count(*) from emp where deptno=3;
○查询1号部门工资在2000到3000之间的员工人数select count(*) from emp where deptno=1 and sal between 2000 and 3000;
分组查询
●分组查询可以将某个字段相同数值的划分为一组,以每组为单位进行统计查询(聚合函数)
●在需求中出现每个xxx或每种xxx时,以xxx作为分组的字段 group by 字段查询每个部门的平均工资:select deptno,avg(sal)from emp group by deptno;
having
●where后面只能写普通字段的条件,不能写聚合函数的条件
●having:如果条件是聚合函数的条件使用having关键字,此关键字和分组查询结合使用,写在group by后面1.查询每个部门的平均工资,只查询平均工资大于2000的信息select deptno,avg(sal)from emp group by deptno having avg(sal)>2000;2.查询每个部门的平均工资,只查询工资在1000到3000之间的,并过滤掉平均工资低于2000的部门select deptno,avg(sal) from emp where sal between 1000 and 3000 group by deptno having avg(sal)>=2000;
各个关键字的位置
select 字段信息 from表名 where 普通字段条件 group by 分组字段 having 聚合函数条件
order by 排序字段 limit 跳过的条数,请求的条数;
子查询(嵌套查询)
●把一条SQL语句嵌入到另外一条SQL语句中,把查询语句的结果作为另一条SQL查询条件的值1.查询工资高于1号部门平均工资的员工信息select avg(sal) from emp where deptno=1;select*from emp where sal>( select avg(sal) from emp where deptno=1);
关联关系
创建表时,表与表之间存在的业务关系
●一对一:有AB两张表,A表中一条数据对应B表的一条数据,同时B表的一条数据也对应A表的一条数据
●一对多:有AB两张表,A表中一条数据对应B表的多条数据,同时B表的一条数据也对应A表的一条数据
●多对多:有AB两张表,A表中一条数据对应B表的多条数据,同时B表的一条数据也对应A表的多条数据
表与表之间建立关系
●通过一个单独的字段建立关系,这种建立关系的字段称为外键,外键的值通常指向另外一张表的主键值。
关联查询
●同时查询多张表数据的查询方式称为关联查询
●关联查询的查询方式:1.等值连接 2.内连接 3.外连接
1.等值连接
●格式:select*from A,B where 关联关系 and 其他条件;查询工资高于2000的员工姓名和对应的部门名select e.ename,d.dnamefrom emp e,dept dwhere e.deptno=d.deptno and e.sal>2000;
2.内连接
●内连接和等值连接查询到的结果试一样的,都是查询两张表的交集数据
●内连接格式:select*from A join B on 关联关系 where 其他条件查询工资高于2000的员工的姓名和对应的部门名select e.ename,d.dnamefrom emp e join dept don e.deptno=d.deptnowhere e.deptno in(1,2);
3.外连接
●查询一张表的全部数据和另外一张表的交集数据
●外连接分为左外连接和右外连接
●格式:select*from A left/right join B on 关联关系 where 条件;查询所有员工的姓名和对应的部门名select e.name,d.dnamefrom emp e right join dept don e.deptno=d.deptno;
关联查询总结
如果查询的是两张表的交集数据则使用等值连接或内连接(推荐),如果查询的是一张表的全部数据和另外一张表的交集数据则使用外连接。
JDBC
●Java DataBase Connectivity:Java数据库连接,
●学习JDBC主要学习的就是如何在Java代码中执行SQL语句
●JDBC实际上是Sun公司所提供的一套连接数据库的API(应用程序编程接口),JDBC接口中封装了一堆和数据库链接相关的抽象方法(只有方法声明没有方法实现)
●JDBC定义一套标准接口,即访问数据库的通用API,不同的数据库厂商根据各自数据库特点去实现这些接口。
连接数据库步骤
1.加载JDBC驱动程序
2.提供JDBC连接的URL
3.创建数据库连接
4.创建一个Statement
5.执行SQL语句
6.处理结果
7.关闭JDBC对象
Servlet
●Servlet是用于扩展web服务端软件业务功能的组件,每一种业务都需要对应的一个单独的Servlet
Web服务软件做了哪些事
1.负责建立底层的网络连接
2.负责将客户端请求的文件返回给客户端
3.web服务器又称为web容器,web容器负责装组件(Servlet),web服务软件通过解析请求路径,找到对应的Servlet做出响应
Servlet生命周期
加载类(加载阶段)--实例化阶段(为对象分配空间)--初始化阶段(为对象的属性赋值)--请求处理(服务阶段)--销毁
Servlet响应流程
●浏览器发出http://localhost:8080/servlet_1_1/HelloServlet请求,请求先有Tomcat拦截,并且获取地址中的/HelloServlet,然后拿着此路径去web.xml配置文件中找到对应的Servlet的完整类名(cn.tedu.HelloServlet),找到完整类名后通过反射技术,将该Servlet类实例化,然后Tomcat会调用Servlet的service方法.
浏览器发出请求的几种方式
1、在浏览器地址栏输入请求路径发出请求 Get
2、在超链接中写请求路径,点击超链接时发出请求 Get
3、通过页面中的form表单发出请求 Get/Post
Get:当浏览器地址栏/超链接/form表单指定get请求方式,这几种方式发出的请求都是Get请求
●请求参数在请求地址的后面,不建议传递敏感数据(密码)
●请求参数大小有限制,只能传递4k以内的数据
Post:只有在form表单中添加了method=post发出的请求才是post请求
●请求参数在请求体里面(用户不可见),相对get请求安全性更高
●请求参数没有大小限制
一般情况都是使用Get请求,只有涉及敏感信息或上传文件请求时,才是用Post请求
静态页面和动态页面
●静态页面:任何客户端,任何时间访问页面显示的内容都是一样的,称为静态页面
●动态页面:显示的内容会受某些因素的影响而改变,动态页面=从数据库中查询的数据+标签。
Thymeleaf框架作用
如果不使用此框架,我们服务器需要给客户端返回动态页面时,处理动态页面的代码需要全部写在Servlet中,动态页面部分包含很多页面标签,如果把标签代码写在Servlet中,首先代码书写效率低,而且Servlet中的代码量会暴增,不利于代码的维护,使用Thymeleaf框架可以将动态页面中的数据和页面分离开,在html页面中写一个模板页面,通过该框架可以将数据库里面查询到的数据和模板页面整合到一起,整合到一起后再把数据返回给浏览器,最终目的就是将页面相关代码从Servlet中分离写到单独的html页面中,提高开发效率,使Servlet类更易维护。
重定向
●写法:response.sendRedirect(request.getContextPath()+"/ListServlet");
●作用:通知浏览器往指定的路径发出请求
●执行过程:当执行此代码时,服务器会给浏览器返回一个302状态码和一个请求路径,当浏览器收到302状态码时,会立即向指定的路径再次发出请求。
转发和重定向的区别
转发是服务器行为,重定向是客户端行为。
●转发(RequestDispatcher):一个请求,一个响应1.转发不会改变浏览器的地址栏2.转发共享一个request3.转发只能在同一个web应用中使用
●重定向(sendRedirect):两个请求,两个响应1.重定向会改变浏览器的地址栏2.重定向不共享request3.可以重定向到任何URL
Cookie和Session
●为什么要使用Session和Cookie浏览器和服务器之间进行数据传输遵循的时HTTP数据传输协议,此协议属于无状态协议(一次请求对应一次响应,服务无法跟踪客户端的请求),通过cookie服务器可以给客户端设置一个标识,设置完之后客户端每次发出请求都会带着这个标识,从而识别客户端。但是Cookie是明文保存在客户端浏览器中,可以被客户端伪造造成完全隐患,这时Session的出现解决了此问题,Session是基于Cookie实现,但是数据保存在了服务器端,这样数据就不能像Cookie一样被伪造,从而提高了安全性。
●作用:Cookie和Session都是为了实现多个Servlet之间的数据共享而存在的
●Cookie:数据保存在客户端(浏览器),类似打孔式的会员卡1.保存时间:默认保存在浏览器内存中,浏览器关闭则数据删除,如果单独设置了时间,数据则保存到磁盘中,时间到之后再删除2.保存数据大小:每个cookie数据不能超过4K,而且只能保存字符串数据3.应用场景:需要长时间保存的数据使用cookie,如:记住用户名和密码
●Session:数据保存在服务器,类似银行卡1.保存时间:默认为半个小时左右,这个时间可以修改但是不建议,因为Session数据保存在服务器,如果用户量比较大非常占用服务器资源,Session只适合短时间的数据保存2.保存数据大小:没有大小限制,而且可以保存任意对象类型3.应用场景:短时间的数据存储和安全性要求高的数据,如:记住登录状态
同步请求和异步请求
1.同步请求:从服务器返回的内容包括html页面+数据,实现页面整体刷新
2.异步请求:从服务器返回的内容只有数据,实现页面局部刷新,异步请求通过Ajax发出
●前后端分离:整个网站都是使用的异步请求没有同步请求,服务端程序员不需要关心请求是浏览器发出的还是各种客户端发出的,不管是什么客户端一视同仁只给客户端返回数据,客户端接收到数据后自己处理显示相关内容,而目前通过Thymeleaf框架把数据和页面整合一起返回给浏览器的做法,在前后端分离则不再使用
Ajax
●Ajax即"Asynchronous Javascript And XML"(异步 JavaScript 和 XML),是指一种创建交互式,快速动态网页应用的网页开发技术。通过在后台与服务器进行少量数据交换,Ajac可以使用网页实现异步更新。在不不重新加载整个网页的情况下,对网页的某部分进行更新。
JSON
●轻量级数据封装格式,类似于XML
Vue
●用于构建用户界面的渐进式框架。频繁刷新页面数据时使用。
●优势1.轻量级,运行高效2.易上手,文档丰富3.不需要频繁的操作dom元素,它本身都是虚拟dom跟数据进行捆绑,降低了性能消耗4.提供丰富的组件支持5.双向数据绑定:变量的值改变影响页面的显示效果,页面中的值改变会影响元素的值
●在页面中引入vue.js框架文件即可使用
●主要应用在异步请求,得到数据后把数据显示在页面中,作用和Thymeleaf类似,是把数据填充到页面中,只不过Thymeleaf是服务端技术,而vue是客户端技术
Spring
1.Spring概述
Spring是个轻量级Java应用的开源开发框架。使用Spring开发可以将Bean对象,Dao组件对象,Service组件对象等交给Spring容器来处理,有效降低代码的耦合度,方便项目后期维护,升级,拓展。
缺点:Spring依赖反射,反射影响性能
2.Spring框架核心
●IOC控制反转:把创建对象的控制权交给Spring配置文件管理
●DI依赖注入:在需要对象时,由外部环境将依赖对象注入到组件中。
优点就是把应用的代码量降到最低,达到松散耦合度
注入方式:1.构造注入 2.Set注入 3.接口注入
3.AOP编程
面向切面,用于将那些与业务无关,但是却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块。这个模块就称为切面。减少系统中的重复代码,降低模块间的耦合度,同时提高了系统的可维护性。
AOP实现关键在于代理模式,AOP主要分为静态代理和动态代理。
4.Spring框架设计模式
●工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例
●单例模式:Bean默认为单例模式
●代理模式:Spring AOP
●模板模式
5.BeanFactory和ApplicationContext
BeanFactory和ApplicationContext是Spring两大核心接口,都可以当做Spring的容器。其中A是B的子接口。
BeanFactory:采用的是延迟加载行驶来注入Bean,使用某个Bean时,才对Bean进行加载实例化。
ApplicationContext:在容器启动时,一次性创建所有的Bean
6.Sping处理并发安全
采用ThreadLocal为每一个线程提供一个独立的变量副本,从而隔离多个线程对数据访问的冲突
@Configuration
Configuration是Spring提供的注解,标注@Configuration注解的类是配置文件,告诉Spring在运行期间创建哪些对象
@Bean
告诉Spring启动时候创建的具体的对象,返回值就是创建好的对象,这个对象是被Spring管理的对象,方法名是Bean的ID
getBeaan方法
●.getBean(DemoBean.class)按照类型获取对象,如果在Spring中只有一个DemoBean类型的对象,就会按照类型匹配找到,如果按照类型没有匹配到唯一的一个对象,就会报错!
●.getBean("BeanID",DemoBean.class)重载的getBean方法根据Bean的ID查找对象,如果找到就返回对象,否则抛出异常!
组件扫描方式创建Bean对象
在类上使用注解,Spring启动会自动根据注解创建Bean对象
●Component组件,在类上标注,在Spring配置类上开启组件扫描ComponentScan后,Spring会自动创建其类型的对象
●使用时候可以按照类型或者ID获得对象
关于组件扫描,Spring提供了功能相同的一组注解,方便标注不同功能的组件:
●@Component 标注通用组件
●@Service 标注业务层组件
●@Controller 标注控制器组件
●@Repository 标注持久层组件
Spring Bean对象的管理策略
单例:只有一个,立即初始化。类似冰箱,电视机,有家的时候立即买一个
原型:多个实例,按需要初始化,每次都是新的。类似吃西红柿鸡蛋
Bean对象的Scope(范围):单列原型(多个实例)
对象懒惰初始化:懒惰(按需初始化)和非懒惰(立即初始化)
Spring默认的对象管理策略是:单例非懒惰方式,也就是在Spring启动期间立即创建对象,并且在使用期间,始终使用同一个对象。
@Scope("prototype")开启"原型范围",会创建多个实例,每次调用getBean方法都会创建一个bean对象
@Lazy开启懒惰初始化方式,单例时候,默认规则是Spring启动时候,立即初始化。设置了@Lazy以后,就会在getBean时候初始化,如果不getBean,就不初始化
依赖注入
一个组件在运行期间需要使用另外一个组件,称为依赖,将被依赖的组件赋值给使用方称为依赖注入。
Spring在IoC的基础之上,实现了DI,也就是在管理对象的基础之上,可以按照依赖关系将对象适当组装(注入)
@Resource
●Spring根据Bean的ID和类型寻找合适Bean对象,如果找到ID一致,类型一样的对象就注入;
●如果ID没有匹配到就根据类型匹配唯一的Bean对象,如果匹配到就注入;
●如果ID,类型都没有匹配到,就抛出异常
set方法注入
@Resource不仅支持属性注入,还支持Set方法注入
●可以标注在属性上,对属性进行注入
●可以标注在setXXX方法,调用set方法注入属性
提供更多灵活性,可以执行Set方法中的逻辑算法,如果需Spring注入时候,执行set方法中算法,就将@Resource标注在set方法上,如果set方法中没有逻辑算法,经常标注在属性上。
@Autowired和@Resource
●@Resource是java提供的注解,Spring支持
●@Autowired Spring提供的注解
●这两个注解功能基本相同
●@Resource:Spring 5推荐使用先寻找Bean ID相同的组件,如果找到再比较类型,匹配就注入如果没有Bean ID匹配,则按照类型进行匹配,如果找到类型唯一的Bean,则注入,否则抛出异常
●@Autowired:Spring 5不推荐使用先寻找类型相同的唯一Bean组件,如果按照类型匹配到唯一的Bean组件就注入;如果按照类型匹配到多个Bean组件,则再按照Bean ID匹配ID,如果匹配上就注入,否则抛出异常
●这两个注解都采用了尽可能匹配成功的策略进行匹配注入属性
解耦
IoC/DI好处之一就是可以实现软件组件的解耦
解耦:将紧密耦合关系,变化为可配置的松散耦合关系,称为解耦
Spring MVC
MVC=Model(数据模型)+View(视图)+Controller(控制器)
●M-Model模型的职责是负责业务逻辑。包含两层:业务数据和业务处理逻辑。实体类,DAO,Service都属于模型层
●V-View视图的职责是负责显示界面和用户交互(收集用户信息)
●C-Controller控制器是模型层M和视图层V之间的桥梁,用于控制流程
概述
Spring MVC是一个轻量级的Web框架,通过模型-视图-控制器分离,将web层进行解耦,简化开发。
核心执行流程
DispatcherServlet:前端控制器 用来处理所有HTTP请求和响应
HandlerMapping:处理器映射器
Controller:控制器
ModelAndView
ViewServlet:视图解析器
●浏览器发出请求,交给前端控制器DispatcherServlet处理
●控制器通过HandlerMapping找到相应的Controller组件处理请求
●执行Controller组件约定方法处理请求,约定方法调用模型组件完成业务处理,之后返回一个MondelAndView对象,封装了处理结果数据和视图名称信息。
●控制器接收ModelAndView之后,调用ViewResolver组件,定位View并传递数据信息,生成响应界面结果。
常用注解
●@RequestMapping:用于处理请求url映射的注解,可用于类或方法上
●@RequestBody:注解实现接收hhtp请求的json数据,将json转换为java对象
●ResponseBody:注解实现将Controller方法返回对象转化为json对象响应给客户
MyBatis
概念
MyBatis是一个可以自定义SQL,存储过程和高级映射的持久层框架。一个半ORM(对象关系映射)框架。
ORM(Object Relational Mapping)
对象关系映射,是一种为了解决关系型数据库数据与简单Java对象映射关系的技术。
因为MyBaits在查询对象或关联集合对象时,需要手动编写SQL。所以称为半自动ORM映射工具。
全自动Hibernate
优点:
●SQL可写在XML里,解除SQL与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态SQL,并可重用
●消除JDBC大量冗余的代码,不需要手动开关连接
●很好的与各种数据库兼容(因为MyBaits使用JDBC来连接数据库,所以只要JDBC支持的数据库,MyBaits都支持)
●能够与Spring很好的集成
缺点:
●SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。
关于#{ }和${ }格式的占位符
●#{} 用于设置参数. 占位符,预编译处理,可防止SQL注入,提供系统安全性
●${} 用于SQL拼接. 拼接符,字符串替换,没有预编译处理,不能防止SQL注入。
SpringBoot
SpringBoot:Spring为了解决其框架繁琐的配置工作,而提供的一键配置,一次启动的整合工具
在IDEA创建SpringBoot项目,需要通过网站进行初始化
1https://start.spring.io主要网站
2https://start.aliyun.com备选网站
3https://start.springboot.io
若有收获,就点个赞吧