精简版:https://blog.csdn.net/qq_37722734/article/details/82380009
一、 面向对象编程讲解培训讲义
1. 什么是面向对象程序设计OOP(Object Oriented Programming) 4
2. 面向过程和面向对象的区别 4
3. 面向对象的三个基本特征,五大基本原则 4
4. 四种基本耦合(Generalization Couple) 5
5. 依赖 5
二、 java语法讲解
1. JAVA的标识符(这些是选择题) 6
2. 数据类型 7
3. 自动类型的转换 8
4. 算术运算符 8
5. 条件运算符 9
6. JAVA循环结构 (这节是关于for循环的程序题) 9
三、集合和泛型 10
四、 枚举讲解12
1. 枚举的定义 12
2. 枚举定制 12
3. 枚举工具类 12
五、 异常讲解培训讲义13
1. 异常事件的分类 13
2. Exception分类 14
3. 常见的异常 14
4. 处理异常 15
六、 Java反射与多线程15
七、 Java序列化IO文件培训讲义20
1. 什么是java序列化和反序列化: 20
2. 为什么序列化: 20
3. java序列化实现的必要条件: 20
八、 IO网络通讯22
1. BIO 22
2. NIO 23
3. AIO 24
4. TCP和UDP 24
5. UDP:用户数据报协议 25
6. TCP和UDP的区别 26
九、 ###答疑 26
十、 设计模式26
1. 设计模式分类 26
2. 六大原则 27
3. 创建型模式 29
十一、常见算法讲解 36
1. 什么是算法 36
2. 算法的分类 36
3. Java常用的排序算法实现原理以及代码实现 36
十二、 XML和JSON讲解 40
1.XML 40
2.DTD验证 41
3.JSON(主要考) 43
十三、 国际化&Tomcat44
十四、 web编程讲解培训讲义 48
1. 浏览器的主要组件 48
2. web工作原理 49
3. JSP 49
4. JS 49
5. AJAX 50
6. Cookie与本地存储 50
十五、前端技术讲解51
1. HTML 51
2. CSS 52
十六、数据基础知识 56
十七、 Spring cloud和FreeMark60
1. Spring cloud 60
1. Freemarker 61
2. http 62
十八、 编程规范_SQL性能问题_集群部署培训讲义63
1. JAVA编程规范 63
2. SQL常见性能问题 65
3. 集群部署 66
十九、 常用开发工具讲解67
面向对象是基于万物皆对的观点,把一个对象的静态特征和动态特征抽象成属性和方法,程序就是多个对象和互相之间的通信组成的。
面向过程,在开发过程中注重过程设计,用函数来表示过程,强调过程间的执行顺序。
面向对象,在开发过程中注重过程的复用性和扩展性。
三个基本特征:
封装:(抽象是把系统中需要处理的数据和在这些数据上的操作结合在一起,根据功能、性质和用途等因素抽象成不同的抽象数据类型。)是指利用抽象数据类型和基于数据的操作结合在一起,数据被保护在抽象数据类型的内部,系统的其他部分只有通过包裹在数据之外被授权的操作,才能与这个抽象数据类型进行交互。
继承:(子承父业),是指子类直接使用父类的属性和方法。
多态:(父子情深),通过父类来使用子类的方法,即同一消息可以根据发送对象的不同而采用多种不同的行为方式。
五大基本原则:
泛化耦合(Generalization Couple):由于泛化(继承)关系的存在,在两个有祖孙、父子关系的类间形成的一种逻辑关联。
聚合(Aggregation):一种弱的拥有关系,体现A对象可以包含B对象,但B对象不是A对象的一部分。
组合(Composition):一种强的拥有关系,体现了严格的部分和整体的关系,部分和整体具有一样的生命周期。
依赖(Dependency):由于逻辑上相互协作可能,而形成的一种关系。
程序世界与现实世界第一点区别:现实世界的依赖以对象为单位,程序世界的依赖以类为单位。(现实世界中对象间的依赖是以对象为单位的,这种依赖关系不会随着泛化过程而被泛化到类里面去;程序世界中对象间的依赖是以类为单位的,这种依赖关系会随着泛化过程而被泛化到类里面去。并且,只要两个类建立了依赖,那么两个类之间的所有对象都两两依赖了)
程序世界与现实世界第二点区别:程序世界里的对象没有选择权,程序世界里的对象不认识对象。
接口(Interface):对象行为的抽象。
接口的哲学意义:对客户类的保证,对服务类的约束。
“依赖注入容器(DI)”,也叫做“控制反转容器(IoC)”:依赖注入就是容器挑选符合接口的服务类为客户类提供服务。
关于Java标识符,需要注意:
(1)所有的标识符都应该以字母(A-Z或者a-z),美元符($)、或者下划线(_)开始
(2)首字符之后可以是字母(A-Z或者a-z),美元符($)、下划线(_)或数字的任何字符组合
(3)关键字不能用作标识符
(4)标识符是大小写敏感的
如:合法标识符:age、$salary、_value、__1_value
非法标识符:123abc、-salary
Java语言提供了八种基本类型。六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型。
(1)byte:数据类型是8位、有符号的,以二进制补码表示的整数;
最小值是 -128(-2^7);最大值是 127(2^7-1);默认值是 0;
byte 类型用在大型数组中节约空间,主要代替整数,因为 byte 变量占用的空间只有 int 类型的四分之一;
例子:byte a = 100,byte b = -50。
(2)short: 数据类型是 16 位、有符号的以二进制补码表示的整数
最小值是 -32768(-2^15); 最大值是 32767(2^15 - 1);默认值是 0;
Short 数据类型也可以像 byte 那样节省空间。一个short变量是int型变量所占空间的二分之一;
例子:short s = 1000,short r = -20000。
(3)int:数据类型是32位、有符号的以二进制补码表示的整数;
最小值是 -2,147,483,648(-2^31); 最大值是 2,147,483,647(2^31 - 1);
默认值是 0 ;
一般地整型变量默认为 int 类型;
例子:int a = 100000, int b = -200000。
(4)long:数据类型是 64 位、有符号的以二进制补码表示的整数;
最小值是 -9,223,372,036,854,775,808(-2^63);
最大值是 9,223,372,036,854,775,807(2^63 -1);默认值是 0L;
这种类型主要使用在需要比较大整数的系统上;
例子: long a = 100000L,Long b = -200000L。
"L"理论上不分大小写,但是若写成"l"容易与数字"1"混淆,不容易分辩。所以最好大写。
(5)float:数据类型是单精度、32位、符合IEEE 754标准的浮点数;
float 在储存大型浮点数组的时候可节省内存空间;
默认值是 0.0f;
浮点数不能用来表示精确的值,如货币;
例子:float f1 = 234.5f。
(6)double:数据类型是双精度、64 位、符合IEEE 754标准的浮点数;
浮点数的默认类型为double类型; 默认值是 0.0d;
double类型同样不能表示精确的值,如货币;
例子:double d1 = 123.4。
(7)char:类型是一个单一的 16 位 Unicode 字符;
最小值是 \u0000(即为0); 最大值是 \uffff(即为65,535);
char 数据类型可以储存任何字符;
例子:char letter = 'A';。
(8)boolean:数据类型表示一位的信息;
只有两个取值:true 和 false; 默认值是 false;
这种类型只作为一种标志来记录 true/false 情况;
例子:boolean one = true。
转换从低级到高级:
低 ------------------------------------> 高
byte,short,char—> int —> long—> float —> double
数据类型转换必须满足如下规则:
1. 不能对boolean类型进行类型转换。
2. 不能把对象类型转换成不相关类的对象。
3. 在把容量大的类型转换为容量小的类型时必须使用强制类型转换。
4. 转换过程中可能导致溢出或损失精度。
5. 浮点数到整数的转换是通过舍弃小数得到,而不是四舍五入。
前缀自增自减法(++a,--a): 先进行自增或者自减运算,再进行表达式运算。
后缀自增自减法(a++,a--): 先进行表达式运算,再进行自增或者自减运算。
条件运算符也被称为三元运算符。该运算符有3个操作数,并且需要判断布尔表达式的值。该运算符的主要是决定哪个值应该赋值给变量。
variable x = (expression) ? value if true : value if false
(1)For循环及增强for循环 吗吗
for(初始化; 布尔表达式; 更新) {
//代码语句
}
关于 for 循环有以下几点说明:
最先执行初始化步骤。可以声明一种类型,但可初始化一个或多个循环控制变量,也可以是空语句。
然后,检测布尔表达式的值。如果为 true,循环体被执行。如果为false,循环终止,开始执行循环体后面的语句。
执行一次循环后,更新循环控制变量。
再次检测布尔表达式。循环执行上面的过程。例子如下:
public class Test {
public static void main(String args[]) {
for(int x = 10; x < 20; x = x+1) {
System.out.println("value of x : " + x );
}
}
}
break与continue的区别
* break 主要用在循环语句或者 switch 语句中,用来跳出整个语句块。
* continue 适用于任何循环控制结构中。作用是让程序立刻跳转到下一次循环的迭代。
在 for 循环中,continue 语句使程序立即跳转到更新语句。
在 while 或者 do…while 循环中,程序立即跳转到布尔表达式的判断语句。
2.Set中不能包含重复的元素。List是一个有序的集合,可以包含重复的元素,提供了按索引访问的方式。
3.Map包含了key-value对。Map不能包含重复的key,但是可以包含相同的value。
4.Iterator,所有的集合类都实现了Iterator接口,这是一个用于遍历集合中元素的接口,主要包含以下三种方法:
(1)hasNext()是否还有下一个元素。
(2)next()返回下一个元素。
(3)remove()删除当前元素。
5.Collection接口存储一组不唯一,无序的对象。List接口存储一组不唯一,有序(插入顺序)的对象。Set接口存储一组唯一,无序的对象。
6.List是允许有重复元素,主要实现类包括ArrayList和LinkedList,前者是顺序表,后者是链表。
7.Set集合的特点:元素不重复,存取无序(元素插入的顺序和输出的顺序不一致)。
8.哈希表是通过hashCode和equals方法来共同保证哈希表的元素唯一性。
9.Map在存储的时候,将键值传入Entry,然后存储Entry对象
其中下面有HashMap,LinkedHashMap和TreeMap。
/*(成员变量类型)*/
private 泛型标识
}
}
泛型的类型参数只能是类类型(包括自定义类),不能是简单类型(int, short, long, byte, float, double, char, boolean)。
* values():返回 enum 实例的数组,而且该数组中的元素严格保持在 enum 中声明时的顺序。
* name():返回实例名。
* ordinal():返回实例声明时的次序,从0开始。
* getDeclaringClass():返回实例所属的 enum 类型。
* equals() :判断是否为同一个对象。可以使用 == 来比较enum实例。
注意:
枚举类型对象之间的值比较,可以使用==直接来比较值是否相等的,不是必须使用equals方法。
枚举类的名称一般以Enum结尾,比如ColorEnum等。
* Java枚举中允许定义属性和方法,但必须在枚举实例序列的最后一个分号后再添加。Java 要求必须先定义枚举实例在前面。
注意:枚举的构造方法默认且只能是private的。
* 父类Enum中的定义的方法只有toString方法没有使用final修饰,因此只能覆盖toString方法。
Java 中提供了两个方便操作enum的工具类——EnumSet 和 EnumMap。
* EnumSet 是枚举类型的高性能 Set 实现。它要求放入它的枚举常量必须属于同一枚举类型。
* EnumMap 是专门为枚举类型量身定做的 Map 实现。它只能接收同一枚举类型的实例作为键值,并且由于枚举类型实例的数量相对固定并且有限,所以 EnumMap 使用数组来存放与枚举类型对应的值。这使得 EnumMap 的效率非常高。EnumMap是是一种键为枚举类型的特殊的Map实现。所有的Key也必须是一种枚举类型,EnumMap是使用数组来实现的。
注意:
& 定义 enum 类型时候,如果是简单类型,那么最后一个枚举值后不用跟任何一个符号;但如果有定制方法,那么最后一个枚举值与后面代码要用分号';'隔开,不能用逗号或空格。
A)Error: Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。一般不编写针对性的代码进行处理。
B)Exception: 其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如:a.空指针访问b.读取不存在的文件c.网络连接中断
A)运行时异常
是指编译器不要求强制处置的异常。一般是指编程时的逻辑错误,是程序员应该积极避免其出现的异常。java.lang.RuntimeException类及它的子类都是运行时异常。
对于这类异常,可以不作处理,因为这类异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响。
B)编译时异常
是指编译器要求必须处置的异常。即程序在运行时由于外界因素造成的一般性异常。编译器要求java程序必须捕获或声明所有编译时异常。
对于这类异常,如果程序不处理,可能会带来意想不到的结果
A) java.lang.RuntimeException
1. ClassCastException
2. ArrayIndexOutOfBoundsException
3. NullPointerException
4. ArithmeticException
B) java.lang.ClassNotFoundException
C) java.lang.InterruptedException
D) java.io.FileNotFoundException
E) java.sql.SQLException
程序员通常只能处理Exception,而对Error无能为力
异常对象的生成:
异常处理三种方式:
1.throws方法头部抛出异常,交付给调用者处理,过程将一直继续下去,直到异常被处理,如果一个异常回到main()方法,并且main()也不处理,则程序运行终止。重写方法不能抛出比被重写方法范围更大的异常类型。
2.throw在方法内部抛出异常。自定义的异常类对象通过throw抛出。首先要生成异常类对象,然后通过throw语句实现抛出操作。抛出的异常必须是Throwable或其子类的实例。
3.通过try-catch-finally语句实现。try语句块可以伴随一个或多个catch语句,用于处理可能产生的不同类型的异常对象。finally语句和catch语句是任选的,finally无论是否发生异常,都无条件执行的语句。
5.NEW:新创建了一个线程对象,但还没有调用start()方法。
RUNNABLE :Java线程中将就绪(ready)和运行中(running)两种状态笼统的成为“运行”。线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得cpu 时间片后变为运行中状态(running)
BLOCKED :表线程阻塞于锁
TIMED_WAITING :线程具备cpu的执行资格,没有cpu的执行权;
WAITING:进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
TERMINATED:表示该线程已经执行完毕。
6.创建线程的第几种方式
继承Thread类
public class ThreadEx extends Thread{
@Override
public void run() {}}
实现Runnable接口
public class ThreadRun implements Runnable{
@Override
public void run() {}}
实现Callable
public class ThreadCall implements Callable
public Integer call() throws Exception {return null;}}
7.Lock API:
lock():获取锁,如果锁被暂用则一直等待
unlock():释放锁
tryLock(): 注意返回类型是boolean,如果获取锁的时候锁被占用就返回false,否则返回true
tryLock(long time, TimeUnit unit):比起tryLock()就是给了一个时间期限,保证等待参数时间
lockInterruptibly():用该锁的获得方式,如果线程在获取锁的阶段进入了等待,那么可以中断此线程,先去做别的
8.Lock和synchronized有以下几点不同:
Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;
synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发 生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;
Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;
通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。
Lock可以提高多个线程进行读操作的效率
9.JAVA反射:动态加载一个指定的类,并获取该类中的所有的内容。而且将字节码文件封装成对象,并将字节码文件中的内容都封装成对象,这样便于操作这些成员。
反射就是把java类中的各种成分映射成一个个的Java对象
反射的好处:大大的增强了程序的扩展性。
②编译时不知道名称,在运行时将类名作为字符串Class class = Class.forName(className);
class myObjectClass = MyObject.class;//得到Java类对象
String className = aClass.getName();//获取类名
int modifiers = aClass.getModifiers();//获取类修饰符
package = aClass.getPackage();//获取有关包的信息
Class superclass = aClass.getSuperclass();//获取超类
Constructor [] constructors = aClass.getConstructors();//访问构造函数
Class [] interfaces = aClass.getInterfaces();//获取接口列表
Method [] method = aClass.getMethods();//访问方法
Field [] method = aClass.getFields();//访问变量
Annotation [] annotations = aClass.getAnnotations();//访问注解
(1) //根据指定参数获得public构造器
Constructor getConstructor(Class[] params)
//获得public的所有构造器
Constructor[] getConstructors()
//根据指定参数获得public和非public的构造器
Constructor getDeclaredConstructor(Class[] params)
//获得public的所有构造器
Constructor[] getDeclaredConstructors()
(2)获取构造函数参数
Class [] parameterTypes = constructor.getParameterTypes();
(3)使用构造函数对象实例化对象
//获取以String作为参数的构造函数
构造函数= MyObject.class.getConstructor(String.class);
MyObject myObject =(MyObject)constructor.newInstance( “构造-ARG1”);
(1)Field [] fields = aClass.getFields();//获得类中所有public的方法
(2)Field field = aClass.getField(“someField”);//根据变量名得到public变量
Field getDeclaredField(String name)//根据方法名获得public和非public变量 Field[] getDeclaredFields()//获得类中所有的public和非public方法
(3)String fieldName = field.getName();//获取变量名称
(4)Object fieldType = field.getType();//获取变量类型
(5)获取和设置变量值
Object value = field.get(objectInstance);
field.set(objetInstance,value);
(1) 根据方法名和参数类型获得方法:
Method getMethod(String name, Class[] params)
(2) 获得所有的public方法:Method[] getMethods()
(3)根据方法名和参数类型,获得public和非public的方法:
Method getDeclaredMethod(String name, Class[] params)
(4) 获得所以的public和非public方法:Method[] getDeclaredMethods()
(5) 获取方法的参数:
Class [] parameterTypes = method.getParameterTypes();
(6)访问如下方法的返回类型:类returnType = method.getReturnType();
本节课程考察重点考察IO知识(熟记字节流和字符流图),考题类型:
选择题
简答题:
Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。
把对象转换为字节序列的过程称为对象的序列化。
把字节序列恢复为对象的过程称为对象的反序列化。
在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象。
该类必须实现 java.io.Serializable 对象。
该类的所有属性必须是可序列化的。如果有一个属性不是可序列化的,则该属性必须注明是短暂的( transient )
网络编程的基本模型是C/S模型,即两个进程间的通信。
服务端提供IP和监听端口,客户端通过连接操作向服务端监听的地址发起连接请求,通过三次握手连接,如果连接成功建立,双方就可以通过套接字进行通信。
传统的同步阻塞模型开发中,ServerSocket负责绑定IP地址,启动监听端口;Socket负责发起连接操作。连接成功后,双方通过输入和输出流进行同步阻塞式通信。
简单的描述一下BIO的服务端通信模型:采用BIO通信模型的服务端,通常由一个独立的Acceptor线程负责监听客户端的连接,它接收到客户端连接请求之后为每个客户端创建一个新的线程进行链路处理,处理完成后,通过输出流返回应答给客户端,线程销毁。即典型的一请求一应答通宵模型。
BIO的问题
该模型最大的问题就是缺乏弹性伸缩能力,当客户端并发访问量增加后,服务端的线程个数和客户端并发访问数呈1:1的正比关系,Java中的线程也是比较宝贵的系统资源,线程数量快速膨胀后,系统的性能将急剧下降,随着访问量的继续增大,系统最终就死-掉-了。
NIO我们一般认为是New I/O(也是官方的叫法),因为它是相对于老的I/O类库新增的(其实在JDK 1.4中就已经被引入了,但这个名词还会继续用很久,即使它们在现在看来已经是“旧”的了,所以也提示我们在命名时,需要好好考虑),做了很大的改变。但民间跟多人称之为Non-block I/O,即非阻塞I/O,因为这样叫,更能体现它的特点。而下文中的NIO,不是指整个新的I/O库,而是非阻塞I/O。
NIO提供了与传统BIO模型中的Socket和ServerSocket相对应的SocketChannel和ServerSocketChannel两种不同的套接字通道实现。
新增的着两种通道都支持阻塞和非阻塞两种模式。
阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好;非阻塞模式正好与之相反。
对于低负载、低并发的应用程序,可以使用同步阻塞I/O来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用NIO的非阻塞模式来开发。
Buffer是一个对象,包含一些要写入或者读出的数据。
在NIO库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的;在写入数据时,也是写入到缓冲区中。任何时候访问NIO中的数据,都是通过缓冲区进行操作。
缓冲区实际上是一个数组,并提供了对数据结构化访问以及维护读写位置等信息。
具体的缓存区有这些:ByteBuffe、CharBuffer、 ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer。他们实现了相同的接口:Buffer。
Selector是Java NIO 编程的基础。
Selector提供选择已经就绪的任务的能力:Selector会不断轮询注册在其上的Channel,如果某个Channel上面发生读或者写事件,这个Channel就处于就绪状态,会被Selector轮询出来,然后通过SelectionKey可以获取就绪Channel的集合,进行后续的I/O操作。
一个Selector可以同时轮询多个Channel,因为JDK使用了epoll()代替传统的select实现,所以没有最大连接句柄1024/2048的限制。所以,只需要一个线程负责Selector的轮询,就可以接入成千上万的客户端。
NIO 2.0引入了新的异步通道的概念,并提供了异步文件通道和异步套接字通道的实现。
异步的套接字通道时真正的异步非阻塞I/O,对应于UNIX网络编程中的事件驱动I/(AIO)。他不需要过多的Selector对注册的通道进行轮询即可实现异步读写,从而简化了NIO的编程模型。
TCP:是机器之间建立连接用的到的一个协议
面向连接的TCP:
1、“面向连接”就是在正式通信前必须要与对方建立起连接。比如你给别人打电话,必须等线路接通了、对方拿起话筒才能相互通话。
2、TCP(Transmission Control Protocol,传输控制协议)是基于连
接的协议,也就是说,在正式收发数据前,必须和对方建立可靠的连接。一个TCP连接必须要经过三次“对话”才能建立起来,其中的过程非常复杂,我们这里只做简单、形象的介绍,你只要做到能够理解这个过程即可。
3、我们来看看这三次对话的简单过程:
(1). 主机A向主机B发出连接请求数据包:“我想给你发数据,可以吗?”,这是第一次对话;
(2). 主机B向主机A发送同意连接和要求同步(同步就是两台主机一个在发送,一个在接收,协调工作)的数据包:“可以,你什么时候发?”,这是第二次对话;
(3). 主机A再发出一个数据包确认主机B的要求同步:“我现在就发,你接着吧!”,这是第三次对话。
三次“对话”的目的是使数据包的发送和接收同步,经过三次“对话”之后,主机A才向主机B正式发送数据。
4、TCP协议能为应用程序提供可靠的通信连接,使一台计算机发出的字节流无差错地发往网络上的其他计算机,对可靠性要求高的数据通信系统往往使用TCP协议传输数据。
面向非连接的UDP协议:
共有23种分为三大类:
创建者模式:创建者模式又叫建造者模式,是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
结构性模式:对象的结构,组成,以及对象之间的依赖关系。
行为模式:对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
其实还有两类:并发型模式和线程池模式。用一个图片来整体描述一下:
2.1开闭原则
原则:可以拓展扩展原代码,不能修改原代码。
优点:扩展性好,易于维护升级。
实现:多用接口、抽象类。
2.2里氏替换原则
原则:任何基类可以出现的地方,子类一定可以出现。
优点:对实现抽象化的具体步骤的规范。
实现:子类对父类的方法尽量不要重写和重载。
2.3依赖倒转原则
原则:开闭原则的基础,面向接口编程,依赖于抽象而不依赖于具体。
实现:用到具体类时,不与具体类交互,而与具体类的上层接口交互。
2.4接口隔离原则
原则:使用多个专门的接口比使用单一的总接口要好。
优点:避免接口污染(一个接口代表一个角色,不应当将不同的角色都交给一个接口。没有关系的接口合并在一起,形成一个臃肿的大接口,这是对角色和接口的污染。)
实现:一个类对另外一个类的依赖性应当是建立在最小的接口上的。
2.5迪米特法则(最少知道原则)
原则:一个类对自己依赖的类知道的越少越好。
优点:被依赖的类变化时,才能最小的影响该类。
实现:无论被依赖的类多么复杂,都应该将逻辑封装在方法的内部,通过public方法提供给外部。
2.6合成复用原则
原则:原则是尽量首先使用合成/聚合的方式,而不是使用继承。
优点:就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分。
实现:就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分。
3.1工厂模式
提供了创建对象的一种最佳方式。
优点:创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同
的接口来指向新创建的对象,用来解耦。
意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类工厂模式使其创建过程延迟到子类进行。
使用场景:日志记录器、数据库访问。
注意事项:复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
创建一个接口:
3.2抽象工厂
围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂它提供了一种创建对象的最佳方式。
优点:接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象,用来解耦。
使用场景:QQ换皮肤,一起换;生成不同的操作系统程序。
注意事项:产品族扩展,产品等级易拓展。
3.3单例模式
涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建
优点:这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象,用来减少垃圾对象和缓存用。
意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
使用场景:要求生产唯一序列号 、WEB 中的计数器、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。
注意事项:1.单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
4、getInstance() 方法中需要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入造成 instance 被多次实例化。
3.3.1懒汉式,线程安全
这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。
优点:第一次调用才初始化,避免内存浪费。
缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。
getInstance() 的性能对应用程序不是很关键(该方法使用不太频繁)。
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
3.3.2饿汉式---线程安全
这种方式比较常用,但容易产生垃圾对象。
优点:没有加锁,执行效率会提高。
缺点:类加载时就初始化,浪费内存。
它基于 classloader 机制避免了多线程的同步问题,不过,instance 在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用 getInstance 方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化 instance 显然没有达到 lazy loading 的效果。
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){
}
public static Singleton getInstance() {
return instance;
}
}
3.3.3双检锁/双重校验锁---线程安全
这种方式比较常用,但容易产生垃圾对象。
优点:没有加锁,执行效率会提高。
缺点:类加载时就初始化,浪费内存。
它基于 classloader 机制避免了多线程的同步问题,不过,instance 在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用 getInstance 方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化 instance 显然没有达到 lazy loading 的效果。
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
3.3.4登记式/静态内部类 ---线程安全
优点:这种方式能达到双检锁方式一样的功效,但实现更简单。
使用场景:对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。
它利用了 classloader 机制来保证初始化 instance 时只有一个线程,它跟第 3 种方式不同的是:第 3 种方式只要 Singleton 类被装载了,那么 instance 就会被实例化(没有达到 lazy loading 效果),而这种方式是 Singleton 类被装载了,instance 不一定被初始化。因为 SingletonHolder 类没有被主动使用,只有通过显式调用 getInstance 方法时,才会显式装载 SingletonHolder 类,从而实例化 instance。想象一下,如果实例化 instance 很消耗资源,所以想让它延迟加载,另外一方面,又不希望在 Singleton 类加载时就实例化,因为不能确保 Singleton 类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化 instance 显然是不合适的。这个时候,这种方式相比第 3 种方式就显得很合。
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
3.3.5枚举 ---线程安全
描述:这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。这种实现方式还没有被广泛采用
优点:它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
3.4适配器模式
两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能
优点:将目标类和适配者类解耦、增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性、灵活性和扩展性都非常好,符合开闭原则
意图:将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
使用场景:有动机地修改一个正常运行的系统的接口,这时应该考虑使用适配器模式。
注意事项:适配器不是在详细设计时添加的,而是解决正在服役的项目的问题。
3.5代理模式
创建具有现有对象的对象,以便向外界提供功能接口。,一个类代表另一个类的功能。
优点:
职责清晰
真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。
(2).代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了中介的作用和保护了目标对象的作用。
(3).高扩展性
组成:
抽象角色:通过接口或抽象类声明真实角色实现的业务方法。
代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
意图:为其他对象提供一种代理以控制对这个对象的访问。
使用场景:1、远程代理。 2、虚拟代理。 3、Copy-on-Write 代理。 4、保护(Protect or Access)代理。 5、Cache代理。 6、防火墙(Firewall)代理。 7、同步化(Synchronization)代理。 8、智能引用(Smart Reference)代理。
主义事项:
1.和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。
2.和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。
3.6策略模式
一个类的行为或其算法可以在运行时更改。创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
主要解决:在有多种算法相似的情况下,
优点:
1、算法可以自由切换。
意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
使用场景:
注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。
3.7责任链模式
每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
优点:实现了请求者与处理者代码分离:发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。提高系统的灵活性和可扩展行。
意图:意图:
避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
使用场景:
1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
3、可动态指定一组对象处理请求。
注意事项:在 JAVA WEB 中遇到很多应用。
算法,一般有5个特征:有穷性、确切性、输入、输出、可行性
按照算法的应用来分:算法可以分为基本算法、几何算法、加密/解密算法、查找算法、图标数据分析算法等。
按照算法的思路来分:算法可以分为递推算法、递归算法、穷举算法、分治算法等。
/**
* 交换数组元素
* @param arr
* @param a
* @param b
*/
public static void swap(int []arr,int a,int b){
arr[a] = arr[a]+arr[b];
arr[b] = arr[a]-arr[b];
arr[a] = arr[a]-arr[b];
}
1.插入排序
插入排序(Straight Insertion Sorting)的基本思想:在要排序的一组数中,假设前面(n-1) [n>=2] 个数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。
public static void insertionSort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
int j = i;
while (j > 0 && arr[j] < arr[j - 1]) {
swap(arr,j,j-1);
j--;
}
}
}
2.选择排序
遍历整个序列,将最小的数放在最前面。遍历剩下的序列,将最小的数放在最前面。重复第二步,直到只剩下一个数。
public static void selectSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int min = i;//每一趟循环比较时,min用于存放较小元素的数组下标,这样当前批次比较完毕最终存放的就是此趟内最小的元素的下标,避免每次遇到较小元素都要进行交换。
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[min]) {
min = j;
}
}
if (min != i) {
swap(arr,min,i);
}
}
}
3.冒泡排序
将序列中所有元素两两比较,将最大的放在最后面。将剩余序列中所有元素两两比较,将最大的放在最后面。重复第二步,直到只剩下一个数。
public static void bubbleSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
boolean flag = true;//设定一个标记,若为true,则表示此次循环没有进行交换,也就是待排序列已经有序,排序已然完成。
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
swap(arr,j,j+1);
flag = false;
}
}
if (flag) {
break;
}
}
}
4.递归算法
递归,就是在运行的过程中调用自己。递归必须要有三个要素:
当边界条件不满足时,递归前进;当边界条件满足时,递归返回。
public static long f(int n){
if(n == 1) // 递归终止条件
return 1; // 简单情景
return n*f(n-1); // 相同重复逻辑,缩小问题的规模
}
public static int fibonacci(int n) {
if (n == 1 || n == 2) { // 递归终止条件
return 1; // 简单情景
}
return fibonacci(n - 1) + fibonacci(n - 2); // 相同重复逻辑,缩小问题的规模
}
public static int getValue(int x, int y) {
if(y <= x && y >= 0){
if(y == 0 || x == y){ // 递归终止条件
return 1;
}else{
// 递归调用,缩小问题的规模
return getValue(x-1, y-1) + getValue(x-1, y);
}
}
return -1;
}
public static void moveDish(int level, char from, char inter, char to) {
if (level == 1) { // 递归终止条件
System.out.println("从" + from + " 移动盘子" + level + " 号到" + to);
} else {
moveDish(level - 1, from, to, inter); // 递归调用,缩小问题的规模
System.out.println("从" + from + " 移动盘子" + level + " 号到" + to);
moveDish(level - 1, inter, from, to); // 递归调用,缩小问题的规模
}
}
(1)XML 主要用于对有特定意义的数据保存或者传递,自带描述性并具有结构化的文本。
(2)HTML和XML区别:
html 用于展示数据,xml 用于存储或传递数据。
xml没有对标签进行定义,需要自己自行定义,而html的标签已定义。 xml具有自我描述性。
(3)XML的用途:
存储性 |
用于存储数据; |
传递性 |
用于数据传递; |
共享性 |
平台无关性,可随意在不同系统切换; |
数据有用性 |
自我解释,使得数据自身就说明意义。 |
(4)XML语法要求:
a.元素之间嵌套要正确
b.元素要有关闭,即使是空元素亦如此
c.元素一定要有根元素,且仅且有一个。
d.属性的值要加引号(单引号或双引号)
e.5个特殊字符的处理:
< |
< |
小于 |
> |
> |
大于 |
& |
& |
和号 |
' |
' |
单引号 |
" |
" |
引号 |
f.注释不能嵌套
g.区分大小写
h.xml中会保留空格.html中文本中多个空格会被压缩为1个空格对待
I.合理利用属性,不泛滥使用降低xml的可读性
(5)xml命名规则:
可使用数字字母和一些字符
不能用数字或标点符号开头
不能有空格
不能用xml开头
(1)DTD验证:
DTD, XSD就是对属性文件的约束。文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。
*------->内部声明
结构体-元素:
结构体-属性:
CDATA |
值为字符数据 (character data) |
(en1|en2|..) |
此值是枚举列表中的一个值 |
ID |
值为唯一的 id |
IDREF |
值为另外一个元素的 id |
IDREFS |
值为其他 id 的列表 |
NMTOKEN |
值为合法的 XML 名称 |
NMTOKENS |
值为合法的 XML 名称的列表 |
ENTITY |
值是一个实体 |
ENTITIES |
值是一个实体列表 |
NOTATION |
此值是符号的名称 |
xml |
值是一个预定义的 XML 值 |
*------->外部引用
(1)JavaScript Object Notation(JavaScript 对象表示法)
JSON 是存储和交换文本信息的语法,类似 XML,是轻量级的文本数据交换格式 JSON 比 XML 更小、更快,更易解析,更直观的了解数据。
JSON 目前是前后端分离后数据传送的最基本最常见的交换格式
(2)JSON对象类型:
:号前面永远为 String字符串类型
:号后面可以为(string number object array true false null)
(3)JSON前台应用:
JSON在传递过程中,实质是以String的形式在传递,在到达目的地后,由给定的格式来声明自己是json,进而被解析(ajax的数据接收dataType:json),数据传递(application/json)
转String:var strUser = JSON.stringify(user);
转对象:var user = JSON.parse(strUser);
注意:json的key值必须要带有双引号才能被解析,不然解析败,单引号可以用eval()解析。
√ {“name”:“张三”}
× {‘name’:“张三”} × {name:“张三”}
(1)国际化:I18N,G11N,L10N
(2)目录结构:
英文环境资源文件:MessageResource_en.properties
中文环境资源文件:MessageResource_zh.properties
资源包的基名:MessageResource.properties
//根据资源包基名和语言环境加载对应的语言资源文件
ResourceBundle bundle =
ResourceBundle.getBundle("cn.itcast.resource.MessageResource",Local.CHNIA)
(3)web服务器:Web服务器可以解析HTTP协议,当Web服务器接收到一个HTTP请求,会返回一个HTTP响应。
(4)什么是JavaEE(了解)
JDBC(Java Database Connectivity)
JNDI(Java Name and Directory Interface)
EJB(Enterprise JavaBean)
RMI(Remote Method Invoke)
Java IDL/CORBA
JSP(Java Server Pages)
Java Servlet
XML(Extensible Markup Language)
JMS(Java Message Service)
JTA(Java Transaction Architecture)
JTS(Java Transaction Service)
JavaMail
JAF(JavaBeans Activation Framework)
(5)常见web服务器种类
Web服务器根据对javaEE支持的能力分为两大类
一、 JavaEE服务器(应用服务器) IBM公司 WebSphere BEA公司 WebLogic JBoss公司 JBoss Apache组织 Geronimo(免费WebSphere社区版)
二、 Web容器(servlet/jsp容器) Apache组织 Tomcat Webtide公司 jetty
(6)Tomcat是什么:Tomcat 是由 Apache 开发的一个 Servlet 容器,实现了对 Servlet 和 JSP 的支持,并提供了作为Web服务器的一些特有功能。
(7)tomcat部署web应用的4种方法
在Tomcat中有四种部署Web应用的方式,简要的概括分别是:
1.利用Tomcat自动部署
2.利用控制台进行部署
3.增加自定义的Web部署文件 (%Tomcat_Home%\conf\Catalina\localhost\AppName.xml)
4.手动修改%Tomcat_Home%\conf\server.xml文件来部署web应用
(此方法即打开%Tomcat_Home%\conf\server.xml文件并在其中增加以下元素:
(8)Tomcat的目录结构:
/bin - Tomcat 脚本存放目录(如启动、关闭脚本)。
*.sh 文件用于 Unix 系统;
*.bat 文件用于 Windows 系统。
/conf - Tomcat 配置文件目录。
/logs - Tomcat 默认日志目录。
/webapps - webapp 运行的目录。
(9)web工程发布目录结构:
(10)Tomcat的配置文件: (加粗)
server.xml: Tomcat的主配置文件,包含Service, Connector, Engine, Realm, Valve, Hosts主组件的相关配置信息;
web.xml:遵循Servlet规范标准的配置文件,用于配置servlet,并为所有的Web应用程序提供包括MIME映射等默认配置信息;
tomcat-user.xml:Realm认证时用到的相关角色、用户和密码等信息;Tomcat自带的manager默认情况下会用到此文件;在Tomcat中添加/删除用户,为用户 指定角色等将通过编辑此文件实现;
catalina.policy:Java相关的安全策略配置文件,在系统资源级别上提供访问控制的能力; catalina.properties:Tomcat内部package的定义及访问相关控制,也包括对通过类装载器装载的内容的控制;Tomcat在启动时会事先读取此文件的相关设置; logging.properties: Tomcat通过自己内部实现的JAVA日志记录器来记录操作相关的日志,此文件即为日志记录器相关的配置信息,可以用来定义日志记录的组件级别以及日志文件的存在位置等;
context.xml:所有host的默认配置信息;
(11)一次完整的http请求:
(13)http响应格式:状态行、响应头、空行、消息体
(14)Tomcat的元素:(加粗)
@server:顶层元素,代表整个Catalina Servlet容器,可以包含一个或者是多个Service;
@Service:连接器元素,它由一个或者多个Connector和一个Engine组成,负责处理所有的Connector所获得的客户请求。这些 Connector共享一个Engine。
@Connector: 一个Connector将在某个指定端口上侦听客户请求,并且将获得的请求交给Engine来处理,再从Engine上或的回应然后返回给客户端。
@Engine: 容器类元素,可以包含多个Virtual Host元素,每个虚拟主机都有一个域名,当Engine获得一个Connector发出的 HTTP请求时,它吧请求匹配到某个Host上,然后把该请求交给该Host来处理,Engine有一个默认的虚拟主机 Localhost。当请求无法匹配到任何一个Host来处理,将交给默认的Host来处理。
@Host: 定义一个虚拟主机,每个虚拟主机都和某个DNS相匹配,每个虚拟主机下都可以部署多个web应用程序。当Host获得一 个请求时,将该请求匹配到某个Context上,然后将该请求交给该Context处理。所有无法与Context匹配的都与path=“”的默认Context匹配。
@Context: Context代表一个虚拟主机上运行的一个应用,一个Context对应一个web应用程序,一个Context包含多Servlet。
(15)Tomcat配置虚拟机:
Tomcat可以通过修改本地虚拟主机和修改本地DNS的方式下,实现访问主流网站:www.sina.com而跳转到自己配置的界面。
用户界面,浏览器引擎 渲染引擎 网络UI后端JS解释器 数据存储
JSP全称Java Server Page,直译就是“运行在服务器端的页面”。上面已经介绍过,我们可以直接在JSP文件里写HTML代码,这和在HTML文件里写HTML/CSS/JS是一模一样的。除此之外,我们还可以把Java代码内嵌在JSP页面中,很方便地把动态数据渲染成静态页面。服务器在响应前,会自动帮我们拼接好HTML代码(静态页面)响应给浏览器。也就是说JSP是运行在服务器端,但最终发给客户端的都已经是转换好的HTML静态页面(在响应体里)。
即:JSP = HTML + Java片段(各种标签本质上还是Java片段)
JavaScript是一个轻量级的,解释型编程语言的面向对象的功能,使能够构建成静态的HTML页面的交互性。在用户浏览网页时,被浏览器的解释器解释并执行
JS可以用来做什么?
使网页具有交互性,验证用户输入的正确性,设置cookie,丰富的接口与后台交互
JS如何使用?
使用标签,放在head中或者html中,也可以设置src属性引入外部文件
AJAX是什么?
AJAX = 异步 JavaScript 和 XML。
AJAX 是一种用于创建快速动态网页的技术。
通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。
原理:
Ajax运行原理:客户端响应某个事件,创建xmlHttpRequest实例对象,然后发送httpRequest请求,通过internet,到达服务端,服务端加工httpRequest请求,然后返回response对象和请求数据,再通过internet发送到客户端,客户端使用js解析加工数据,然后更新页面内容.
Get和post请求的区别:
(1)使用Get请求时,参数在URL中显示,而使用Post请求,则不会显示出来;
(2)Post传输的数据量大,可以达到2M,而Get方法由于受到URL长度的限制,只能传递大约1024字节.
(3)Get请求请求需注意缓存问题,Post请求不需担心这个问题;
(4)Post请求必须设置Content-Type值为application/x-form-www-urlencoded;
(5)发送请求时,因为Get请求的参数都在url里,所以send函数发送的参数为null,而Post请求在使用send方法时,却需赋予其参数;
(6)GET方式请求的数据会被浏览器缓存起来,因此其他人就可以从浏览器的历史记录中读取到这些数据,例如账号和密码等。在某种情况下,GET方式会带来严重的安全问题。而POST方式相对来说就可以避免这些问题。
Cookie是什么?
浏览器和服务器之间有约定:通过使用cookie技术来维护应用的状态。
1、创建:Cookie是可以被Web服务器设置的字符串,并且可以保存在浏览器中。
2、发送:当浏览器访问了页面1时,web服务器设置了一个cookie,并将这个cookie和页面1一起返回给浏览器,
3、保存:浏览器接到cookie之后,就会保存起来,
4、发送:在它访问页面2的时候会把这个cookie也带上,Web服务器接到请求时也能读出cookie的值,根据cookie值的内容就可以判断和恢复一些用户的信息状态。
本地存储的优缺点:
① localstorage大小限制在500万字符左右,各个浏览器不一致
② localstorage在隐私模式下不可读取
③ localstorage本质是在读写文件,数据多的话会比较卡(firefox会一次性将数据导入内存,想想就觉得吓人啊)
④本地存储分为sessionstorage和localstorage,两个的区别是临时保存和永久保存;
1.定义:超文本标记语言HTML( HyperText Markup Language 的缩写)是一种用于创建网页的标准标记语言。HTML 运行在浏览器上,由浏览器来解析
2.网页结构:
……
3.标签显示结构: