JDK是整个JAVA的核心,包括了Java运行环境JRE,一堆Java工具和Java基础的类库。通过JDK开发人员将源码文件(java文件)编译成字节码文件(class文件)。
JRE是Java运行环境,不含开发环境,即没有编译器和调试器。将class文件加载到内存准备运行
栈:调用方法将在栈中开辟内存,称为入栈(压栈)。
栈内存存放基本类型值和引用数据类型的地址。
栈内存中的数据,没有默认初始化值,需要手动设置。
方法调用完成,栈内存立即释放,称为出栈(弹栈)
堆:用于存放使用new创建的对象或数组。
所有的对象都有内存地址值。
数据都有默认初始化值。
堆内存中的对象不再被指向时,JVM启动垃圾回收机制,自动清除。
方法区:与Java堆一样,是各个线程共享的内存区域。
存储已被Java虚拟机加载的类信息、常量、静态变量、以及编译器编译后的代码等。
GC是垃圾收集的意思。是指JVM用于释放那些不再使用的对象所占用的内存。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。
Java有了GC,就不需要程序员去人工释放内存空间。
一般情况下java中对象可被回收的前提是:该对象不再被引用。然后垃圾回收器在回收的时候便会把这个对象清理掉
会存在,
内存泄漏是指程序分配的堆内未释放或无法释放的现象。
原因:长生命周期的对象持有短生命周期对象的引用。
java中内存泄露的发生场景:全局的集合变量、不正确的单例模式的使用
1、静态集合类引起内存泄漏;
2、当集合里面的对象属性被修改后,再调用remove()方法时不起作用;
3、监听器
4、各种连接
5、内部类和外部模块的引用
6、单例模式
具体说明请自行查看原文,链接:https://blog.csdn.net/c_royi/article/details/79527518
封装 有选择的隐藏和暴露一些数据和方法
继承 子类可以直接实现父类中的方法,有选择的扩展
多态 调用同一个方法展示出来不同的方式。
抽象 把共同的特性抽取到一个类中"
OOP(object oriented programming),即面向对象编程
面向对象具有四大特性,分别是
1.抽象:将一些事物的共性抽离出来归为一个类。
如对于动物,具有生命体征、活动能力等区别于其它事物的共同特征
2.封装:有选择地隐藏和暴露数据和方法
比如有U盘这个类,我希望隐藏内部组成和实现,只暴露USB接口以供使用
3.继承:子类可以直接使用父类的部分数据和方法,可以有选择的扩展
比如鸟是动物,但鸟扩展了飞行的能力。
4.多态:同一类的对象调用相同方法可以表现出不同的行为
比如动物实现了say()方法,猴子、马等动物重写了say()方法来表现不同的交流语言。"
Java中,靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象,而程序调用的方法在运行期才动态绑定,就是引用变量所指向的具体实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变量的类型中定义的方法。
方法重写(overriding):继承
1、也叫子类的方法覆盖父类的方法,要求返回值、方法名和参数都相同。
2、子类抛出的异常不能超过父类相应方法抛出的异常。(子类异常不能超出父类异常)
3、子类方法的的访问级别不能低于父类相应方法的访问级别(子类访问级别不能低于父类访问级别)
方法重载(overloading): 当前类
重载是在同一个类中的两个或两个以上的方法,拥有相同的方法名,但是参数却不相同,方法体也不相同,最常见的重载的例子就是类的构造函数
Constructor(构造器)不能被继承,所以不能被override(重写),但是可以被overloading(重载)。
抽象类是什么?含有abstract修饰符的class即为抽象类。
特点:
\1. 不能创建的实例对象
\2. 可以有抽象方法
\3. 可以有构造方法,但构造方法不能是抽象的
\4. 抽象方法必须子类进行实现,如果子类只实现部分方法,该子类必须是抽象的。
接口是什么?含有interface修饰符的就是 。
特点:
\1. 接口中的所有方法都必须是抽象的
\2. 接口中的方法定义默认为public abstract类型
\3. 接口中的成员变量类型默认为public static final
区别是什么
\1. 单继承多实现:一个类可以实现多个接口,但只能继承一个抽象类。
\2. 构造方法:抽象类可以有构造方法,接口中不能有构造方法。(JDK7之前)
\3. 变量:抽象类中可以有普通成员变量,接口中只有常量。
\4. 方法:抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
\5. 修饰符:抽象类中的抽象方法可以使用public和protected进行修饰,但接口中的抽象方法只能使用public abstract修饰。
\6. 静态方法:抽象类中可以包含静态方法,接口中不能包含静态方法
\7. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。
(注:JDK1.8新特性,接口可以有默认方法和静态方法)
l 接口的定义
package com.itheima.anno;
public interface TestInterface {
//成员变量默认修饰:public static final
public String *str* = “jack”;
public static final String *str2* = “rose”;
//方法默认修饰:public abstract
void demo01();
public abstract void demo02();
}
l 抽象类
package com.itheima.anno;
public abstract class TestAbstract {
//抽象方法
public abstract void demo();
//普通方法
public void demo02(){
System.*out*.println(“abc”);
}
}
class Son extends TestAbstract{
//抽象方法必须子类进行实现
@Override
public void demo() {
}
}
//如果子类只实现部分方法,该子类必须是抽象的。
abstract class Son2 extends TestAbstract{
}
l 单继承多实现
package com.itheima.anno;
//单继承多实现
public class Hello extends C implements A,B {
@Override
public void b() {
}
@Override
public void a() {
}
@Override
void c() {
}
}
interface A {
void a();
}
interface B {
void b();
}
abstract class C {
abstract void c();
}
子类继承抽象类时,构造函数不会被覆盖。
而且,在实例化子类对象时首先调用的是抽象类中的构造函数再调用子类中的。
在这个阶段初始化抽象类字段或执行其它与子类相关的代码
Java的类是单继承的,即每个类只能继承一个类。
但是,Java中接口支持多继承,即一个接口可以继承多个接口
1.整型:byte(1个字节)、short(2个字节)、int(4个字节) 、long(8个字节)
2.浮点型:float(4个字节)、double(8个字节)
3.字符型:char(2个字节)
4.布尔型:boolean(1个字节)
byte的取值范围为-128~127(-2的7次方到2的7次方-1)
short的取值范围为-32768~32767(-2的15次方到2的15次方-1)
int的取值范围为(-2147483648~2147483647)(-2的31次方到2的31次方-1)
long的取值范围为(-9223372036854774808~9223372036854774807)(-2的63次方到2的63次方-1)
单精度:float 3.402823e+38 ~ 1.401298e-45
双精度:double 1.797693e+308~ 4.9000000e-324
char:0-65535"
1.int是Java的数据类型之一,Integer是Java为int提供的封装类;
2.int的初始化值为0,而Integer的初始化值为null。
数值提升是指数据从一个较小的数据类型转换成为一个更大的数据类型。
byte,char,short值会被转化成int类型。需要的时候int类型也可能被提升成long。long和float则有可能会被转换成double类型。
显示转换:就是强制类型转换,就是大范围的变量能够接受小范围的数据;父类转换为子类。
隐式转换:就是自动类型强转,数字表示范围小的数据类型可以自动转换成范围大的数据类型
Integer.parseInt()
“++i”:先自增,后赋值
“i++”:先赋值,后自增
“+”":a+=b -> a = a+b
& 位运算,求2个二进制数的与。也可以进行逻辑运算,表达式左边为false,表达式右边继续执行。
&& 逻辑运算符,表达式左边为false,整个表达式结果为false,因此表达式右边不执行。此现象称为逻辑短路。
1.this表示对象本身,用来调用当前类里的属性、方法,也可以调用从父类继承而来的未被重写、非私有的方法;
super表示当前对象类的父类对象部分,用来调用父类里的属性、方法;
2.this和super用来调用构造器方法
不同点:super()从子类中调用父类的构造方法,this()在同一类内调用其它构造方法。
相同点:super()和this()都必须在构造函数的第一行进行调用,否则就是错误的
==比较的是值
== 如果比较的是基本数据类型,比较的则是变量值
== 如果比较的为引用数据类型,比较的则是地址值
equals比较的是引用数据类型
如果没有重写hashCode和equals方法,比较的是地址值。因为Object的equals方法中使用是==。
如果重写hashCode和equals方法,则比较的重写后的规则。
例如:两个String字符串比较时:比较的是内容。因为String底层重写了equals方法进行内容的比较。
l 等号==
package com.czxy.changgou3.eq;
import lombok.Data;
/*
* Created by liangtong.
*/
* public class TestEq {
public static void main(String[] args) {
// 1 == 比较的是值
// 1.1 *基本数据类型:数值
* int a = 1;
int b = 1;
System.*out*.println( a == b ); //true
// 1.2 *引用数据类型:地址值
* Student s1 = new Student();
Student s2 = s1;
System.*out*.println( s1 == s2 ); *//true
* Student s3 = new Student();
System.*out*.println(s2 == s3); *//false
* }
}
@Data
class Student {
private String name;
}
l equals 默认
package com.czxy.changgou3.eq;
/*
* Created by liangtong.
*/
* public class TestEq2 {
public static void main(String[] args) {
*// 2 equals
* Student2 s1 = new Student2();
Student2 s2 = s1;
Student2 s3 = new Student2();
*// Object.equals**方法,默认使用 ==
* System.*out*.println( s1.equals(s2) ); *//true
* System.*out*.println( s2.equals(s3) ); *//false
* }
}
class Student2 {
private String name;
}
l 重写 equals
package com.czxy.changgou3.eq;
/*
* Created by liangtong.
*/
* public class TestEq2 {
public static void main(String[] args) {
*// 2 equals
* Student2 s1 = new Student2(“jack”); // *空、“rose”
* Student2 s2 = s1;
Student2 s3 = new Student2(“jack”); // *空
// Object.equals**方法,默认使用 ==
* System.*out*.println( s1.equals(s2) ); *//true
* System.*out*.println( s2.equals(s3) ); *//true
* }
}
class Student2 {
private String name;
public Student2() { *//**无参构造
* }
public Student2(String name) { *//**有参构造
* this.name = name;
}
*//name**如果相同返回true
* @Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student2 student2 = (Student2) o;
**return name** != **null** ? **name**.equals(student2.**name**) : student2.**name** == **null**;
}
@Override
public int hashCode() {
return name != null ? name.hashCode() : 0;
}
}
l 作用:hashCode()方法和equals()方法的作用一样,对比两个对象是否相等
l 区别:
n equals() 比较对象很多内容,比较全面,耗时较多,效率就比较低。绝对可靠。
u equal()相等的两个对象,hashCode()肯定相等
n hashCode() 只比较一个hash值,效率就比较高。不可靠。
u hashCode()相等的两个对象他们的equal()不一定相等
l 比较原则:
n 首先,比较hashCode(),如果不相同,两个对象肯定不相同。
n 如果hashCode()相同,再比较equals
l 目的:既能大大提高了效率也保证了对比的绝对正确性
正则(扩展 如:s.replaceAll(“[^0-9]“,”"),这样非数字就全部去除了,只保留数字了
String:String类被final修饰不能被继承,String内部char[]被final修饰,字符串内容无法被修改
StringBuffer:可变字符串、效率低、线程安全;
StringBuilder:可变字符序列、效率高、线程不安全;
java中4中修饰符分别为public、protect、default、private
访问权限 类 包 子类 其他包
public ∨ ∨ ∨ ∨
protect ∨ ∨ ∨ ×
default ∨ ∨ × ×
private ∨ × × ×"
静态初始化只在Class对象首次被加载的时候进行一次。
成员变量初始化,在new对象的时候被初始化,在构造函数的隐式三步其中一步进行初始化,初始化完成之后才会执行构造器中的代码
static关键字为静态的
1.用来修饰成员变量,静态变量所有对象共享;
2.用来修饰成员方法,可通过“类名.方法名”的方式调用,常用于工具类;
3.静态代码块,在类被加载的时候就会被执行的代码块;
final关键字
1.用来修饰数据,包括成员变量和局部变量,该变量只能被赋值一次且它的值无法被改变。对于成员变量来讲,必须在声明时或者构造方法中对它赋值;
2.修饰方法,表示该方法无法被重写;
3.修饰类,表示该类无法被继承。
1.通过全路径类名的字符串获取对象,Class clazz = Class.forName("“com.czxy.pojo.User”")
2.通过类名加.class获取对象,Class clazz = User.class
3.通过对象来获得类对象,Class clazz = new User() .getClass();
4.通过子类的实例获取父类的类对象,
User cn = new User();
Class userClass = cn.getClass();
Class subUserClass = userClass.getSuperclass(); "
1.使用new关键字
2.使用反射创建对象
3.使用Clone的方式创建:用clone方法创建对象并不会调用任何构造函数。
4.使用反序列化:反序列化时,JVM创建对象并不会调用任何构造函数。"
1, clone()不会调用构造方法;new会调用构造方法。
2, new对象时根据类型确定分配内存空间的大小, clone是根据原对象分配内存
1.为什么要克隆?
①方便,克隆的对象可能包含一些已经修改过的属性,而new出来的对象的属性都还是初始化时候的值,所以当需要一个新的对象来保存当前对象的“状态”使用clone方式很方便;
②速度快,clone方法最终将调用JVM中的原生方法完成复制也就是调用底层的c++代码,所以一般使用clone方法复制对象要比新建一个对象然后逐一进行元素复制效率要高。
2.实现clone
① 实现Cloneable接口并重写Object类中的clone()方法;
② 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。对象序列化后写入流中,再从流中读取,生成新的对象,新对象和原对象之间也是完全互不影响的。
l Cloneable接口和Serializable接口,统称标记接口。没有具体的方法,仅仅只是提供给JVM使用。
n Cloneable接口,准备用于对象克隆的。
n Serializable接口,准备用于序列化和反序列化
u 序列化:将内存中的对象,保存到硬盘中。
u 反序列化:从硬盘中保存对象,加载到内存。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-16uQzepY-1598857977957)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg)]
经过序列化和反序列化后,对象不再是同一个对象,对外展示效果就是克隆。
l 浅克隆是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象。
l 深克隆不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。
l 举例:学生类,含老师类
@Data
public class Student implements Cloneable {
private Integer id;
private String name;
private Teacher teacher;
n 浅克隆:克隆学生时,不克隆老师。
public Object clone() throws CloneNotSupportedException {
*//**浅客隆
* return super.clone();
}
n 深克隆:克隆学生时,同时克隆老师。
@Override
public Object clone() throws CloneNotSupportedException {
*//*深克隆
//1 *克隆学生
* Student student = (Student)super.clone();
//2 *克隆老师
* Teacher teacher = (Teacher)student.getTeacher().clone();
student.setTeacher(teacher);
return student;
}
是值传递, Java中只有值传递,没有引用传递概念
(1)java.lang.NullPointerException 【空指针异常】
(2)java.lang.ClassNotFoundException 【类找不到异常】
(3)java.lang.NumberFormatException 【数字格式化异常】
(4)java.lang.IndexOutOfBoundsException 【数组角标越界异常】或 【数组索引越界异常】
(5)java.lang.IllegalArgumentException 【非法参数异常】
(6)java.lang.ClassCastException 【类型转换异常】
(7)java.lang.NoClassDefFoundException 【类未定义异常】
(8)SQLException 操作数据库异常 【SQL异常】
(9)java.io.IOException 【IO异常】
(10)java.lang.NoSuchMethodException 【没有匹配方法异常】
package com.czxy.changgou3.exception;
import java.io.*;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.List;
/*
* Created by liangtong.
*/
* public class TestException {
public static void main(String[] args) throws IOException, ClassNotFoundException {
/**—1-4 运行时异常:只有右键运行才可以查看异常----*/
//1 空指针异常 NullPointerException
// String str = null;
// System.out.println( str.length() ); //str *空指针
//2* *数字格式化异常 NumberFormatException
// String num = “b123”;
// Number parse = Integer.parseInt(num);
// System.out.println(parse);
///3* *数组下标越界异常 ArrayIndexOutOfBoundsException
// int[] arr = new int[3];
// System.out.println(arr[5]);
//4* *类型转换异常 ClassCastException
// Object obj = 123;
// String objStr = (String)obj;
/**---5-7* *编译时异常:源码的时候,必须处理----\*/
//5* *文件找不到异常 FileNotFoundException
* OutputStream out = new FileOutputStream( new File("") );
//6 IO *异常 IOException
* out.write(65);
*//7* *类找不到异常 ClassNotFoundException
* Class.forName(“com.czxy.Hello”);
}
}
1, exception可以通过try…catch捕获, 进行相应的处理, 或者抛出由调用者处理
2, error 不可控制, 无法处理
checked检查型异常,又称为编译时异常,必须对异常进行处理(try-catch 或 throws)
运行时异常,不被检查型的异常,对异常可以处理,也可以不处理。
自定义检查性异常类,继承 Exception 类。
自定义运行时异常类,继承 RuntimeException 类。
(1)final:修饰符。
A).如果一个类被声明为final,就意味着它不能再派生出新的子类,不能作为父类被继承。
B).如果将变量或者方法声明为final,可以保证它们在使用中不被改变。
C).被声明final的方法只能使用,不能重写。
(2)finally:异常处理机制的一部分
A).finally结构使代码总会执行,而不管是否有异常。
B).使用finally常用于释放资源。
(3)finalize:Java中垃圾回收器执行的方法。
A).它是一个方法,属于java.lang.Object类。
B).在垃圾收集器执行的时候会调用的此方法,进行对象的回收,但在调用垃圾回收gc()后,并不能立即执行回收,JVM根据算法定时执行。
l final
package com.czxy.changgou3.testfinal;
/**
* Created by liangtong.
*/
public final class HelloFinal {
/*
public final String str = “jack”;
public void demo(){
//1.B 如果将变量或者方法声明为final,可以保证它们在使用中不被改变
str = “rose”;
}
*/
}
/*
// 1.A final 修改的类,不能被继承
class Son extends HelloFinal {
}
*/
package com.czxy.changgou3.testfinal;
/*
* Created by liangtong.
*/
* public class HelloFinal2 {
public final void demo(){
}
}
/*
class Son2 extends HelloFinal2 {
//1.C 被声明final**的方法只能使用,不能重写。
@Override
public void demo() {
super.demo();
}
}
*/
l finally
try {
System.*out*.println();
} catch (Exception e) {
e.printStackTrace();
} finally {
*//**释放资源
* }
不能,数组一旦实例化,它的长度就是固定的
1、List中的元素,有序、可重复、可为空;
2、Set中的元素,无序、不重复、只有一个空元素;
3、Map中的元素,无序、键不重,值可重、可一个空键、多个空值;
1, ArrayList的底层是动态数组;LinkedList的底层是双向链表
2, ArrayList默认初始大小为10,默认扩容大小为1.5倍;LinkedList将元素添加到链表的末尾,无须扩容
3, ArrayList查询快, 增删慢, LinkedList增删除快, 查询慢
1.借助set集合
2.利用List的contains方法循环遍历"
数组:查询多,增删少; 数组的特性
链表:查询少,增删多; 链表的特性"
HashMap底层数据结构为数组+链表;在JDK1.8中当链表的长度超过8时,链表会转换为红黑树;
(HashMap如何存储数据?)
1、如果数组还没有初始化(数组长度是0),则先初始化,默认16
2、通过hash方法计算key的hash值,hash值对数组长度进行取余操作,进而计算得到应该放置到数组的位置
3、如果该位置为空,则直接放置此处
4、如果该位置不为空,而且元素是红黑树,则插入到其中
5、如果是链表,则遍历链表,如果找到相等的元素则替换,否则插入到链表尾部
6、如果链表的长度大于或等于8,则将链表转成红黑树"
1、1.8中引入了红黑树,而1.7中没有
2、1.8中元素是插在链表的尾部,而1.7中新元素是插在链表的头部
3、扩容的时候,1.8中不会出现死循环,而1.7中容易出现死循环"
(1)HashMap是非线程安全的。HashTable是线程安全的,内部的方法基本都经过synchronized修饰。
(2)因为同步、哈希性能等原因,HashMap的性能优于HashTable
(3) HashMap允许有null值的存在,在HashTable不允许有null值
(4)HashMap默认初始化数组的大小为16,HashTable为11。前者扩容时乘2,使用位运算取得哈希,效率高于取模。而后者为乘2加1,都是素数和奇数,这样取模哈希结果更均匀。
while结构在循环的开始判断下一个迭代是否应该继续。
do/while结构在循环的结尾来判断是否将继续下一轮迭代。do结构至少会执行一次循环体。
(1)break:
常用于循环中,含义:结束循环,跳出循环体
其他应用场景:switch语句中,结束语句。
(2)continue:
结束本次循环,进行下一次循环;(注意:如果,循环进行到最后一次,continue执行,结束本次循环, 继续进行循环逻辑判断结束循环。循环结束与continue无关)
ArrayList使用普通for循环效率更高,因为对于数组结构的数据来说,for循环采用的是下标访问;
但是LinkedList是通过链表实现的,for循环时每获取第i个元素都必须从头开始遍历;foreach是通过iterator实现的遍历,而iterator遍历就是从头开始遍历,遍历完只需要一次;所以使用增强for循环效率更高。
结论:for和foreach循环效率差不多,for循环稍微好一点;但是对于链表来说,for循环效率明显比foreach低"
读写操作,我们通常称为输入/输入(IO)操作。Java通过流进行IO操作的。
字节流
InputStream是所有字节输入流的祖先,
OutputStream是所有字节输出流的祖先。
字符流
Reader是所有读取字符串输入流的祖先
Writer是所有输出字符串的祖先
字节高效流:BufferedOutputStream 、BufferedInputStream
字符高效流:BufferedWriter、BufferedReader
转换流: OutputStreamWriter、InputStreamReader"
java的序列化:把Java对象转换为二进制数据流的过程。
实现:需要序列化的类实现Serializable接口"
序列化:把对象转换为字节序列的过程称为对象的序列化。
反序列化:把字节序列恢复为对象的过程称为对象的反序列化。
1.把内存中的对象保存到一个文件中或者数据库中;
2.网络上传送对象;
3.通过RMI传输对象;
好处:
1.描述数据的传输格式,这样可以方便自己组织数据传输格式,以至于避免一些麻烦及错误
2.如果是跨平台的序列化,则发送方序列化后,接收方可以用任何其支持的平台反序列化成相应的版本,比如 Java序列化后, 用.net、phython等反序列化
有,transient表示瞬态的,被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。
进程:一个软件,在操作系统中,运行时,我们称其为进程。
1)什么是线程:
在一个进程中,每个独立的功能都需要独立的去运行,这时又需要把当前这个进程划分成多个运行区域,每个独立的小区域(小单元)称为一个线程。
例如:360杀毒软件,同时既可以安全体检电脑又可以清理电脑中的垃圾。那么这里的安全体检是360杀毒软件中的一个线程,清理电脑中的垃圾也是一个线程。
2)什么是多线程:
一个进程如果只有一条执行任务,则称为单线程程序。
一个进程如果有多条执行任务,也就是说在一个进程中,同时开启多个线程,让多个线程同时去完成某些任务(功能)。则称为多线程程序。
1.方式一:继承Thread,重写Thread类中的run方法;
2.方式二:实现Runnable接口,实现run方法;
3.方式二的方式更好,原因是:
①避免了Java单继承的局限性;
②把线程代码和任务的代码分离,解耦合(解除线程代码和任务的代码模块之间的依赖关系)。代码的扩展性非常好;
③方式二可以更方便、灵活的实现数据的共享"
l 继承Thread
package com.czxy.changgou3.thread;
/*
* Created by liangtong.
*/
* public class MyThread extends Thread {
@Override
public void run() {
System.out*.println(“my thread …”*);
}
}
l 实现Runable接口
package com.czxy.changgou3.thread;
/*
* Created by liangtong.
*/
* public class MyThread2 implements Runnable {
@Override
public void run() {
System.out*.println(“my 2222 …”*);
}
}
多线程环境中,且存在数据共享,一个线程访问的共享数据被其它线程修改了,那么就发生了线程安全问题;整个访问过程中,无一共享的数据被其他线程修改,就是线程安全的。
程序中如果使用成员变量,且对成员变量进行数据修改,就存现数据共享问题,也就是线程安全问题。
1.使用线程同步机制,使得在同一时间只能由一个线程修改共享数据;
2.消除共享数据:即多个线程数据不共享或者共享的数据不做修改。
使用局部变量,不使用成员变量。
如果使用成员变量,对成员变量不进行修改。"
使用关键字 synchronized 就可以间数据同步
public synchronized void demo01(){
*//**该方法只能被一个线程访问
* }
public void demo02(String str){
System.out*.println(“111”);
synchronized (str) {
*//该区域只能被一个线程访问
* }
System.out*.println(“2222”);
}
当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作,而其他线程又处于等待状态
启动线程使用的是start()方法。
当用start()开始一个线程后,线程就进入就绪状态,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。当cpu分配给它时间时,才开始执行run()方法(如果有的话)。start()是方法,它调用run()方法.而run()方法是你必须重写的. run()方法中包含的是线程的主体"
1.什么是死锁
死锁是指两个或者两个以上的线程在执行的过程中,因争夺资源产生的一种互相等待的现象
2.死锁产生的原因
①系统资源的竞争
通常系统中拥有的不可剥夺资源,其数量不足以满足多个进程运行的需要,使得进程在 运行过程中,会因争夺资源而陷入僵局,如磁带机、打印机等。只有对不可剥夺资源的竞争 才可能产生死锁,对可剥夺资源的竞争是不会引起死锁的。
②进程推进顺序非法
进程在运行过程中,请求和释放资源的顺序不当,也同样会导致死锁。例如,并发进程 P1、P2分别保持了资源R1、R2,而进程P1申请资源R2,进程P2申请资源R1时,两者都 会因为所需资源被占用而阻塞
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XMuZUFib-1598857977966)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image004.jpg)]
死锁产生的条件
产生死锁必须同时满足以下四个条件,只要其中任一条件不成立,死锁就不会发生。
①互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。
②请求与保持条件(Hold and wait):进程已获得了一些资源,但因请求其它资源被阻塞时,对已获得的资源保持不放。
③不可抢占条件(No pre-emption) :有些系统资源是不可抢占的,当某个进程已获得这种资源后,系统不能强行收回,只能由进程使用完时自己释放。
④循环等待条件(Circular wait):若干个进程形成环形链,每个都占用对方申请的下一个资源。"
死锁解决几种方式:
①加锁顺序(线程按照一定的顺序加锁,只有获得了从顺序上排在前面的锁之后,才能获取后面的锁)
②加锁时限(线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁)
③死锁检测 (判断系统是否处于死锁状态)
④死锁避免(指进程在每次申请资源时判断这些操作是否安全。例如银行家算法:在分配资源之前先看清楚,资源分配后是否会导致系统死锁。如果会死锁,则不分配,否则就分配。)"
1.sleep()方法,属于Thread类的。;wait()方法,则是属于Object类的;
2.sleep方法不会释放锁,而wait方法会释放锁
3.wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用
4.sleep需要接收时间参数,wait不需要接收时间参数;
5.sleep可以自然醒,wait必须等待别人唤醒;"
notify和notifyAll都可以唤醒处于等待的线程。
1.如果调用了线程 wait()方法,那么线程便会处于等待状态。
2.当调用notifyAll()方法后,将唤醒所有等待的线程
3.当调用notify()方法后,将随机唤醒一个等待线程"
有些业务逻辑在执行过程中要求对数据进行排他性的访问,于是需要通过一些机制保证在此过程中数据被锁住不会被外界修改,这就是所谓的锁机制。
优点:保证资源同步
缺点:有等待肯定会慢
悲观锁:总是假设最坏的情况。
每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁。
传统的关系型数据库里边就用到了很多这种锁机制,比如读锁,写锁等,都是在做操作之前先上锁。
乐观锁
总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据。
乐观锁适用于写比较少的情况,即冲突真的很少发生,这样可以省去锁的开销,从而提高系统的吞吐量。
悲观锁使用于写比较频繁的情况,即经常产生冲突,上层引用会不断的进行重试,这样反倒降低了性能,所以使用锁比较合适。
原理:反射在程序运行时,能够动态的操作类的成员。
1.反射前提:通过字节码获得Class对象
2.反射操作:通过Class对象对构造Constructor、字段Field、方法Method进行动态操作。
3.反射应用:框架底层都使用了反射。"
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zRUXyinJ-1598857977972)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image006.jpg)]
TCP(传输控制协议,Transport Control Protocol)
UDP(用户数据报协议,User Data Protocol)
1、TCP(面向连接如打电话要先拨号建立连接),建立TCP连接需经过三次握手,释放TCP连接需经过四次挥手;UDP是无连接的,即发送数据之前不需要建立连接
2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
Tcp通过校验和,重传控制,序号标识,滑动窗口、确认应答实现可靠传输。如丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。
3、UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。
4.每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
5、TCP对系统资源要求较多,UDP对系统资源要求较少。
1.饿汉式单例设计模式:
public class Singleton {
//私有构造方法
private Singleton() {}
//单例对象
private volatile static Singleton instance = new Singleton();
//静态工厂方法
public static Singleton getInstance() {
return instance;
}
}
2.基于双重检查锁的懒汉式单例设计模式:
public class Singleton {
//私有构造方法
private Singleton() {}
//单例对象
private volatile static Singleton instance = null;
//静态工厂方法
public static Singleton getInstance() {
if (instance == null) { //双重检测机制
synchronized (Singleton.class){ //同步锁
if (instance == null) { //双重检测机制
instance = new Singleton();
}
}
}
return instance;
}
}"
drop 用于删除结构:数据库、表
delete 删除数据,可以回滚
truncate 删除结构重建构建,不可以回滚
基于mysql
delete不重置自动增长列的计数值
truncate重置自动增长列的计数值
主键:唯一标识一条记录的字段或字段的组合称为主键。
主键不能重复,也不允许为空
外键:用来维护两个表之间数据的一致性,。
外键可以有重复的, 也允许有空值
作用:
主键:用来保证数据完整性,保证记录的唯一性
外键:通过设置外键和其他表建立关联关系(一对一,一对多,多对多)
char是一种固定长度的字符串类型,
varchar是一种可变长度的字符串类型;
适用场景:
char一般用来存储长度固定字段,如:手机号,身份证号等
varchar一般用来存储不固定长度的字段:如:用户名,昵称等
\1. 主键约束:在主键上使用
\2. 外键约束:建立俩个表之间的关系时使用
\3. 唯一约束:保证数据表中某个字段数据的唯一性时使用
\4. 非空约束:需要保证数据库字段值不为空时使用
\5. 自动增长列:数据值自增时使用,字段类型必须是整数,且必须使用主键修饰。
\1. avg():返回指定组中的平均值,空值被忽略;
\2. count():返回指定组中的项目个数
\3. max():返回指定数据中的最大值;
\4. min():返回指定数据中的最小值;
\5. sum():返回指定数据的和,只能用于数字列,空值忽略;
内连接:是从结果表中删除与其他被连接表中没有匹配行的所有行
左连接(左外连接):以左表作为基准进行查询,左表数据都显示,连接条件成立右表数据显示,条件不成立显示null
右连接(右外连接):以右表作为基准进行查询,右表数据都显示,连接条件成立左表数据显示,条件不成立显示null
作用:
1.资源重用,避免了数据库连接频繁建立、关闭的开销
2.更快的系统响应速度,直接从连接池中获取连接,响应速度加快
3.控制资源的使用,连接池能自动维护池中的连接数量,提高资源的利用率。
常用的数据库连接池:DBCP、C3P0、Druid
select * from table_name limit 49, 2
原因:MySQL的limit用法:
select * from table limit m,n
其中m是指记录开始的index,从0开始,表示第一条记录;n是指从第m+1条开始,取n条。
事务:业务中的一组操作,要么全部成功,要么全部失败,不可分割的工作单位。
数据库事务的四大特性为:ACID,分别是原子性、一致性、隔离性和持久性
原子性:不可分割的工作单位,操作要么全部成功,要么全部失败;
一致性:一个事务执行前后,表中数据必须保持一致。比如:如果从A账户转账到B账户,不可能因为A账户扣了钱,而B账户没有加钱;
隔离性:事务的隔离性是指在并发环境中,并发的事务是互相隔离的,一个事务的执行不能被其它事务干扰;
持久性:事务一旦提交后,数据库中的数据必须被永久的保存下来。
脏读:一个事务读取到了另一个事务中尚未提交的数据
不可重复读:一个事务读取到了另一个事务中已经提交的数据,通常为update时引发的问题
幻读:一个事务读取到了另一个事务中已经提交的数据,通常为insert或delete时引发的问题
读未提交:任何问题都没有解决;
读已提交:解决了脏读问题;
可重复读:解决了脏读和不可重复读问题;
串行化:解决了脏读、不可重复读和幻读问题。
操作开始前开启事务,操作成功完成提交事务,操作失败回滚事务。
开启事务:start transaction
提交事务:commit
回滚事务:rollback
在事务的处理过程中,业务操作执行了一部分,可以记录一个保持点,程序继续执行,如果程序出现异常,可以回滚所有,也可以回滚到保持点,从而保证已经执行的部分操作可以进行事务的提交。
事务的保存点,类似单击游戏的存档和读档:
1、如果没有游戏的存档功能,每次玩单机游戏都会从第一关重新开始。
2、如果使用了游戏的存档功能,下次在玩游戏时,就会从存档处开始。
distinct 对查询结果去重。
借助group by 进行分组,也可以出现去重效果。
1.SELECT子句中的列名必须为分组列或聚合函数
2.聚合函数对于GROUP BY子句定义的每个组各返回一个结果
3.必须在GROUP BY 子句之前指定 WHERE 子句
4.having对分组结果进行过滤。
索引是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。
索引的实现通常使用B树及其变种B+树。
索引相当于字典的目录,作用在于提升查询效率。
据数据库的功能,可以在数据库设计器中创建三种索引:唯一索引、主键索引和聚集索引。
唯一索引:不允许其中任何两行具有相同索引值的索引。
主键索引:在数据库关系图中为表定义主键将自动创建主键索引,主键索引是唯一索引的特定类型。该索引要求主键中的每个值都唯一。当在查询中使用主键索引时,它还允许对数据的快速访问。
聚集索引:表中行的物理顺序与键值的逻辑(索引)顺序相同。一个表只能包含一个聚集索引。聚集索引通常提供更快的数据访问速度。
索引的优点:
\1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性;
\2. 可以大大加快数据的检索速度,这也是创建索引的最主要的原因;
索引的缺点:
\1. 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加;
\2. 索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大;
\3. 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度
参考:https://blog.csdn.net/u013310119/article/details/52527632
适用场景:
\1. 加快条件的判断速度;
\2. 在作为主键的列上,强制该列唯一
\3. 在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;
\4. 在经常需要排序的列上创 建索引,因为索引已经排序
不适用场景:
\1. 查询少的列
\2. 数据内容少的列
\3. text, image和bit数据类型的列不应该增加索引
\4. 修改多于查询的列不能加索引。
1, 主键一定是唯一性索引,唯一性索引并不一定就是主键。
2, 一个表中可以有多个唯一性索引,但只能有一个主键。
3, 主键列不允许空值,而唯一性索引列允许空值。
注意:唯一索引也称为唯一约束
视图是一个虚拟表,其内容由查询定义。
从用户角度来看,一个视图是从一个特定的角度来查看数据库中的数据。
从数据库系统内部来看,一个视图是由SELECT语句组成的查询定义的虚拟表。创建视图时候,可以是一个数据表的一部分,也可以是多个基表的联合,
从数据库系统外部来看,视图就如同一张表一样,对表能够进行的一般操作都可以应用于视图,例:查询,插入,修改,删除操作等。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E36bd8Kv-1598857977981)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image008.jpg)]
用来创建视图的表叫做基表 base table
视图(view)是在基表之上建立的,它的结构(即所定义的列)和内容(即所有数据行)都来自基表,它依据基表存在而存在。一个视图可以对应一个基表,也可以对应多个基表。
区别:
1、视图是已经编译好的sql语句;而表不是。
2、视图没有实际的物理记录;而表有。
3、视图是窗口;表是内容
4、表占用物理空间而视图不占用物理空间
5、视图的建立和删除只影响视图本身,不影响对应的基本表。
1.合并字段concat
select concat(user_name, password ) from tb_user;
下述只有mysql才有:
2.使用指定连接符合并字段 concat_ws
#是连接符:select concat_ws("#" , user_name , password ,id ) from tb_user;
3.合并结果group_concat,将所有结果显示在一个单元格中
:select group_concat(user_name , password ) from tb_user;
# concat 连接
SELECT CONCAT(user_name,PASSWORD) FROM tb_user;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yS1BNWac-1598857977988)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image010.jpg)]
# concat_ws 使用指定符号进行连接
SELECT CONCAT_WS(’#’,user_name,PASSWORD) FROM tb_user;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4z3rdRMI-1598857977994)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image012.jpg)]
# group_concat 将查询结果合并在一个单元格,是否逗号拼凑
SELECT GROUP_CONCAT(user_name,PASSWORD) FROM tb_user;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ftBzRjgF-1598857977996)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image014.jpg)]
1.交叉连接:交叉连接不带WHERE子句,它返回被连接的两个表所有数据行的笛卡尔积
2.左右外连接:左连接以左表为基表,右表为从表,基表全部展示,从表数据对应匹配条件进行展示,没有匹配显示null
3.内连接:还可以被称为普通连接或者自然连接,内连接是从结果表中删除与其他被连接表中没有匹配行的所有行。
having关键字通常是与group by关键字联合使用
group by 进行分组,having对分组结果进行过滤。
select distinct * | 字段 from 表名
where 查询条件
group by 分组字段 having 分组条件
order by 排序字段 asc | desc
1 避免在where子句中进行null判断
2 避免在where子句中使用!=
3 避免在where子句中进行or条件连接
4 避免使用select*,而应该使用具体的字段名
5 避免使用like关键字
都是集合运算,求的是并集:用于合并两个或多个 SELECT 语句的结果集
union:不允许出现重复的记录
union all:允许出现重复的记录
在数据库中可以使用 DATE_FORMAT(date,format)进行时间格式化
date 参数是合法的日期
format 参数规定日期/时间的输出格式
//把时间格式化成字符串
// Oracle 格式化函数 to_char
select to_char( sysdate , ‘yyyy/mm/dd’) from dual;
// Mysql 格式化函数
– %Y 年,4 位
– %m 月,数值(00-12)
– %d 月的天,数值(00-31)
– %H 小时 (00-23)
– %i 分钟,数值(00-59)
– %S 秒(00-59)
select date_format( now() , ‘%Y-%m-%d %H:%i:%S’)
count(*)和count(1)执行的效率是完全一样的
count(1)的执行计划将转化为count(*)
参考:https://www.cnblogs.com/sueris/p/6650301.html
https://blog.csdn.net/moni_mm/article/details/82056021
mysql的执行计划
//语法: explain 查询语句
explain select count(*) from tb_user;
explain select count(1) from tb_user;
– Oracle 执行计划
– 语法:explain plan for 查询语句
explain plan for select count(*) from dual;
explain plan for select count(1) from dual;
– 查询执行计划结果
select * from table(dbms_xplan.display());
一样
主键:唯一标识一条记录的字段或字段的组合称为主键。 主键不能重复,也不允许为空
外键:用来维护两个表之间数据的一致性,外键可以有重复的, 也允许有空值,其他没有学过
在数据库中,我们通过主键和外键,组成成主外键关系,来描述一对多。
可以直观的操作数据 查看数据,可以借助图形化界面轻松完成对数据库的常用操作
Mysql的优化,大体可以分为三部分:
1.索引的优化,2.sql语句的优化,3.表的优化
1.索引的优化
(1)只要列中含有NULL值的字段,不使用索引
(2)尽量使用短索引
(3)经常在where子句使用的列,尽量使用索引,有多个列where或者order by子句的,应该建立复合索引,对于like语句,以%或者‘-’开头的不会使用索引,以%结尾会使用索引
(4)尽量不要在列上进行运算
(5)尽量不要使用not in和<>操作
2.sql语句的优化
(1)查询时,能不要就不用,尽量写全字段名
(2)查询时,尽量使用连接查询代替子查询
(3)多表连接时,尽量小表驱动大表,即小表 join 大表
3.表的优化
(1)表的字段尽可能用NOT NULL
(2)字段长度固定的表查询会更快
(3)把数据库的大表按时间或一些标志分成小表
(4)将表分区
1.主键用于表示数据(记录)的唯一性, 不设置主键会导致数据表中可能存在完全相同的数据;
2.一个表的外键必须是另一个表的主键,不设置主键将无法建立俩个表之间的关联关系;
3.设置主键时,会自动增加索引,有利于提高数据的检索速度;
MySQL数据库引擎取决于MySQL在安装的时候是如何被编译的。要添加一个新的引擎,就必须重新编译MYSQL。
常见的引擎:Innodb、MyISAM。
InnoDB是默认的MySQL引擎,支持事务,支持行锁定和外键。
MyISAM拥有较高的插入、查询速度,但不支持事物。
servlet的生命周期是初始化(init)、服务(service)、销毁(destroy)
1.初始化(init):默认第一次请求前,只初始化一次。修改web.xml,允许服务器启动时初始化。
2.服务(service):方法被调用时进行服务,在项目启动期间可以进行多次服务(请求一次执行一次)
3.销毁(destory):当服务器关闭时进行销毁。只销毁一次
Servlet接口中声明3个方法,tomcat在不同的时候将调用不同的方法。
init 初始化方法,2种情况被调用
情况1:默认,第一次请求前
情况2:在web项目核心配置文件web.xml中,配置初始化,将在服务器启动时初始化。
每次请求时,调用服务
服务器关闭时,调用销毁。
Servlet是服务器端的程序
JSP是服务器页面程序
JSP本质上就是一个Servlet,在访问jsp时,在服务器端会将jsp先转换成servlet,再将生产的servlet的结果响应给浏览器。
jsp是html页面中内嵌Java代码,侧重页面显示;Servlet是中书写Java代码,侧重逻辑控制;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AqFctp0n-1598857978000)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image016.jpg)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8eaqOWBq-1598857978003)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image018.jpg)]
1.init(ServletConfig):初始化方法,默认第一次请求前执行,完成servlet初始化工作
2.service(ServletRequest,ServletResponse):执行方法,一次请求执行一次。
3.destroy():销毁方法,Servlet对象应该从服务中被移除的时候,容器会调用该方法进行销毁操作
4.getServletConfig():获得ServletConfig配置对象,包括初始化参数等。
5.getServletInfo():获得Servlet描述,一般没有用。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lQ3c5qm6-1598857978006)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image020.jpg)]
异步处理允许Servlet重新发起一条新线程去调用 耗时业务方法,这样就可以避免等待
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A5yPemo0-1598857978010)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image022.jpg)]
1、request.getParameterValues(“参数”); //获得指定参数名的一组参数值 (String[])
2、request.getParameter(“参数”); //获得指定参数名的一个参数值(String) , UserServlet?username=jack , 通过username获得值jack
public class TestRequestParam {
private HttpServletRequest request;
public void testDemo01(){
*//**请求数据:index.html?username=jack&hobby=**抽烟&hobby=**喝酒&hobby=**烫头
//* *获得username**的值,一个值
* String username = request.getParameter(“username”);
*//* *获得hobby**的值,一组值
* String[] hobbyArr = request.getParameterValues(“hobby”);
*//* *所有值 , map.key* *参数名称,map.value* *参数的值
* Map
}
}
1、doGet():地址栏url方式访问、超链接访问、以及form表单中的method属性值为get方式访问,则调用doGet()方法
2、 doPost():form表单中的method属性值为post方式访问,则调用doPost()方法
\1. 以下3种情况调用的是doGet方法:1. 地址栏url直接访问;2. 超链接访问; 3. 表单method为get方式访问
\2. 一般情况1种情况调用的是doPost方法:form表单中的method属性值为post方式
* 以上方式都不含ajax,ajax支持get和post等方式。
package com.czxy.changgou3.param;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
* Created by liangtong.
*/
* public class HelloWorld extends HttpServlet {
// get请求调用doGet方法
// 1 地址栏直接访问、2 表单提交 method=“get”**、3 *超链接(**与地址栏直接访问一样)
* @Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
*//表单提交 method=“post”
// post请求调用doPost**方法
* @Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
ServletContext对象是上下文对象 Servlet直接调用getServletContext方法返回ServletContext对象
l ServletContext 称为Servlet的上下文对象,通过上下文对象可以更方便的管理所有的servlet及其相关资源。
n 可以动态添加servlet、filter、listener 等
n 可以管理web项目初始化参数
n 可以管理web项目作用域数据(xxxAttribute)
l 获得方式:
n 1) 通过init方法参数ServletConfig获得
n 2)通过父类提供简化方法 getServletContext() 获得
package com.czxy.changgou3.param;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
* Created by liangtong.
*/
* public class TestServletContext extends HttpServlet {
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
*//servletConfig* *, servlet* *配置对象,用于存放web.xml**文件配置信息的
// 1.**通过ServletConfig**获得上下文对象
* config.getServletContext();
}
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
*// 2.**调用父类提供的简化方法
* ServletContext servletContext = getServletContext();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KlxBtw4P-1598857978014)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image024.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dmMilzyg-1598857978019)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image026.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u6ryx0wY-1598857978023)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image028.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TB15kxb2-1598857978028)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image030.jpg)]
Servlet不是线程安全的。Servlet 默认是单例模式,如果提供成员变量,多个线程对成员变量进行操作,将发生并发问题,所以不安全。
如果不提供成员变量,或提供成员变量但不使用,可以解决并发问题
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o9DEQYMn-1598857978032)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image032.jpg)]
l 文件上传
1.使用fileupload完成上传功能,需要添加commons-fileupload相关Jar包
2.表单提交请求编码类型必须是enctype=“multipart/form-data”,请求方式必须是post
3.服务器如果是Servlet需要使用fileupload的提供的工具类ServletFileUpload完成文件上传。
4.服务器如果是Spring mvc,通过MultipartFile类型接收上传数据,从而完成文件上传。
l 文件下载
1.提供一个超链接,可以下载浏览器不能解析的资源
2.响应头 + 响应流:如果下载资源浏览器可以解析,需要自定义实现类,添加一个下载使用的响应头content-disposition确定下载时浏览器显示的文件名,然后以流的方式将资源响应给浏览器即可
文件 第二步
文件 第四步
package com.czxy.changgou3.param;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
/*
* Created by liangtong.
*/
* public class FileController {
@PostMapping
public void fileupload(MultipartFile image) throws IOException {
*//**原始文件,上传文件名
* image.getOriginalFilename();
*//**上传内容
* image.getInputStream();
}
}
*//下载
* public void download(HttpServletResponse response) throws IOException {
*//响应头
* response.setHeader(“content-disposition”,“attachment;filename=mm.jpg”);
*//**响应内容
* ServletOutputStream out = response.getOutputStream();
*//out.write(…);
* }
\1. 表现形式:get在url中拼凑请求参数。Post请求参数在请求体中;
\2. 安全性:get请求参数追加在路径上,可见不安全,post请求参数在请求体中,一般人不可见,较安全。
\3. 数据大小:get提交数据有限,post无限。
//get请求
http://localhost/IndexServlet?username=jack&password=1234&sex=男
forward 请求转发
redirect 重定向
1.地址栏是否改变:forward浏览器端网址不会发生变化,redirect浏览器端地址会变成;
2.是否可共享请求参数:forward是转发,属于同一个请求,数据可以传递;redirect是两次请求,数据不能传递;
3.是否可站外跳转:forward一般用于网站内部跳转,redirect可在站内跳转,也可跳转到其它网站。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yxrffI4Y-1598857978037)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image034.jpg)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m9uq8qJ9-1598857978040)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image036.jpg)]
request:请求对象
response:响应对象
session:回话对象
pageContext:页面上下文对象
application:类型是ServletContext,表示servlet上下文对象,可以在整个web项目中共享资源。
out 输出对象
page JSP网页本身
config Servlet的配置对象
exception 异常对象
l JSP就是servlet,Servlet是一个Java类。
n page,内容当前页面(this)
n config,配置类,有init方法提供
u application,servlet获得上下文,类型ServletContext
n request 请求对象,service第一个参数
u session对象,request.getSession() 获得session对象
n response 响应对象,service第二个参数
u out 输出对象,response.getWriter() 获得输出流
n exception 异常对象,只要是程序就存在异常
n pageContext,jsp页面的上下文对象
session属性:表示当前页面是否支持session,如果为false,则在JSP页面中不能使用session对象。属性的默认值为true。
info属性:设置JSP页面的相关信息。
contentType属性:设置JSP的MIME类型和字符编码。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jt2KTE33-1598857978045)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image038.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YYaJfML6-1598857978049)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image040.jpg)]
application:在当前web项目中有效
session:在当前会话中有效
request:在当前请求中有效
page:在当前页面有效
page ,表示当前页面,主要用于jsp标签。当前页面和jsp标签之间传递数据可以使用page作用域。
request,表示当前请求,可以涉及多个页面。如果使用多个页面需要请求转发。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E66fMecC-1598857978051)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image042.jpg)]
session:表示当前会话,可以允许多次请求。(会话:打开浏览器,进行多次访问、关闭浏览器)
application:表示当前应用(项目),多用户(session)之间可以共享数据。
通过page指令设置<%@ page isThreadSafe=“false”%>,默认Servlet支持多线程模式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cBqR1wcR-1598857978054)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image044.jpg)]
<% %> 用于编写Java代码,语法与方法体一致。
<%= %>将结果输出到浏览器,语法与方法的实际参数一致。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hSVjEPaj-1598857978059)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image046.jpg)]
<% 内容 %> ,将拼凑到service方法体中
<%= 内容 %>,将转换成 out.wirter(“内容”)
1.JSP页面显示中文乱码:JSP页面设置为项目对应编码:contentType=“text/html; charset=UTF-8”
2.URL传递参数中文乱码:修改Tomcat的conf目录下的server.xml配置文件, 元素中添加 URIEncoding=“UTF-8” 属性解决;
3.表单提交中文乱码:采用过滤器Filter统一解决乱码问题
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4vKdaDgL-1598857978063)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image048.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-87VTep2k-1598857978066)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image050.jpg)]
\1. 过滤器Filter是对访问资源拦截的一种技术。
\2. 默认在请求前拦截,在访问请求资源前完成需要的操作后,放行即可访问资源,资源访问后,再回到过滤器进行后续的处理,最后请求结束。
3.filter可以通过dispatcher来修饰拦截时机。
REQUEST:请求前拦截,默认值
FORWARD:请求转发前拦截
INCLUDE:请求包含前拦截
ERROR:显示错误页面前拦截
\3. 应用场景:统一编码、统一用户认证、屏蔽非法文字,进行响应数据压缩,等等
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C2NNQ0KJ-1598857978069)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image052.jpg)]
package com.czxy;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class HelloFilter implements Filter {
@Override
public void init(FilterConfig arg0) throws ServletException {
//初始化方法
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//过滤方法
//放行
chain.doFilter(request, response);
}
@Override
public void destroy() {
//销毁方法
}
}
HelloFilter
com.czxy.HelloFilter
HelloFilter
/*
REQUEST
\1. 什么是WEB监听器:所谓的WEB监听器是指对WEB环境中Request、Session和ServletContext等的监听,当被监视的对象的创建、销毁或者属性发生变化时,便调用相应的方法进行处理。
\2. 使用场景:网站在线人数统计、监听用户的行为(管理员踢人),等等
\3. 监听器的底层原理采用的观察者模式。例如:父亲检测儿子吃饭。
cookie是浏览器技术, 是服务器发送过来的, 保存在浏览器
session是服务器技术, 数据保持在服务器,通过cookie与浏览器建立联系, 保证用户在切换页面时保持会话
区别:
1, cookie只能存储英文字符串, session可以存储任意数据
\2. cookie只能存储少量数,session可以存储大量数据
3, cookie默认生命周期是当前会话, 关闭浏览器自动销毁, session默认生命周期是30分钟
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5eQOoGki-1598857978072)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image054.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nQ7BI6ic-1598857978076)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image056.jpg)]
session.setMaxInactiveInterval(设置时间/秒)
cookie信息存储在浏览器端,不同浏览器存储在硬盘的具体位置会不同。
如果限制cookie的使用
1.提示用户不要禁用cookie;
2.使用URL****重写技术解决cookie被禁用,session不能使用的问题:
3.使用html5的localStorage替代cookie
参考:https://blog.csdn.net/m0_38039437/article/details/76718541
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lad4PVmJ-1598857978081)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image058.jpg)]
url重写是修改响应给用户的访问地址,在url中拼接session id,。
Url重写解决是浏览器端cookie禁用,session无法使用的问题。
1xx(请求进行中):用于表示临时响应并需要请求者执行操作才能继续的状态代码;
2xx(请求成功):用于表示服务器已成功处理了请求的状态代码;
3xx(请求被重定向):通常这些状态代码是用于重定向的;
4xx(客户端错误):用于指出客户端的错误;
5xx(服务器错误):这些状态代码表示,服务器在尝试处理请求时发生内部错误
l 常见状态码:
200,服务器已成功处理了请求。
302,请求重定向
400,请求路径语法错误
404,请求资源不存在
405,请求方式不正确,如:一个资源只支持GET方法,但是客户端使用PUT方法访问。
500,服务器遇到错误,无法完成请求。
token是服务器写到浏览器的用户标识, 一般是使用32位的UUID,为自定义数据。
session是浏览器与服务器的一次会话,是web服务器创建的对象。
session可以用于单机web服务,记录用户登录。
token可以用于集群web服务,完成单点登录(登录一次,其他应用处不需要登录)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jvke1UyS-1598857978084)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image060.jpg)]
localStorage 浏览器端对象,用于在浏览器本地存储服务器响应的数据。
localStorage 是 HTML5 的新特性。
用于解析cookie存储空间不足的问题。
localStorage中一般浏览器支持的是5M大小,这个在不同的浏览器中localStorage会有所不同。
localStorage 用于长久保存整个网站的数据,保存的数据没有过期时间,直到手动去删除。
1.是什么:Ajax 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术
2.使用ajax的好处有:
①通过异步模式,提升了用户体验;
②优化了浏览器和服务器之间的传输,减少不必要的数据往返,减少了带宽占用;
③Ajax引擎在客户端运行,承担了一部分本来由服务器承担的工作,从而减少了大用户量下的服务器负载
3.如何使用
①jQuery中发送ajax请求:
$.ajax({
type: “POST”,url: “”,data: “name=John”,success: function(msg){}
});
②Vue发送ajax请求:
get请求:axios.get(url[,options]);
post请求:axios.post(url,data,[options]);
//请求路径、请求方式、请求参数、请求数据类型、响应数据类型、是否成功
$.ajax({
url: “请求路径”,
type: “请求方式:POST、GET”,
data: “发送到服务器的数据”,
contentType: “发送信息至服务器时内容编码类型”,
dataType: “预期服务器返回的数据类型:json、xml、text 等”,
success: function( data, textStatus ) { //成功回调
// data 响应数据
},
error: function() { //请求失败时调用此函数
}
});
\1. 是什么:
json一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性。
xml是可扩展标记语言 ,使用标签描述数据结构。
\2. 对比:
xml的内容是结构+数据,可读性高,数量大,语法格式统一。
Json的内容是数据,可读性低,数量小,格式自定义(更灵活)。
\3. 适用场景:
json更适合项目间数据的传递;
xml更适合结构的说明,例如:maven项目的pom.xml文件;
//描述一个学生(id、name、age 等)
//JSON格式
{
“id”: “u001”,
“name”: “jack”,
“age”: 18
}
//xml格式
jack
18
JSON 语法规则:
1.数据在名称/值对中
2.数据由逗号分隔
3.花括号保存对象
4.方括号保存数组
JSON对象:{“key”:“value”,“key”:“value”,…}
JSON数组:[ obj , obj , obj , …]
{
“id”: “u001”,
“name”: “jack”,
“age”: 18,
“hobby”: [“抽烟”,“喝酒”,“烫头”],
"courses: [
{
“name”: “体育”
“count”: 100,
},
{
“name”: “英语”
“count”: 99,
}
]
}
基于TCP的应用层协议,它不关心数据传输的细节,主要是用来规定客户端和服务端的数据传输格式,最初是用来向客户端传输HTML页面的内容
l 客户端和服务器数据传输格式:
n 请求:请求行、请求头、请求体
n 响应:响应行、响应头、响应体
l 七层协议和四层协议(了解)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6hQedvMy-1598857978089)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image062.jpg)]
HTTP:超文本传输协议,基于TCP/IP通信协议来传递数据网络协议,数据不安全,没有加密。默认端口号80
HTTPS:超文本传输安全协议,是HTTP协议 + SSL证书协议,证书需要到ca申请,传输过程中数据需要加密。默认端口号443
参考:https://www.cnblogs.com/wudaoyongchang/p/6253451.html
l HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版。
l 对称加密+非对称加密结合
用非对称加密的方式去传输对称加密的密钥,这样可以保证对称加密的密钥可以安全的交付给对方。
1、客户端先把非对称加密的公钥,明文传输给服务器;
2、服务端在接到密钥之后,会生成一把用于对称加密的密钥;
3、服务器用之前接到的公钥对刚刚生成的密钥进行加密,然后传输给客户端;
4、客户端通过自己的密钥对服务器传过来的被公钥加密过的密钥进行解密;)
l 加密算法:对称加密+非对称加密
l 常见的加密:RC5、RC4、SHA(信息摘要算法,同MD5一样属于不可逆算法)
短链接:客户端和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。
长连接:用以保持连接特性。 长连接多用于操作频繁,点对点的通讯,而且连接数不能太多。
因为用短连接频繁的通信会造成socket错误 WEB网站的http服务一般都用短链接。因为长连接对于服务端来说会耗费一定的资源。
MVC设计模式: Model-View-Controller简写。
MVC是软件工程中的一种软件架构模式,它是一种分离业务逻辑与显示界面的设计方法。它把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。
控制器Controller:对请求进行处理,负责选择视图;
视图View:用户与程序交互的界面;
模型Model:用于业务处理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-THiRbkqr-1598857978094)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image064.jpg)]
SpringMVC是一个MVC框架,springmvc的工作流程:
\1. 发送请求:在浏览器输入请求路径,发送请求,前端控制器连接所有的请求。
\2. 获得处理器:核心控制器(DispatcherServlet)接收到请求,通过处理器映射器(handlerMapping)获得对应的处理器(Handler)
大白话:根据请求路径获得对应的controller。
\3. 执行处理器:通过处理器适配器(HandlerAdapter)执行处理器(Handler),并返回视图模型对象(ModelAndView)
大白话:执行controller方法。如果方法返回的字符串,底层也会转换成ModelAndView。
\4. 解析视图:通过视图解析器(ViewResolver)解析ModelAndView中的视图,将逻辑视图解析成真正的视图。
\5. 渲染视图:将Model中的数据渲染到视图(View)中
\6. 响应结果
大白话:将模型数据(查询结果)渲染到jsp页面中,并将处理结果响应给浏览器。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hDAPi0iA-1598857978097)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image066.jpg)]
Spring框架的核心控制器(前端控制器)是DispatherServlet
他的核心功能就是分发请求,请求会被分发给对应处理的类handler。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-njqvMiZ8-1598857978100)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image068.jpg)]
使用@ResponseBody注解,将返回json数据。
1.如果在方法使用该注解,当前方法返回json数据。
2.如果在类上使用该注解,当前类中所有的方法,都将返回json数据。
springmvc默认用jackson对json数据进行转换,但需要添加jackson的包
扩展阅读:
消息转换器原理解析:https://blog.csdn.net/shadabing/article/details/84664402
SpringBoot配置Fastjson:https://blog.csdn.net/cjq2013/article/details/76421101
SpringMVC配置Fastjson:https://blog.csdn.net/do_bset_yourself/article/details/51324186
l 之前编写controller返回的都是json数据,但没有使用@ResponseBody
l 通常每一个controller都使用 @RestController,而@RestController已经被@ResponseBody修饰
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GlmQDrTG-1598857978103)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image070.jpg)]
l 总结:只要返回json,必须使用@ResponseBody
优点:
1、开发人员可以只关注整个结构中的其中某一层;
2、可以很容易的用新的实现来替换原有层次的实现;
3、可以降低层与层之间的依赖;
4、有利于标准化;
5、利于各层逻辑的复用
缺点:
1、降低了系统的性能。这是不言而喻的。如果不采用分层式结构,很多业务可以直接造访数据库,以此获取相应的数据,如今却必须通过中间层来完成。
2、有时会导致级联的修改。这种修改尤其体现在自上而下的方向。如果在表示层中需要增加一个功能,为保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码。
1.Spring相关注解
1.1)声明bean的注解
@Component 通用注解,用于声明bean。可以配置任意组件。
@Repository 派生注解,与@Component等效,Dao实现类推荐使用的注解,不仅可以声明bean,而且提高可读性。
@Service 派生注解,与@Component等效,Service实现类推荐使用的注解,不仅可以声明bean,而且提高可读性。
@Controller 派生注解,与@Component等效,Controller实现类推荐使用的注解,不仅可以声明bean,而且提高可读性。
1.2)bean注入的相关注解
@Autowired:按类型注入,
@Resource(name=""):按名称注入
@Resource():先按名称注入,如果没有再按照类型。
1.3)配置类相关注解
@Bean 注解在方法上,声明当前方法的返回值为一个bean。
@Configuration 声明当前类为配置类,内部常使用@Bean进行详细配置。取代了xml文件配置。
@ComponentScan 用于对Component进行扫描,可以配置扫描的包路径
1.4)@Value注解:为属性注入简单值
2.SpringMVC相关注解
@RequestMapping 修饰方法,将请求路径映射到Controller对应的处理方法上。
修饰类,给请求路径添加访问前缀(二级路径)
@ResponseBody 将返回值转换成json数据,并响应给浏览器。
@RequestBody 将json格式的请求参数,封装到指定的JavaBean中。
@PathVariable 用于接收路径参数,比如@RequestMapping(“/hello/{name}”)申明的路径,参数前使用注解@PathVariable(“name”),就可以获取name对应的值。
@RestController 该注解为一个组合注解,相当于@Controller和@ResponseBody的组合,注解在类上,意味着,该Controller的所有方法都响应JSON格式数据。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jHAPRwe4-1598857978109)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image072.jpg)]
package com.czxy.controller;
import com.czxy.domain.Film;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/*
* Created by liangtong.
*/
* @Controller *//普通web层 controller
* @RestController // 返回json controller *, @Controller + @ResponseBody
* @RequestMapping("/test") *//**访问前缀路径
* public class TestController {
*//**注入
//@Resource
* @RequestMapping(path="",method= RequestMethod.GET*)
@GetMapping("/{uid}")
@PostMapping
@PutMapping
@DeleteMapping
public void demo(@PathVariable(“uid”*) String uid , @RequestBody Film film){
}
}
1.地址栏参数或普通表单请求,如:age=18&gender=man,SpringMVC方法参数需要使用@RequestParam(“参数名”)获得参数值。
2.提交json类型数据,SpringMVC 方法参数需要使用@RequestBody 将数据封装到java对象中。
3.路径占位符:如 http://localhost:8080/user/findById/1,使用@RequestMapping(“findById/{id}”)匹配路径,使用@PathVariable(“id”)获得对应的参数值。
4.文件上传,修改表单请求为"multipart/form-data"方式,SpringMVC采用MultipartFile参数类型接收数据
package com.czxy.controller;
import com.czxy.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
/*
* Created by liangtong.
*/
* @Controller
@RequestMapping("/param")
public class ParamController {
*//方式1:普通get请求
// GET http://localhost:8080/param?username=jack&password=1234
* @GetMapping
public void demo01(@RequestParam(“username”) String username, @RequestParam(“password”**) String password){
}
*//方式2:json post**请求
/*
POST http://localhost:8080/param
{
“username” : “jack”,
“password” : “1234”,
}
*/
* @PostMapping
public void demo02(@RequestBody User user){
}
*//方式3:get路径参数
// GET http://localhost:8080/param/100
* @GetMapping("/{uid}")
public void demo03(@PathVariable(“uid”**) Integer uid){
}
//方式4:文件上传
/* *前端请求
* *请求方式
post http://localhost:8080/param/upload
*/
* @PostMapping("/upload")
public void demo04(MultipartFile image){
}
}
其实问题相当于SpringMVC的执行流程,DispatcherServlet用来处理所有的HTTP请求和请求响应,回答SpringMVC的执行流程即可。
@Controller 是@Component的派生注解(别名),功能就是将被修饰的类添加到spring容器。
字面意思,用于修饰Controller层的组件,提高可读性。
修饰方法,将请求路径映射到Controller对应的处理方法上。
修饰类,给请求路径添加访问前缀(二级路径)
使用 @ResponseBody 注解将Java集合转换json数组,并将结果响应给浏览器。
package com.czxy.controller;
import com.czxy.domain.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
/*
* Created by liangtong.
*/
* @RestController *// @Controller + @ResponseBody
* @RequestMapping("/user")
public class ListController {
//@RequestMapping(value = “/findAll”, method = RequestMethod.GET)
* @GetMapping("/findAll")
public List findAll(){
List list = new ArrayList();
list.add(new User(“jack”,“1234”));
list.add(new User(“rose”,“5678”));
return list;
}
/
* get http://localhost:8080/user/findAll
[
{
“username”:“jack”,
“password”:“1234”,
},
{
“username”:“jack”,
“password”:“1234”,
}
]
*/
* }
Spring是一个分层的JavaSE/EE full-stack(一站式)轻量级开源框架。
Spring为不同的层都提供的企业级解决方案:
web层:spring mvc
service层:spring
dao层:JDBCTemplate、Spring data jpa (Java Persistence API)
Spring的核心思想是IoC(控制反转)和AOP(面向切面编程)
1.方便解耦,简化开发 (高内聚低耦合)
Spring就是一个大工厂(容器),用于创建对象(bean)和维护对象间的依赖关系。
2.AOP编程的支持
Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能.
声明式事务的支持 ,只需要通过配置就可以完成对事务的管理,而无需手动编程
3.方便程序的测试
Spring对Junit4支持,可以通过注解方便的测试Spring程序
4.方便集成各种优秀框架
Spring支持各种优秀框架(如:MyBatis、Redis、MongoDB、ElementsSearch、Quartz等)
5.降低JavaEE API的使用难度
Spring 对JavaEE开发中非常难用的一些API(JDBC、JavaMail等),都提供了封装,使这些API应用难度大大降低。
l aop底层代用代理模式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tuK9Rcot-1598857978113)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image074.jpg)]
l Spring整合Junit , @RunWith(SpringRunner.class)
l Spring boot 整合 Junit, @SpringBootTest(clases = 启动类.class )
1.Spring Core:Spring框架的核心容器,他提供了Spring框架的基本功能。这个模块中最主要的一个组件为BeanFactory,它使用工厂模式来创建所需的对象。同时BeanFactory使用IOC思想,通过读取XML文件的方式来实例化对象,可以说BeanFactory提供了组件生命周期的管理,组件的创建,装配以及销毁等功能;
2.Spring AOP:采用了面向切面编程的思想,使Spring框架管理的对象支持AOP,同时这个模块也提供了事务管理,可以不依赖具体的EJB组件,就可以将事务管理集成到应用程序中;
5.Spring Web:提供了Servlet监听器的Context和Web应用的上下文。同时还集成了一些现有的Web框架,例如Struts;
6.Spring Context:扩展核心容器,提供了Spring上下文环境,给开发人员提供了很多非常有用的服务,例如国际化,Email和JNDI访问等;
7.Spring Web MVC:提供了一个构建Web应用程序的MVC的实现
3.Spring ORM:提供了对现有的ORM框架的支持,例如Hibernate等;
4.Spring DAO:提供了对DAO(Data Access Object,数据访问对象)模式和JDBC的支持。DAO可以实现将业务逻辑与数据库访问的代码分离,从而降低代码的耦合度。通过对JDBC的抽象,简化了开发工作,同时简化了对异常的处理(可以很好的处理不同数据库厂商抛出的异常);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jm5CQf4C-1598857978116)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image076.jpg)]
1.基于XML配置
在XML文件中通过元素定义Bean,如:
2.基于注解配置
在Bean实现类处通过标注@Component或衍型类(@Repository、@Service及@Controller)定义Bean
3.基于Java类配置
在标注了@Configuration的Java类中,通过在类方法上标注@Bean定义一个Bean。方法必须提供Bean的实例化逻辑
l xml采用 方式进行配置
public class StudentController{
private StudentService studentService;
}
l 注解方式
@Controller
public class StudentController{
@Resource
private StudentService studentService;
}
@Service
public class StudentServiceImpl implements StudentService {
}
l Java类配置(配置类)
@Configuration
public class DataSourceConfiguration {
@Bean
public DataSource druidDataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
return druidDataSource;
}
Spring Bean生命周期共分10个步骤,简述如下:
1.实例化:实例化一个Bean
2.注入:按照Spring上下文对实例化的Bean进行依赖注入
7.初始化:自动调用init-method初始化方法
//此处就是项目中使用的bean
10.销毁:当bean不再需要时,执行销毁方法destroy-method
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hTWnwqgV-1598857978123)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image078.jpg)]
专业解释,参考文档如下:(后处理bean)
https://blog.csdn.net/fuzhongmin05/article/details/73389779
https://www.jianshu.com/p/3944792a5fff
1.singleton:单例,默认值,在Spring IoC容器只有一个Bean实例;
2.prototype:多例,每次从容器中获得Bean时,都返回一个新的实例;
3.request:一次请求,请求开始创建bean,请求结束销毁bean。只有在Web应用中使用Spring时,该作用域才有效
4.session:一次会话,同一个会话共享一个Bean实例,在session过期后,bean会随之失效。同样只有在Web应用中使用Spring时,该作用域才有效
5.global-session:全局会话(集群环境),在不同的portlet间共享session。(Portal是一个基于Web的应用)
l xml配置
l 注解配置
*//@Scope(“singleton”) //单例
* @Scope(“prototype”**) *//**多例
* public class StorageController {
线程安全产生的原因是,多个线程对共享数据同时进行修改。
该问题分以下俩种情况:
1.有问题:如果类中存在成员变量(即共享数据),且成员变量中的数据在方法中会被修改,此时可能会产生线程安全问题;
2.没有问题:如果Bean没有成员变量,或者成员变量数据在访问的时候不会被修改,则不会产生线程安全问题。
1.Spring组件扫描:
在spring的配置类中使用@ComponentScan(basePackages = “com.czxy”)可以扫描com.czxy包以及子包下添加了指定注解的类。
常见的注解有: @Component、@Service、@Controller、@Repository
2.SpringBoot扫描机制
1)默认扫描规则,SpringBoot中会自动扫描启动类所在包及其子包中的所有添加了指定注解类
2)使用@ComponentScan注解可以覆盖默认扫描规则。
自动装配,自动完成各个bean之间的依赖关系装配。
Spring提供了5中自动装配模式:
1.no:默认值,没有使用自动装配
2.byName 按照属性名自动装配。
3.byType 按照属性的数据类型自动装配。如果存在不止一个这样的bean,将抛出异常。
4.constructor 按照构造函数参数类型自动装配。(常见于xml配置)
5.autodetect 自动。先constructor自动装配,如果不执行,再按照 byType 自动装配
l xml配置,使用autowire确定装配机制
l 如果使用注解,注解自带各自默认的装配机制,参考:5.11
\1. 显示的依赖注入(@Resource) 会重写自动装配
\2. 不能自动装配基本数据类型、字符串、数组等
\3. 自动装配不如显示依赖注入精确
两个注解都可以完成依赖注入功能。
1.@Autowired:
@Autowired : 默认是以byType按类型自动注入。
@Autowired + @Qualifier(“名称”):将按照名称自动注入
2.@Resource:
@Resource() 如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称注入,
如果注解写在setter方法上默认取属性名进行注入。
当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
@Resource(name="") 将按照名称自动注入
//按照类型 byType进行注入
@Autowired
private StorageService storageServiceImpl;
*//按照名称注入
* @Autowired
@Qualifier(“storageService”**)
private StorageService storageServiceImpl;
//默认按照名称注入,如果没有将按照类型注入
@Resource
private FilmService filmService;
*//只按照名称注入
* @Resource(name=“fileService”**)
private FilmService filmService;
1.在指定类中添加指定注解,配置类添加@ComponentScan注解进行包扫描,就可以完成bean的配置。
2.相关注解
@Component 通用组件类
@Controller 用于配置web层的controller类
@Service 用于配置service层的service类
@Repository 用于配置dao层dao类
@Bean 用于配置第三方实例,只能修饰方法。
1.通过ApplicationContext手动获取:手动加载xml或配置类获得上下文对象,通过getBean()获得指定名称的bean。(通过注入的方式获得ApplicationContext,在通过ApplicationContext提供getBean获得指定对象)
2.实现BeanFactoryAware接口:先获得BeanFactory,再getBean()获得指定名称的bean。
3.实现ApplicationContextAware 接口 :先获得ApplicationContext,再getBean()获得指定名称的bean。
l BeanFactory 和 ApplicationContext 均表示Spring 工厂本身
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EFCvpCTr-1598857978129)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image080.jpg)]
public class User implements BeanFactoryAware,ApplicationContextAware {
private String username;
private String password;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
beanFactory.getBean("");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
applicationContext.getBean("");
}
}
事务就是业务中的一组操作,要么全部成功,要么全部失败
Spring通过平台事务管理器(PlatformTransactionManager)进行事务管理
事务管理器通过事务定义(TransactionDefinition)进行具体的事务操作。
事务定义通过4方面对事务进行详细描述
1.readOnly:是否只读
2.timeout:超时时间
3.isolationLevel:事务隔离级别,隔离级别4种:读未提交、读已提交、可重复读、串行化
4.propagationBehavior:传播行为,共7种,常见的有:必须有事务 PROPAGATION_REQUIRED、每次必须新的 PROPAGATION_REQUIRES_NEW
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rqKhOq98-1598857978132)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image082.jpg)]
l 语法
@Transactional(timeout = 超时时间,readOnly = 是否只读,isolation = 隔离级别,propagation =传播行为)
l 实例
@Transactional(timeout = -1,readOnly = false,isolation = Isolation.*DEFAULT*,propagation = Propagation.*REQUIRED*)
Spring事务管理高层抽象主要包括3个接口,Spring的事务主要是由他们共同完成的:
PlatformTransactionManager:事务管理器—主要用于平台相关事务的管理
TransactionDefinition: 事务定义信息(隔离、传播、超时、只读)—通过配置确定如何进行事务管理。
TransactionStatus:事务具体运行状态—事务管理过程中,每个时间点事务的状态信息。
有异常就会回滚
可以通过@Transactional(rollbackFor=Exception.class,notRollbackFor=RunTimeException.class)修改默认行为
rollbackFor用于设置那些异常将发生回滚
notRollbackFor用于设置那些异常不会发生回滚
DEFAULT(默认):使用后端数据库默认的隔离级别(spring中的的选择项)
READ_UNCOMMITED(读未提交):允许你读取还未提交的改变了的数据。可能导致脏、幻、不可重复读
READ_COMMITTED(读已提交):允许在并发事务已经提交后读取。可防止脏读,但幻读和 不可重复读仍可发生
REPEATABLE_READ(可重复读):对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏、不可重复读,但幻读仍可能发生。
SERIALIZABLE(串行化):完全服从ACID的隔离级别,确保不发生脏、幻、不可重复读。这在所有的隔离级别中是最慢的,它是典型的通过完全锁定在事务中涉及的数据表来完成的。
@Transactional(isolation= Isolation.*READ_UNCOMMITTED*)
@Transactional(isolation= Isolation.*READ_COMMITTED*)
@Transactional(isolation= Isolation.*REPEATABLE_READ*)
@Transactional(isolation= Isolation.*SERIALIZABLE*)
@Transactional(isolation= Isolation.*DEFAULT*)
事务传播行为:多个事务方法相互调用时,事务如何在这些方法间传播
作用:事务的传播行为就是一个个的事务策略,根据需求、设备等条件选择对应的策略,从而完成需求或优化程序。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q89YJEQx-1598857978136)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image084.jpg)]
required:必须,支持当前事务,如果没有事务创建一个新的
a()如果有事务,b()直接使用
a()如果没有事务,b()创建一个新事务
supports:支持,支持当前事务,如果没有事务以非事务执行
a()如果有事务,b()直接使用
a()如果没有事务,b()以非事务执行
mandatory:强制,支持当前事务,如果没有事务抛异常
a()如果有事务,b()直接使用
a()如果没有事务,b()抛异常
requires_new:必须新的,必须创建一个新的事务
a()如果有事务,先将a()事务挂起,在为b()创建新事务
a()如果没有事务,为b()创建新事务
not_supported:不支持,不支持事务,以非事务执行执行
a()如果有事务,先将a()事务挂起,b()以非事务
a()如果没有事务,b()以非事务执行
never:从不,不支持事务,如果有事务抛异常
a()如果有事务,b()将抛异常
a()如果没有事务,b()以非事务执行
nested:嵌套,底层采用savepoint保存点,以嵌套事务进行执行
1.只开启了一个事务,Spring默认的传播行为是PROPAGATION_REQUIRED,即如果当前存在事务,即加入该事务;如果当前没有事务,则新建一个新的事务。因此只开启了一个事务。
l Spring事务的传播行为的7种类型
TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。
TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
@Transactional(propagation = Propagation.*REQUIRED*)
IoC:Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。Ioc意味着将你设计好的对象交给容器控制,而不是new。
IoC 控制反转,指将对象的创建权,反转到Spring容器
IOC容器就是具有依赖注入功能的容器,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。应用程序无需直接在代码中new相关的对象,应用程序由IOC容器进行组装。在Spring中BeanFactory是IOC容器的实际代表者。
1.减少代码的耦合,可以使应用更加模块化
2.增加代码的复用率
3.资源更加统一管理
4.维护代码更加方便,一般只需要修改一下配置文件就ok了。
5.提升了程序的测试性(更方便进行集成测试)
链接:https://www.imooc.com/article/35099
DI:Dependency Injection 依赖注入,在Spring框架创建Bean对象时,动态的将依赖对象注入到Bean组件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xVq1qcOc-1598857978140)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image086.jpg)]
1.实例化Bean对象:服务器启动时,初始化spring容器,创建由XML配置或添加了相应注解的类的实例,并将实例保存到Spring容器中;
2.完成ID操作:通过XML描述或对应注解,完成对象之间的依赖关系,此过程称为依赖注入,spring支持3种注入实现:
①注解注入:通过注解显示注入。常用注解@Resource。
②XML注入:通过xml显示注入。
③自动注入:隐式进行bean搜索并自动装配
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R4GHpqnv-1598857978145)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image088.jpg)]
IoC 控制反转,指将对象的创建权,反转到Spring容器 ,
DI 依赖注入,指Spring创建对象的过程中,将对象依赖属性通过配置进行注入
DI依赖注入不能单独存在,必须在IoC控制反转的基础上才能完成。
在web项目中配置Spring的Ioc容器其实就是创建web应用的上下文(WebApplicationContext)
1.如果使用Spring Boot,默认扫描启动类所在包以及子包,启动完成上下文对象创建完成。
2.使用注解的普通web项目,需要在配置类中使用@ComponentScan确定扫描包位置,启动完成上下文对象创建完成。
3.使用xml的普通web项目,需要在web.xml配置初始化参数确定xml文件位置,从而确定加载的内容,启动完成上下文对象创建完成。
参考:http://www.cnblogs.com/qf123/p/8488404.html
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uHoe8JFE-1598857978149)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image090.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gb3VX9Jn-1598857978154)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image092.jpg)]
1.单例设计模式:spring 容器中 bean默认是单例的。
2.工厂模式:BeanFactory,是spring管理bean的核。
3.代理模式:AOP通过代理对目标类进行增强;
4.适配器模式:将一个类的接口变换成客户所期待的另一种接口,从而使原本不匹配而无法一起工作的俩个类能够在一起工作;SpringMVC中的适配器HandlerAdatper,HandlerAdatper根据不同的handler规则执行不同的handler;
5.模板方法模式:父类定义了骨架(调用哪些方法及顺序),某些特定方法由子类实现;在Spring的 JdbcTemplate,RestTemplate, JmsTemplate等地方使用了模板方法模式;
参考:https://blog.csdn.net/z69183787/article/details/65628166
在spring中可以通过 HandlerInterceptor 处理器拦截器对程序进行拦截。
拦截之前调用 preHandler()方法,拦截时调用 postHandler() ,完成拦截后,调用 afterCompletion()方法
https://www.cnblogs.com/lyq-biu/p/11017106.html
AOP (Aspect Oriented Programing) 称为:面向切面编程,它是一种编程思想。在程序运行的时候,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。
基于代理思想,对原来目标对象,创建代理对象,在不修改原对象代码情况下,对原有业务方法进行增强 !
代理模式:分为静态代理、JDK动态代理、cglib代理
1.静态代理
代理类和被代理类实现共同的接口(或继承),代理类中存有指向被代理类的引用,实际执行时通过调用代理类的方法、实际执行的是被代理类的方法。
2.jdk动态代理:必须有接口和实现类(目标类),通过工具类Proxy生产接口对应的代理类,从而对目标类进行增强。
3.Cglib代理:Cglib代理生成的代理类是目标类的子类,所以目标类不能使用final修饰。
AOP
Spring AOP通过代理的方式,对目标类进行增强。
Spring aop底层默认使用JDK动态代理(必须有接口),通过配置可以修改成cglib代理。
l 静态代理:需要手动创建代理类,在new 代理类,获得代理实例
\1. 目标类: class 目标类 implements 接口{ 方法1(); 方法2(); }
\2. 代理类: class 代理类 implements 接口{
代理类( 目标类实例 )
方法1( 前增强; 目标类实例.方法1() ; 后增强; );
方法2();
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ONZ73knH-1598857978158)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image094.jpg)]
l JDK动态代理:采用JDK提供工具类,在程序【运行时】,创建出代理类的实例对象。
n 动态代理,属于反射的范畴,也就是在运行时(内存中)进行执行。
l cglib代理:字节码代理,在运行时,为目标类生成子类,让子类对父类进行增强。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uKa2p5xa-1598857978163)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image096.jpg)]
l 没有使用aop,service内存显示
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tfrzwVgC-1598857978166)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image098.jpg)]
l 如果有接口,采用JDK动态代理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-knwy97Qi-1598857978169)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image100.jpg)]
l 如果没有接口,采用cglib字节码代理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RY7wqRQ2-1598857978175)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image102.jpg)]
l 在yml文件中,可以设置强制使用cglib
n spring.aop.proxy-target-class = true ,使用cglib字节码代理
n spring.aop.proxy-target-class = false,进行JDK动态代理(前提:必须有接口)
spring:
aop:
proxy-target-class: true
描述切面必须先了解以下几个概念:
1.目标类:需要被增强的类。
2.连接点:可能被增强的点,目标类中的所有方法。
3.切入点:将会被增强的连接点,目标类中被增强的方法。
4.通知/增强:对切入点增强的内容。增强的内容通常以方法的形式体现的。增强执行的位置不同,称呼不同。
(前置通知、后置通知、环绕通知、抛出异常通知、最终通知)
通知方法所在的类,通常称为切面类。
5.切面:通知和切入点的结合。一个通知对应一个切入点就形成一条线,多个通知对应多个切入点形成多条线,多条线形成了一个面,我们称为切面。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nCeV0vIY-1598857978179)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image104.jpg)]
通知:对切入点增强的内容。增强的内容通常以方法的形式体现的。
在spring中根据增强执行位置的不同,将通知分成以下5种:
1.前置通知(before):在一个方法执行前被调用。
2.后置通知(after-returning):仅当方法成功完成后执行的通知。
3.环绕通知(around):在方法执行之前和之后调用的通知。
4.抛出异常通知(after-throwing):在方法抛出异常退出时执行的通知。
5.最终通知(after): 在方法执行之后调用的通知,无论方法执行是否成功。
l 实现细节,方便理解
try{
//1 前置通知
// 目标方法
//2 后置通知
} catch(){
//4 抛出异常通知
} finally{
//5 最终通知
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XO3naUN0-1598857978182)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image106.jpg)]
在说切入点前,需要先说连接点
连接点:可能被增强的点,目标类中的所有方法。
切入点:将会被增强的连接点,目标类中被增强的方法。
目标类:需要被增强的类。
AOP通过生成代理对象,对目标类进行增强。
在spring aop中,代理对象,将通知和切入点连接在了一起,从而实现增强的过程。
使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。
业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。
横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。
AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。
参考:https://www.cnblogs.com/hongwz/p/5764917.html
1.目标类(target):需要被增强的类。
2.连接点(Joinpoint):可能被增强的点,目标类中的所有方法。
3.切入点(Pointcut):将会被增强的连接点,目标类中被增强的方法。
4.通知/增强(Advice):对切入点增强的内容。增强的内容通常以方法的形式体现的。增强执行的位置不同,称呼不同。
(前置通知、后置通知、环绕通知、抛出异常通知、最终通知)
通知方法所在的类,通常称为切面类。
5.切面(Aspect):通知和切入点的结合。一个通知对应一个切入点就形成一条线,多个通知对应多个切入点形成多条线,多条线形成了一个面,我们称为切面。
6.织入(Weaving): 生成切面并创建代理对象的过程。(将通知和切入点的结合,并创建代理对象的过程)
7.引介(Introduction):一种特殊的增强
参考:https://www.cnblogs.com/hongwz/p/5764917.html
1.事务
2.日志处理
3.缓存
4.权限控制
5.错误处理
6.懒加载
链接:http://blog.sina.com.cn/s/blog_7045cb9e01010a9r.html
https://blog.csdn.net/qq513165077/article/details/78288999
IoC控制反转:指将对象的创建权,反转到Spring容器
方式1:创建工厂
创建一个工厂,用于创建目标对象,就是最简单的IoC。但工厂和目标类耦合。
方式2:工厂 + 配置文件
1)配置文件中存放类的全限定名称
2)编写工厂,用于读取配置文件中的内容,并通过反射创建对象。
问题:工厂只能生产一个对象
方式3:工厂 + properties文件
1)properties配置文件存放一组,key是标识,value是全限定名称
2)编写工厂类,读取配置文件
3)提供getBean( name ) 用于生成实例:通过name获得对应的全限定名称,再通过反射创建对应的实例。
package com.czxy.xuecheng.factory;
import com.czxy.xuecheng.service.AopService;
import com.czxy.xuecheng.service.impl.AopServiceImpl;
/*
* Created by liangtong.
*/
* public class MyFactory {
public static AopService create(){
return new AopServiceImpl();
}
public static void main(String[] args) {
*//**自己new
* AopService aopService = new AopServiceImpl();
*//**工厂new
* AopService aopService2 = MyFactory.create();
}
}
mybatis是一个持久层ORM框架。它内部封装了jdbc,使得开发更简洁,更高效。
Mybatis使开发者只需要关注sql语句本身,简化JDBC操作,不需要在关注加载驱动、创建连接、处理SQL语句等繁杂的过程。
MyBatis可以通过xml或注解完成ORM映射关系配置。
l ORM框架:对象关系映射框架,Java的JavaBean (对象)与数据库的表(关系) 之间的对应关系。通过对象可以直接操作表。save(User) --> 用户数据进入表中
@Select(“select * from t_user ”)
public List findAll()
JDBC是Java提供的一个操作数据库的API; MyBatis是一个持久层ORM框架,底层是对JDBC的封装。
MyBatis对JDBC操作数据库做了一系列的优化:
(1) mybatis使用已有的连接池管理,避免浪费资源,提高程序可靠性。
(2) mybatis提供插件自动生成DAO层代码,提高编码效率和准确性。
(3)mybatis 提供了一级和二级缓存,提高了程序性能。
(4) mybatis使用动态SQL语句,提高了SQL维护。(此优势是基于XML配置)
(5) mybatis对数据库操作结果进行自动映射
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H46xPeAU-1598857978186)(file:///C:/Users/20297/AppData/Local/Temp/msohtmlclip1/01/clip_image108.jpg)]
ORM的全称是Object Relational Mapping,即对象关系映射。
描述的是对象和表之间的映射。操作Java对象,通过映射关系,就可以自动操作数据库。
在ORM关系中,数据库表对应Java中的类,一条记录对应一个对象,一个属性对应一个列。
常见的ORM框架:Mybatis、Hibernate
注解、XML
l MyBatis 注解版增删改查
n 通常增删改使用通过mapper,@Insert等注解很少使用
@Select()
@Insert()
@Update()
@Delete()
l 多表关系映射
@Results({
@Result( property=”属性” , column=”列”)
})
1.#{}实现的是sql语句的预处理参数,之后再sql中用?号代替,使用时不需要关注数据类型,Mybatis自动实现数据类型的转换,并且可以防止SQL注入;
2.${}实现的是sql语句的直接拼接,不做数据类型转换,需要自行判断数据类型,不能防止SQL注入;
3.在某些特定情况下必须使用 , 如 : 在 分 表 存 储 的 情 况 下 , 对 哪 张 表 的 查 询 是 不 确 定 的 , 也 就 是 s q l 语 句 不 能 写 死 , 表 明 是 动 态 的 , 查 询 条 件 是 固 定 的 , 此 时 表 明 只 能 使 用 {},如:在分表存储的情况下,对哪张表的查询是不确定的,也就是sql语句不能写死,表明是动态的,查询条件是固定的,此时表明只能使用 ,如:在分表存储的情况下,对哪张表的查询是不确定的,也就是sql语句不能写死,表明是动态的,查询条件是固定的,此时表明只能使用{}方式进行字符串拼接,这样:slect * from ${tableName} where id = #{id}
总结:#{}占位符,用于参数传递; ${}用于SQL拼接
\1. 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致
2.使用通用Mapper时,可以通过@Column注解设置
3.如果进行自定义查询,可以通过@Result进行设置
【了解】4.如果使用的xml配置,通过进行配置
1.使用通用Mapper的Criteria进行like语句的拼凑
2.使用#{}占位符方式,参数前后拼凑%。(select * from t_user where username like #{username} ,username数据为"%jack%")
【了解】3.使用 字 符 串 拼 接 方 式 , 可 能 引 发 s q l 注 入 问 题 : s e l e c t ∗ f r o m t u s e r w h e r e u s e r n a m e l i k e ′ {}字符串拼接方式,可能引发sql注入问题:select * from t_user where username like '% 字符串拼接方式,可能引发sql注入问题:select∗fromtuserwhereusernamelike′{username}%’
Example example = new Example(Film.class);
Example.Criteria criteria = example.createCriteria();
criteria.andLike(“username”,“x”);
Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行接口方法所对应的MappedStatement所代表的sql,然后将sql执行结果返回。
MappedStatement解释:MappedStatement维护了一条
select id, username from author where id = #{value}
Dao接口在使用时,MyBatis创建接口对应的代理类。
在调用对应的方法时,执行的是代理类对应的方法。
代理类的方法上添加的注解完成增删改查的操作,如果是查询将结果封装到方法返回值类型声明的对象中。
不能重载的,
因为是全限定名+方法名的必须唯一。
l XML id值和dao 方法名,进行匹配,要求必须唯一
select * from…
使用第三方分页助手:PageHelper
使用方式:
在将要执行查询sql语句之前使用分页助手:PageHelper.startPage(pageNum:页码, pageSize:每页显示数量);
使用MyBatis插件(也称为拦截器)机制,对需要使用分页的功能进行增强。也就是重写SQL,根据不同的数据库生产不同的分页语句。
Mysql生成limit语句,Oracle借助rownum生成对应子查询语句。
提供POJO和表之间的映射关系,查询结果就可以完成封装。
1.使用通用Mapper,需要在POJO上字段上使用@Column注解
2.如果是自定义查询,需要通过Dao接口里使用@Result注解
3.如果是xml,需要使用配置映射关系
动态SQL标签主要是基于XML进行配置的,在校主要学习的是注解,没有使用过XML。
不过注解也支持部分动态标签,@Select("")
不同的Xml映射文件,如果配置了namespace,那么id可以重复;如果没有配置namespace,那么id不能重复。MyBatis通过namespace+id来进行不同XML标识。
Hibernate是全自动的ORM框架,也就是使用hibernate不用编写任何SQL语句。关联对象直接调用对应方法,可以自动完成数据的查询。
MyBatis封装了JDBC基本操作,但仍需要编写SQL语句,也称为半自动ORM框架。使用通过Mapper可以简化MyBatis单表操作,多表仍需要自己编写SQL语句。
namespace用于标识不同的XML配置文件。这样不同xml文件中sql语句的id相同也不会有冲突。
注解开发没有类似要求,只要保证接口全限定名不同即可(包+类名)
在xml配置文件,根据数据的不同,动态拼凑对应的SQL语句。
例如:
用于处理条件成立时显示部分SQL语句
如果有条件就显示 where 子句,如果没有条件则不显示。
Mybatis的缓存机制分为一级缓存和二级缓存
1.一级缓存:一级缓存的作用域是sqlSession会话级,相当于JDBC的Connection连接。一级缓存默认开启,用户不能手动配置。当在同一个sqlSession中执行两次相同的sql语句时,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次查询时会从缓存中获取数据,不再去底层数据库查询,从而提高查询效率;
2.二级缓存:二级缓存的作用域为同一个mapper的namespace,是跨sqlSession的,同一个namespace中不同的查询SQL可以从二级缓存中命中。二级缓存默认关闭,但是可以通过配置进行开启。
二级缓存的对象必须序列化,例如:User对象必须实现Serializable接口。
er> findAll()
JDBC是Java提供的一个操作数据库的API; MyBatis是一个持久层ORM框架,底层是对JDBC的封装。
MyBatis对JDBC操作数据库做了一系列的优化:
(1) mybatis使用已有的连接池管理,避免浪费资源,提高程序可靠性。
(2) mybatis提供插件自动生成DAO层代码,提高编码效率和准确性。
(3)mybatis 提供了一级和二级缓存,提高了程序性能。
(4) mybatis使用动态SQL语句,提高了SQL维护。(此优势是基于XML配置)
(5) mybatis对数据库操作结果进行自动映射
[外链图片转存中…(img-H46xPeAU-1598857978186)]
ORM的全称是Object Relational Mapping,即对象关系映射。
描述的是对象和表之间的映射。操作Java对象,通过映射关系,就可以自动操作数据库。
在ORM关系中,数据库表对应Java中的类,一条记录对应一个对象,一个属性对应一个列。
常见的ORM框架:Mybatis、Hibernate
注解、XML
l MyBatis 注解版增删改查
n 通常增删改使用通过mapper,@Insert等注解很少使用
@Select()
@Insert()
@Update()
@Delete()
l 多表关系映射
@Results({
@Result( property=”属性” , column=”列”)
})
1.#{}实现的是sql语句的预处理参数,之后再sql中用?号代替,使用时不需要关注数据类型,Mybatis自动实现数据类型的转换,并且可以防止SQL注入;
2.${}实现的是sql语句的直接拼接,不做数据类型转换,需要自行判断数据类型,不能防止SQL注入;
3.在某些特定情况下必须使用 , 如 : 在 分 表 存 储 的 情 况 下 , 对 哪 张 表 的 查 询 是 不 确 定 的 , 也 就 是 s q l 语 句 不 能 写 死 , 表 明 是 动 态 的 , 查 询 条 件 是 固 定 的 , 此 时 表 明 只 能 使 用 {},如:在分表存储的情况下,对哪张表的查询是不确定的,也就是sql语句不能写死,表明是动态的,查询条件是固定的,此时表明只能使用 ,如:在分表存储的情况下,对哪张表的查询是不确定的,也就是sql语句不能写死,表明是动态的,查询条件是固定的,此时表明只能使用{}方式进行字符串拼接,这样:slect * from ${tableName} where id = #{id}
总结:#{}占位符,用于参数传递; ${}用于SQL拼接
\1. 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致
2.使用通用Mapper时,可以通过@Column注解设置
3.如果进行自定义查询,可以通过@Result进行设置
【了解】4.如果使用的xml配置,通过进行配置
1.使用通用Mapper的Criteria进行like语句的拼凑
2.使用#{}占位符方式,参数前后拼凑%。(select * from t_user where username like #{username} ,username数据为"%jack%")
【了解】3.使用 字 符 串 拼 接 方 式 , 可 能 引 发 s q l 注 入 问 题 : s e l e c t ∗ f r o m t u s e r w h e r e u s e r n a m e l i k e ′ {}字符串拼接方式,可能引发sql注入问题:select * from t_user where username like '% 字符串拼接方式,可能引发sql注入问题:select∗fromtuserwhereusernamelike′{username}%’
Example example = new Example(Film.class);
Example.Criteria criteria = example.createCriteria();
criteria.andLike(“username”,“x”);
Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行接口方法所对应的MappedStatement所代表的sql,然后将sql执行结果返回。
MappedStatement解释:MappedStatement维护了一条
select id, username from author where id = #{value}
Dao接口在使用时,MyBatis创建接口对应的代理类。
在调用对应的方法时,执行的是代理类对应的方法。
代理类的方法上添加的注解完成增删改查的操作,如果是查询将结果封装到方法返回值类型声明的对象中。
不能重载的,
因为是全限定名+方法名的必须唯一。
l XML id值和dao 方法名,进行匹配,要求必须唯一
select * from…
使用第三方分页助手:PageHelper
使用方式:
在将要执行查询sql语句之前使用分页助手:PageHelper.startPage(pageNum:页码, pageSize:每页显示数量);
使用MyBatis插件(也称为拦截器)机制,对需要使用分页的功能进行增强。也就是重写SQL,根据不同的数据库生产不同的分页语句。
Mysql生成limit语句,Oracle借助rownum生成对应子查询语句。
提供POJO和表之间的映射关系,查询结果就可以完成封装。
1.使用通用Mapper,需要在POJO上字段上使用@Column注解
2.如果是自定义查询,需要通过Dao接口里使用@Result注解
3.如果是xml,需要使用配置映射关系
动态SQL标签主要是基于XML进行配置的,在校主要学习的是注解,没有使用过XML。
不过注解也支持部分动态标签,@Select("")
不同的Xml映射文件,如果配置了namespace,那么id可以重复;如果没有配置namespace,那么id不能重复。MyBatis通过namespace+id来进行不同XML标识。
Hibernate是全自动的ORM框架,也就是使用hibernate不用编写任何SQL语句。关联对象直接调用对应方法,可以自动完成数据的查询。
MyBatis封装了JDBC基本操作,但仍需要编写SQL语句,也称为半自动ORM框架。使用通过Mapper可以简化MyBatis单表操作,多表仍需要自己编写SQL语句。
namespace用于标识不同的XML配置文件。这样不同xml文件中sql语句的id相同也不会有冲突。
注解开发没有类似要求,只要保证接口全限定名不同即可(包+类名)
在xml配置文件,根据数据的不同,动态拼凑对应的SQL语句。
例如:
用于处理条件成立时显示部分SQL语句
如果有条件就显示 where 子句,如果没有条件则不显示。
Mybatis的缓存机制分为一级缓存和二级缓存
1.一级缓存:一级缓存的作用域是sqlSession会话级,相当于JDBC的Connection连接。一级缓存默认开启,用户不能手动配置。当在同一个sqlSession中执行两次相同的sql语句时,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次查询时会从缓存中获取数据,不再去底层数据库查询,从而提高查询效率;
2.二级缓存:二级缓存的作用域为同一个mapper的namespace,是跨sqlSession的,同一个namespace中不同的查询SQL可以从二级缓存中命中。二级缓存默认关闭,但是可以通过配置进行开启。
二级缓存的对象必须序列化,例如:User对象必须实现Serializable接口。
Mybatis中,执行select时,查询数据会被缓存;当执行insert、update、delete等操作的时候,缓存则会被清除
7.1.1 MVVM中,M V VM分别表示什么?作用是什么?
总结:MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版。(1-2分)
主要目的是分离视图(View)和模型(Model),在通过ViewModel视图模型将V和M连接起来。
模型Model发生变化,通过MVVM框架自动更新视图View的状态。
视图View发生变化,通过MVVM框架自动更新模型Model的数据。
7.1.2 简述什么是单页,以及单页的优缺点
单页Web应用(single page web application,SPA),就是只有一张Web页面的应用,是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序。
单页面的优点:
1,用户体验好,快,内容的改变不需要重新加载整个页面,基于这一点spa对服务器压力较小
2,前后端分离
3,页面效果会比较炫酷(比如切换页面内容时的专场动画)
单页面缺点:
1,不利于seo
2,导航不可用,如果一定要导航需要自行实现前进、后退。(由于是单页面不能用浏览器的前进后退功能,所以需要自己建立堆栈管理)
3,初次加载时耗时多
4,页面复杂度提高很多
7.1.3 Vue中的src文件夹一般都是放置哪些文件/文件夹?
src目录为前端开发的源码目录。
1)assets:文件夹用来放置静态资源目
2)components:功能组件
3)views:页面组件
4)router:路由文件
5)store:vuex的数据
6)app.vue:首页,初始化页面
7)main.js:入口文件
7.1.4 简述Vue中的生命周期函数(钩子函数)以及作用?
Vue实例从创建到销毁的过程,就是生命周期。
生命周期钩子函数共8个,分别是:
1 beforeCreate: 初始化前
2 created: 初始化完成,一般完成“页面加载成功后”的相关操作
3 beforeMount:挂载前,双向数据绑定前
4 mounted:挂载完成,双向数据绑定完成
5 beforeUpdate:更新前
6 updated: 更新完成
7 beforeDestroy: 销毁前
8 destroyed: 销毁完成
7.1.5 前后台分离,跨域问题如何解决?
1.使用Nginx代理:Nginx统一程序入口,通过Nginx分发到不同的服务。
2.JSONP,通过
7.1.6 Vue-router作用是什么
Vue Router 是 Vue.js 官方的路由管理器。
作用是:
7.1.7 Vue中父子组件之间的传值是怎么实现的?
1)父组件向子组件传递,子组件使用props接收父组件传递的数据。(自定义属性)
2)子组件向父组件传值,子组件通过 e m i t ( ) 触 发 父 组 件 的 事 件 , 父 组 件 通 过 v − o n 绑 定 的 函 数 函 数 接 收 值 。 ( 自 定 义 事 件 ) 3 ) 非 父 子 组 件 之 间 传 值 , 使 用 公 共 文 件 ( B u s / E v e n t B u s ) 。 7.1.8 V u e 中 , 路 由 如 何 传 参 , 如 何 获 取 路 由 传 递 的 参 数 ? 1. 方 式 1 : 请 求 参 数 , / u s e r ? i d = 123 路 由 的 路 径 < r o u t e r − l i n k t o = " / u s e r ? i d = 1234 " > < / r o u t e r − l i n k > 参 数 的 获 取 : t h i s . emit()触发父组件的事件,父组件通过v-on绑定的函数函数接收值。(自定义事件) 3)非父子组件之间传值,使用公共文件(Bus/EventBus)。 7.1.8 Vue中,路由如何传参,如何获取路由传递的参数? 1. 方式1:请求参数,/user?id=123 路由的路径
2. 方式2:路由参数、 /user/1234
路由的路径
路由的配置:{ path: ‘/user/:id’ }
参数的获得:this.$route.params.id
7.1.9 Vuex怎么实现数据共享的?
1. vue整合vuex,在main.js文件中,vue以组件的方式导入store/index.js
2. 将数据存放到 store.js 的 state 区域,任何位置都可以引用。
3. 通过store.js的 mutations可以对state区域的数据进行更新。
通过读写最终达到数据的共享。
7.1.10 Vue全家桶有哪些?
答:Vue两大核心思想:组件化和数据驱动。组件化:把整体拆分为各个可以复用的个体,数据驱动:通过数据变化直接影响dom展示,避免dom操作。
1)Vue-cli是快速构建这个单页应用的脚手架。
2)vue-router路由,组件之间的切换。
3)Vuex数据管理。
4)axios是一个http请求包,vue官网推荐使用axios进行http调用。(ajax操作)
7.1.11 Vue的导航守卫是什么?有什么作用?
答:vue-router 提供的导航钩子主要用来拦截导航,让它完成跳转或取消。有多种方式可以在路由导航发生时执行钩子:全局的、单个路由独享的、组件级别的。
1、全局钩子
router.beforeEach 注册一个全局的 before 钩子
2、某个路由独享的钩子
在路由配置上直接定义 beforeEnter 钩子
3、组件内的钩子
beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave,在路由组件内直接定义路由导航钩子
https://router.vuejs.org/zh/guide/advanced/navigation-guards.html
7.1.12 Vuex的五大核心属性是什么?
答:VueX 是一个专门为 Vue.js 应用设计的状态管理架构。
Vue有五个核心概念,state, getters, mutations, actions, modules。
state => 所有共享的数据在此处定义
getters => 根据state组装数据
mutations =>同步方法!
actions => 异步方法。
modules => 分模块开发
-----------ES6--------
7.1.13 var、let、const用法和区别
答:var是es3中定义变量的关键字,定义全局变量
let是es6中新增的关键字,定义局部变量
const是定义常量
7.1.14 字符串的方法有哪些?各代表什么意思?
答:
indexOf: 返回字符串的索引
lastIndexOf: 返回字符串的最后的索引
substr (i,v): 从第i个索引开始截取v个长度的字符
substring(i,v): 从第i个位置截取到第v个位置(不包含v)
Length: 获取字符串长度
charAt(i): 获取第i个位置的字符
Includes: 返回布尔值,表示是否找到了参数字符串
startsWith: 返回布尔值,表示参数字符串是否在原字符串的头部
endsWith: 返回布尔值,表示参数字符串是否在原字符串的尾部。
7.1.15 Vue中有哪些指令?
答:v-if:条件判断。当得到结果为true时,所在的元素才会被渲染
v-model:是双向绑定,视图(View)和模型(Model)之间会互相影响。
v-on: 用于给页面元素绑定事件
v-for: 遍历数组
v-show: v-show 只是简单地切换元素的 CSS 属性 display
v-bind: 绑定class样式 v-bind:class简写为:class
7.1.16 Vue中有哪些事件修饰符,各代表什么作用?
.stop// 停止触发,阻止冒泡修饰符
.prevent // 阻止事件发生,阻止事件默认行为
.capture // 捕获
.self //只点自己身上才运行
.once // 只执行一次
7.1.17
7.1.18 Vue中有哪些按键修饰符,各代表什么作用
.enter // 表示键盘的enter键
.tab
.delete (捕获 “删除” 和 “退格” 键)
.esc
.space
.up
.down
.left
.right
.ctrl
.alt
.shift
.meta
7.1.19 什么是js的冒泡事件?
当前标签的某事件触发后,将依次触发当前标签父标签对应的事件,直到页面的根标签。
7.1.20 什么是计算属性?你是如何理解计算属性的?
• 计算属性本质就是一个有返回值的方法,在页面渲染时,可以把这个方法当成一个变量来使用。
• data区域中的数据没有发生更改时,计算属性直接读取缓存。
7.1.21 import、export导入导出
ES6标准中,Module模块功能主要由两个命令构成:import 和 export。
export用于对外输出本模块(一个文件可以理解为一个模块)变量的接口
import用于在一个模块中加载另一个含有export接口的模块
4 Eureka的工作原理
• Eureka:就是服务注册中心(可以是一个集群),对外暴露自己的地址
• 提供者:启动后向Eureka注册自己信息(地址,提供什么服务)
• 消费者:向Eureka订阅服务,Eureka会将对应服务的所有提供者地址列表发送给消费者,并且定期更新
• 心跳(续约):提供者定期通过http方式向Eureka刷新自己的状态
5 什么是服务注册
服务提供者在启动时,会向EurekaServer发起一次请求,将自己注册到Eureka注册中心中去
6 什么是服务续约
在注册服务完成以后,服务提供者会维持一个心跳(每30s定时向EurekaServer发起请求),告诉EurekaServer:“我还活着”。这个我们称为服务的续约(renew);
7 什么是失效剔除
有些时候,我们的服务提供方并不一定会正常下线,可能因为内存溢出、网络故障等原因导致服务无法正常工作。Eureka Server需要将这样的服务剔除出服务列表。因此它会开启一个定时任务,每隔60秒对所有失效的服务(超过90秒未响应)进行剔除。
8 什么是自我保护
当一个服务未按时进行心跳续约时,在生产环境下,因为网络延迟等原因,此时就把服务剔除列表并不妥当,因为服务可能没有宕机。Eureka就会把当前实例的注册信息保护起来,不予剔除。生产环境下这很有效,保证了大多数服务依然可用。
2 什么是有状态?
答:使用session和cookie登录的时候,用户的登录信心保存在服务器的session中,然后将sessionId送到客户端,保存到cookie中,此时服务端通过session标记当前的请求,这就是有状态。
缺点:
3 什么是无状态?
'- 特点
5 SpringBoot和Spring cloud的区别
1.springboot可以单独使用,它不依赖于springcloud
而springcloud必然依赖于springboot,属于依赖关系。
2. Springboot专注于快速方便的开发单个个体服务。
3. SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并管理起来,为各个微服务之间提供,配置管理、服务发现、断路器、路由、等集成服务。
6 HttpClient/RestTemplate和feign的区别
1 相同点:都是远程调用技术,都是系统间相互调用的技术
2 不同点: