JVM会将申请到的内存从逻辑上划分为三个区域:堆、栈、方法区。这三个区域分别用于存储不同的数据。
1.堆:用于存储使用new关键字所创建的对象以及对象的属性成员变量。
2.栈:用于存储程序运行时在方法中声明的所有的局部变量。
3.方法区:方法区存储静态资源,以及类的信息,随类的加载而加载,不手动卸载就会一直存在;
成员变量:
第二种:
1.1程序计数器:是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器,各条线程之间计数器互不影响,独立存储。
1.2虚拟机栈:它描述的是 Java 方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧(Stack Frame,是方法运行时的基础数据结构)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
1.3本地方法栈:它与虚拟机栈所发挥的作用是非常相似的,它们之间的区别不过是虚拟机栈为虚拟机执行 Java 方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的 Native 方法服务。
1.4Java 堆:它是 Java 虚拟机所管理的内存中最大的一块。Java 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。
1.5方法区:它与 Java 堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
垃圾回收区 cms回收的过程?
有四个阶段,第一个初始标记找那个GC root(可达性算法)直接引用对象,然后还有一个就是并发标记,就是会跟那个系统线程可以一快运行的,不会出现系统暂停的情况,这阶段会有点耗时去追诉GC root 的那个引用链表,进行标记啊
3.第三个阶段就是整理标记,
1.创建一个新对象,会把这个新对象的实例放在新生代的Eden区域,当Eden区空间不足,无法保存创建新的对象时则会触发MinerGC进行清理
2.当经过一次MinorGC进行清理后Eden区还存活的一些对象会通过复制算法把它复制到Survivor区(存活区)的from 区(原to区).
3.Survivor区的两块区域是相同大小的两块区域,是可以互相交换的,交换以后form的叫to,to的叫from,交换的过程中会把其中一个的对象复制到另外一个,保证有一个是空的。
–经历一次MinorGC,如果Eden区有对象被保存到Survivor区的原to区时,然后对原from区域中进行一次清理,把清理后还依然存活的对象复制到原to区,然后把原to区更名为from区,把原form区更名为to区,这样就保证每次to区都是空的
4.当原from区进行MinorGC进行清理后往原to区进行复制的时候,原to区复制一部分对象后满了的情况下,会将原form区的剩余对象复制到老年代区域.
–另外Survivor区中的对象每熬过一次MinorGC年龄就会增长一次,还可以通过设置年龄阈值参数:-XX:MaxTenuringThreshold,当年龄增到到我们设定的阈值时,将该对象直接复制到老年代中.
5.老年代区域没有可用空间时会触发Full GC,Full GC会扫描整个老年代区域将还存活的对象进行标记,然后把不存活的对象进行清除.
优点:空间内存活对象多的情况下,效率高.
缺点:直接回收不存活对象所占用的内存空间,回收后造成整个空间不连贯,产生内存碎片.
封装,继承,多态
封装:把描述一个对象的属性和行为封装成一个类,把具体的业务逻辑功能实现封装成一个方法,其次封装的意义还有效的保护属性通过访问修饰符私有化属性(成员变量),公有化方法.
继承:实现代码的复用,所有的子类所共有的行为和属性抽取为一个父类,所有的子类继承该类可具备父类的属性和行为,继承具有单一性和传递性.
多态:程序中定义的引用类型变量所指向的具体类型和调用具体的方法在编译期无法确定,而是在运行期才能确定该引用类型变量指向具体哪个对象而调用在哪个类中声明的方法.
多态的表现形式有强制类型转换,向上造型等,多态可分为行为多态和对象多态:
行为多态 – 方法重写:同一个run(){}方法,不同的对象调用时会有不同的实现,猫调用时是跑,鱼调用时是游,鸟调用时是飞.
对象多态 – 实现接口(多实现,实现多个接口,可以具有不同的类型):同一个对象,可以被造型为不同的类型,比如同一个人对象,可以被造型为儿子,父亲,员工等
Overload是重载的意思,Override是覆盖的意思,也就是重写。
重载Overload表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同(即参数个数或类型不同)。
重写Override表示子类中的方法可以与父类中的某个方法的名称和参数完全相同,通过子类创建的实例对象调用这个方法时,将调用子类中的定义方法,这相当于把父类中定义的那个完全相同的方法给覆盖了,这也是面向对象编程的多态性的一种表现。两同(方法名.参数列表)两小(引用类型\抛出异常)一大[访问权限]
含有abstract修饰符的class即为抽象类,抽象类不能创建的实例对象。含有抽象方法的类必须定义为abstract class.
接口(interface)可以说成是一种特殊的抽象类,接口中的所有方法都必须是抽象的。接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final。
下面比较一下两者的语法区别:
a)抽象类可以有构造方法,接口中不能有构造方法。
b)抽象类中可以有普通成员变量,接口中没有普通成员变量
c)抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
d)抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然eclipse不报错,但也不行,默认类型子类不能继承),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型.
e)抽象类中可以包含静态方法,接口中JDK1.8之前不可以有不能包含静态方法和成员方法,JDK1.8之后可以包含.但成员方法必须使用default修饰
f)抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。
g)一个类可以实现多个接口,用逗号隔开,但只能继承一个抽象类,接口不可以实现接口,但可以继承接口并且可以继承多个接口,用逗号隔开.
在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。
在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。
总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。
咯!
在switch(expr1)中,expr1只能是一个整数表达式,整数表达式可以是int基本类型或Integer包装类型,由于byte,short,char都可以自动转换成int型,所以可以使用.
long类型由于不能自动转换成int类型,所以不能使用.
关于字符串类型,在JDK是1.7版本之前,swicth case中不可以使用字符串,但在JDK1.7之后是可以用字符串的,这是最新版本新加入的特性.
String有length()这个方法。
Array(数组)有length的属性。
集合没有length()方法,有size()方法。
比较基本数据类型时比较的时值是否相等,比较引用类型时比较的是对象的地址值是
否相同,也就是否是同一对象。
(1) 未重写的equals方法调用的是Object的方法,用法一样,重写后的equals方法是用
于比较两个独立对象的内容是否相同,就好比去比较两个人的长相是否相同,它比较的
两个对象是独立的。例如对于下面的代码:
String a=new String(“foo”);
String b=new String(“foo”);
两条new语句创建了两个对象,然后用a和b这两个变量分别指向了其中一个对象,
这是两个不同的对象,它们的地址是不同的,所以表达式a==b将返回false,而这两
个对象中的内容是相同的,所以,表达式a.equals(b)将返回true.
String这个类重写过equals方法, StringBuffer,StringBuilder未重写过equals方法.
再以上基础上又String str1=new String(“abc”);一共创建几个对象?
创建了两个对象,一个str引用指向堆内存中的String对象,另外一个则是String类有参构造方法中的直接量字符串对象,该字符串对象在字符串常量池中.
如果在执行一次String str1=new String(“abc”);此时共创建了几个对象?
因为在第一次常量池中已经有一个"abc"字符串对象,第二个创建时并没有创建新的,而是拿过来直接用,只是创建了1个str1指向堆内存中的String对象,共3个。
字符串有第一个是数组,第二个可以传你想变得类型;
Integer i3=Integer.valueOf(127);Integer i4=Integer.valueOf(127);
i3==i4结果为true还是false?
是引用类型取的地址值从Integer缓存区拿出来的 第一个是true 第二个是是fasle记住缓存区范围是-127~-128之间
String类是final修饰的,该类所表示的字符串对象不可变,一旦发生改变即创建新对象, 当我们通过字面量,常量来初始化一个字符串时,JVM首先会从字符串的常量池(一个JVM内部维护的内存区域,用来保存已经创建过的字符串对象)中查询用来保存该字符串的对象是否存在,若存在则直接引用,若不存在则创建该字符串对象并存入常量池,然后引用它.
StringBuffer和StringBuilder是可变字符串对象,对字符串的修改操作不会创建新对象,都是在原有对象基础上进行修改,内部有很多操作字符串的方法,比如append()等.另外StringBuffer是线程安全的,同步处理的,性能稍慢;StringBuilder是非线程安全的,并发处理的,性能稍快。
List是可重复集合,Set是不可重复集合,这两个接口都实现了Collection(克莱克神)父接口.
Map未继承Collection,而是独立的接口, Map是一种把键对象和值对象进行映射的集合,
它的每一个元素都包含了一对键对象和值对象, Map中存储的数据是没有顺序的,
其key是不能重复的,它的值是可以有重复的。
List的实现类有ArrayList, Vector和LinkedList.
ArrayList和Vector内部是线性动态数组结构,在查询效率上会高很多,Vector是线程安全的,相比ArrayList线程不安全的,性能会稍慢一些.
LinkedList:是双向链表的数据结构存储数据,在做查询时会按照序号索引数据进行前向或后向遍历,查询效率偏低,但插入数据时只需要记录本项的前后项即可,所以插入速度较快。
Set的实现类有HashSet和TreeSet;
HashSet: 内部是由哈希表(实际上是一个 HashMap 实例)支持的。它不保证 set元素的迭代顺序.
TreeSet: TreeSet使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序.
Map接口有三个实现类:Hashtable,HashMap,TreeMap,LinkedHashMap,concurrenthashmap
Hashtable: 内部存储的键值对是无序的是按照哈希算法进行排序,与HashMap最大的区别就是线程安全.键或者值不能为null,为null就会抛出空指针异常
HashMap: 内部存储的键值对是无序的是按照哈希算法进行排序,与Hashtable最大的区别就是非线程安全的,键或值可以为null
TreeMap: 基于红黑树(red-black tree)数据结构实现, 按 key 排序,默认的排序方式是升序.
LinkedHashMap:有序的Map集合实现类,相当于一个栈,先put进去的最后出来,先进后出.
concurrenthashmap:(代替hashtable 安全 效率高、多锁代替它的单锁)多用于多线程高并发
底层实现的原离:采用分段锁设,计将一个大的hashmap集合拆分成n多个不同小的hashtable,默认是分成16个不同的Segment(赛哥门特)存放;
数据结构:jdk1.8取消了Segment(赛哥门特)分段锁的数据结构,取而代之的是数组+链表+红黑树的结构。
2.保证线程安全机制:JDK1.7采用segment的分段锁机制实现线程安全,其中segment继承自Reentrant{瑞安催的}Lock。
JDK1.8采用CAS+Synchronized保证线程安全。
3.锁的粒度:原来是对需要进行数据操作的Segment加锁,现调整为对每个数组元素加锁(Node)。
4.链表转化为红黑树:定位结点的hash算法简化会带来弊端,Hash冲突加剧,因此在链表节点数量大于8时,会将链表转化为红黑树进行存储。
5.查询时间复杂度:从原来的遍历链表O(n),变成遍历红黑树O(logN)。
List的实现类有ArrayList, Vector和LinkedList。
ArrayList和Vector内部是线性动态数组结构,在查询效率上会高很多,Vector是线程安全的,相比ArrayList线程不安全的,性能会稍慢一些.
LinkedList:是双向链表的数据结构存储数据,在做查询时会按照序号索引数据进行前向或后向遍历,查询效率偏低,但插入数据时只需要记录本项的前后项即可,所以插入速度较快。
1.)HashMap: 内部存储的键值对是{无序、散列存放的}的是按照哈希算法进行排序,与Hashtable最大的区别就是非线程安全的,键或值可以为null
2.)Hashtable: 内部存储的键值对是无序的是按照哈希算法进行排序,与HashMap最大的区别就是线程安全.键或者值不能为null,为null就会抛出空指针异常
1.使用put方法向HashMap存储数据,key会计算出一个hashcode值,然后再使用hash算法,计算出一个地址值,如果这个地址值的桶中没有数据,就直接将value值存储再这里,
如果已经有值,会使用equals方法,对地址值进行比较,如果地址值相同,就会将原先的value值替换掉,不相等,则将这个值挂载到原先值的后面,形成链表。
4)产生链表会影响查询效率,所以被存入的键值对对象都会重写equals和hashcode方法,但链表不能完全避免,原因是可能存在巧合key不相同但HashCode值相同.
1.7版本底层基于数组+链表实现根据key的hash值计算该key存放在数组的index位置如果发生index冲突则会使用单向链表存放;
1.8版本底层基于数组+链表+红黑树实现,当数组的容量大于等于64且链表长度大于8则会将链表转化为红黑树;
1.7hashmap集合中当我们发生hash冲突则会存放在同一个链表中当链表的查询长度过长会导致查询效率低,因为采用链表存放查询的时间复杂度o(N)从头查到尾部
在jdk1.8开始优化,当数组的容量大于等于64且链表长度大于8则会将链表转化为红黑树,红黑树的时间复杂度为O(logN)。性能有所提升
concurrenthashmap:
扩容
jdk8中,采用多线程扩容。整个扩容过程,通过CAS设置sizeCtl,transferIndex等变量协调多个线程进行并发扩容。
多线程无锁扩容的关键就是通过CAS设置sizeCtl与transferIndex变量,协调多个线程对table数组中的node进行迁移。
它到底是如何实现线程安全的?
答案:采用了 CAS + synchronized 来保证并发安全性。
synchronized属于悲观锁,悲观的认为程序中的并发情况严重,所以严防死守,CAS属于乐观锁,乐观地认为程序中的并发情况不那么严重,所以让线程不断去重试更新。
CAS的缺点:
1) CPU开销过大
在并发量比较高的情况下,如果许多线程反复尝试更新某一个变量,却又一直更新不成功,循环往复,会给CPU带来很到的压力。
2) 不能保证代码块的原子性
CAS机制所保证的知识一个变量的原子性操作,而不能保证整个代码块的原子性。比如需要保证3个变量共同进行原子性的更新,就不得不使用synchronized了。
3) ABA问题
这是CAS机制最大的问题所在(加version版本号解决ASA)
如果一个值原理是A,变成了B,又变成了A,那么使用CAS进行检查时会认为它的值没有变化,但是实际上却变了。
解决:ABA问题的解决办法就是使用版本号,在变量前面追加版本号,每次变量更新时把版本号加1,那么A-B-A就会变成1A-2B-3A。
19.01.啥叫线程安全与线程不安全?
1)线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。
2)线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据
1)继承Thread类.重写run方法 单继承
2)实现Runnable接口.重写run方法 可以将创建线程的代码和代码要执行的代码分开, 降低了耦合性
New(新建):当我们创建一个线程时该线程并没有纳入线程调度处于一个new状态。
Runnable(就绪):当调用线程的start方法后,该线程纳入线程调度的控制,其处于一个可运行状态,等待分配时间片段以并发运行。
Running(运行):当该线程被分配到时间片段后被CPU运行,该线程处于running状态。
Blocked(阻塞):当线程在运行过程中可能会出现阻塞现象,比如等待用户输入信息等。但阻塞状态不是百分百出现的,具体要看代码中是否有相关需求。
Dead(结束):当线程的任务全部运行完毕,或在运行过程中抛出了一个未捕获的异常,那么线程结束,等待GC回收.
当使用new线程创建完毕后调用start方法后线程进入就绪状态,线程调度系统将就绪状态的线程转为运行状态,遇到synchronized语句时,由运行状态转为阻塞,当该线程获得synchronized对象锁后,由阻塞状态转为运行,在这种情况下可以调用wait 方法转为挂起状态,当线程关联的代码执行完毕后,线程变为结束状态.
java中有一个关键字名为:synchronized,该关键字是同步锁,用于将某段代码变为同步操作,从而解决线程并发安全问题.
用于将某段代码变为同步操作,解决线程并发的问题
锁普通方法:是同步方法,上锁对象是this,同一对象访问时,需要等待顺序执行,如果创建两个对象,可以执行各自的同步方法,互不影响
锁静态方法:因为静态方法只有一份,所以上锁对象是类对象,必须等待顺序执行
锁代码块:为了缩小同步范围,提高多线程并发效率,上锁对象是this
优化?
就是从偏向级锁升级为轻量级锁在升级为重量级锁,不可回退;
咋区分轻量级锁和重量级锁?
会根据一个个对象头(英文:马克我的)进行判断,对象头的话他会去进行一个二进制进行一个判断他尾部的一个数字状态;
同步锁:多个线程 同一对象 同一个加锁方法 上锁对象是同一个
互斥锁:多个线程 同一对象 不同加锁方法 上锁对象是同一个
就是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,
若无外力作用,它们都将无法推进下去。
办法:只要把四个必要条件破坏一个就可以
4个必要条件:
1)互斥: 所谓互斥就是进程在某一时间内独占资源。
2)等待/持有: 一个进程因请求资源而阻塞时,对已获得的资源保持不放。
3)非抢占: 进程已获得资源,在末使用完之前,不能强行剥夺。
4)形成等待环: 若干进程之间形成一种头尾相接的循环等待资源关系。
Exception与Error的区别?
1.Exception是java程序运行中可预料的异常情况,咱们可以获取到这种异常,并且对这种异常进行业务外的处理。
2.Error是java程序运行中不可预料的异常情况,这种异常发生以后,会直接导致JVM不可处理或者不可恢复的情况。
1.继承Exception时自定义异常属于检查型异常,编译器会做检查,会主动提示抛出…
2.继承RuntimeException时自定义异常属于运行时异常,编译期不会检查,运行时会抛出相关异常.
throw和throws的区别?
1.throw:是指抛出的一个具体的异常类型,写在方法的内部, 需要用户自己捕获相关的异
常,而后在对其进行相关包装,最后在将包装后的异常信息抛出.
2.throws:是用来声明一个方法可能抛出的所有异常信息,多个异常之间逗号隔开,写在方法上, 通常不用显示的捕获异常,可由系统自动将所有捕获的异常信息抛给上级调用者.
(1)SQLException 操作数据库异常类
(2)NullPointerException:空指针异常,调用null对象,或者null对象调用方法时出现
(3)ClassNotFoundException: 找不到类异常,找不到对应的class文件
(4)FileNotFoundException 文件未找到异常
(5)ClassCastException 类型转换异常类
(6)IOException:操作输入流和输出流时可能出现的异常。
使用final关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的,另外final修饰的方法不能被重写,修饰的类不可被继承,修饰的成员变量不可改变.
finalize:方法名
在垃圾回收器将内存中的没有引用指向的对象清空之前,调用finalize() 进行清理工作.
finally:异常处理中的程序块
在异常处理时,使用finally块来进行必要的清理工作,不论是否有异常发生,finally语句块中的语句都会被执行,如果发生了异常,则执行catch语句,再执行finally块.
反射是Java 动态执行机制,可以实现动态执行功能
通过反射获取类对象有三种方法: 对象.getclass 类名.class,class.forname(类的全路径名);
给属性赋值: Field(费油的)对象调用set(实例对象.值)
获取类中的属性及方法: 用类对象调用getDeclaredDield(“变量名”)
获取类中的方法并执行:
(1)获取:类对象调用getDeclaredMethod(方法名.参数类型的class)
(2)执行:返回一个method类型的对象,用它调用in vo ke(实例对象,参数)
DeclaredMethod :汗语发音(第课类儿特卖佛的)
CSS/JS
28.表单控件有哪些?
(三) 11题
常用的有三种:
提示对话框:alert():弹出并显示字符串文本信息
function f1(){
alert(“你好”);
}
确认对话框:confirm():弹出确认框,点击确定返回true,点击取消返回false.
function f2(){
var b=confirm(“你吃了吗”);
console.log(b);
}
输入对话框: prompt():弹出输入框,让用户输入信息
function f3(){
var r=prompt(“你吃了吗?”);
console.log®;
}
盒子模型指的是页面标签的实际宽高
公式:宽:左外边距+左边框线+内容的宽+右外边距+右边框线
高:上外边距+上边框线+内容的高+下外边距+下边框线
在没用on()函数之前是前绑定事件,一般用加on函数来实现后绑定比较方便;
on() 方法在被选元素及子元素上添加一个或多个事件处理程序。
使用 on() 方法添加的事件处理程序适用于当前及未来的元素(比如由脚本创建的新元素)
可以使用层次选择器+过滤选择器,获取id为city的父元素下的符合状态过滤选择器是selected(选中状态)的option元素.
使用层次选择器+过滤选择器,获取id为good的父元素下的符合表单元素选择器:checkbox的元素再次使用状态过滤选择器:checked定位到被选中的复选框.
$("#f1 :radio:first").val(0);
可以使用层次选择器+过滤选择器,获取id的值再加具体的判断条件radio的第几个?最后在点个val;
根据选择器
{ 类选择器 ID选择器 选择器组 派生选择器 伪类选择器 元素选择器}
派生:根据父元素找到子元素;
{ --基本选择器 -层次选择器 --过滤选择器又分为(基本 内容 可见性 属性 状态)}
val() 获取元素 value 值; val()只支持form表单控件中的标签
val(‘值’) 设定元素的 value 值;
html() 获取元素的 html 内容; html()返回选择器中的页面值,包括标签
html(“html 内容”) 设定元素的 html 内容;
text() 获取元素的文本内容,不包含 html ; text()只获取文本值,不获取标签
不能获取form表单中的标签的值,除了select下拉框
text(“text 内容”) 设置元素的文本内容,不包含 html;
data(“绑定名”);data(“绑定名”,“绑定值”);attr(“属性名”,“属性值”);attr(“属性名”);函数都是做什么用的?
添加样式class选择器:addClass()
删除样式class选择器:removeClass()
hasClass():判断是否有某个class选择器
data(“绑定名”); 给元素添加属性
data(“绑定名”,“绑定值”); 给属性赋值
data是保存在jquery对象里,attr是保存在DOM元素上);
attr(“class”) 获取 class 属性的值,即样式名称
attr(“class”,”样式名”) 修改 class 属性的值,修改样式
mysql:3306
oracle:1521(一个我爱你)
聚合函数:是对查询结果集进行进一步处理的函数(求和,求平均,计数,最大值,最小值)
sum(),avg(),count(字段名)/count(*),max(),min()
空值函数:判断某个字段是否为null,如果为空可以将其替换成其他值
mysql:ifnull(字段,值1):当字段为null时,取值1的值,否则取字段的值
select ifnull(sal,0);
oracle:nvl(字段,值1)
nvl2(字段,值1,值2):当字段的值为null的取值2,不为null取值1
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class itemController {
@RequestMapping("/test")
public String test (String itemId){
return “test”;
}
}
50条共500条,要第三条到第50
limit(99,50)
(起死条,查多少条)
mysql:limit 10,1
oracle:rownum:伪列:对查询结果集生成一个编号,作为过滤条件时不能大于几
1.排序
select * from emp order by sal desc;
2.取最大范围数据
select rownum rn,name,sal from(
select * from emp order by sal desc)
where rownum <=10;
3.取开始的范围
select * from (
select rownum rn,name,sal from(
select * from emp order by sal desc)
where rownum <=10)
where rn>=3;
1.case when then end;/通用/
2.结合聚合函数中的sum或者count
3.若需要分组使用group by
1.if(条件,值1,值2);/mysql特有
2.结合聚合函数中的sum或者count
3.若需要分组使用group by
带数据复制
create table 新表名 as select * from 原始表名 where 1=1;
不带数据复制
create table 新表名 as select * from 原始表名 where 1=2;
批量插入
insert into 目标表 select * from 原始表名;
rownum:伪列:对查询结果集生成一个编号,作为过滤条件时不能大于几
rowid :伪id:是每一条添加到数据库表中的数据的物理地址
约束(CONSTRAINT):限制条件,均用于创建表时对字段进行添加限制条件.
约束类型:
非空约束(NOT NULL):简称NN 1)确保字段值不为空;
唯一性约束(UNIQUE):简称UK 2)保证指定的字段不允许有重复的值(NULL除外);
主键约束(PRIMARY KEY):简称:PK 3)约定的字段非空且唯一,并且一个表中只能有一个主键或者联合主键;
外键约束(FOREIGN KEY):简称:FK 4)一张表保存的是另一张表的主键字段的值, 两个方面的数据约束:
检查约束(CHECK):简称:CK 5)用来强制在字段上的每个值都满足check 中定义的条件;
–TRUNCATE语句属于DDL语句,删除表中数据保留表结构,立即生效,不可以回滚,大数据量删除记录时效率高.
–DELETE语句属于DML语句,删除表中数据保留表结构,逐行删除记录,大数据量删除效率低,可执行条件删除,若不指定条件是全表删除.
–DROP语句是DDL语句,是删除数据库中表的操作语句.
DML和DDL的区别?2
1.DML操作是可以手动控制事务的开启、提交和回滚的。
2.DDL操作是隐性提交的,不能rollback!
2)WHERE过滤句子和having过滤子句的区别?(面)
一)WHERE过滤子句是查询过程中对表中数据的过滤条件, 不允许使用聚合函数作为过滤条件,原因在于时机不对,聚合函数是对表中数据查询后的结果集进行统计处理的,两者的执行时机不一致.
二)HAVING过滤子句是对查询结果集进行过滤的,可以在该子句后使用聚合函数,因为时机相同,聚合函数是处理结果集的,HAVING子句又是过滤结果集的,可以在一起使用,另外HAVING不能单独使用,只能跟在GROUP BY分组子句后面使用.
1.找到每一组的最小id数据
2.解决mysql中不能变查边删的问题(用查询语句再次查询起个别名)
3.使用delete嵌套刚才的查询进行删除并保留刚才查询到的数据
并集:对多个查询结果集的数据进行合并
union:结果集合并时会去重
select * from u where id=4
union
select * from u where id=8
union
select * from u where id=8;
union all:结果集合并时不会去重
select * from u where id=4
union all
select * from u where id=8
union all
select * from u where id=8;
create user 新的用户名 identified by 密码;
grant 权限名字(select,update…) on 库名.表名(*所有表) to 用户名;
flush privileges; 授权后刷新权限表
revoke 权限名字(select,update…) on 库名.表名(*所有表) from 用户名;
注:all是所有权限
查看权限:
show grants for 用户名;
真删除:真的使用delete语句删除数据
假删除:使用update语句改变数据库表中数据的状态
假分页:一次性从数据库中查询出所有数据放到内存中,每次使用从内存取对应数据
真分页:多次访问数据库查询出对应范围的数据
事务:保护数据库数据可靠交易的安全机制
事务特性ACID:
1)原子性(Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
2)一致性(Consistency)一个事务中,事务前后数据的完整性必须保持一致。
3)隔离性(Isolation)多个事务,事务的隔离性是指多个用户并发访问数据库时, 一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。
4)持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变 就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
分布式系统的CAP基本概念?
分布式系统的三个指标
1)Consistency 一致性–数据实时同步备份始终保持一致
2)Availability 可用性–保证每个请求不管成功或者失败都有响应
3)Partition tolerance 分区容错性–任意信息的丢失或失败不会影响系统的继续运行
三者不可得兼,要么AP,要么CP,要么AC,但是不存在CAP。
事务的隔离级别:
1)read uncommitted : 读未提交 :最低级别,任何情况都无法保证。
2)read committed:读已提交 :可避免脏读的发生。 ---- oracle、sql server默认
3)repeatable read:可重复读:可避免脏读、不可重复读的发生。 —mysql默认的
4)serializable:串行化:可避免脏读、不可重复读、幻读的发生—相当于锁表
1)脏读:B事务读取到了A事务尚未提交的数据 ------ 要求B事务要读取A事务提交的数据
2)不可重复读:一个事务中两次读取的数据的内容不一致 ----- 要求的是一个事务中多次读取时数据是一致的
— update
3)幻读/虚读:一个事务中 两次读取的数据的数量不一致 ----- 要求在一个事务多次读取的数据的数量是一致的
–insert delete
悲观锁:认为操作一定会发生数据冲突,每次操作前都要获取锁
1)排他锁:对一资源增加排他锁后,只有自身可以进行增删改查操作,其他人无法进行操作。默认对增删改假排他锁
对查询语句加排他锁:select * from goods_lock where id=1 for update ; 表示id等于1的资源不能被其他人操作
2)共享锁:对一资源加共享锁后,自身可以进行增删改查,别人只可以进行查询,其他操作必须等共享锁释放
对查询语句加共享锁: select * from goods_lock where id=1 lock in share mode;
乐观锁:认为操作不会导致数据冲突,操作数据时,不加任何特殊处理,在操作完成后,判断是否有冲突。它属于开发人员编写的锁,与数据库无关。
具体是,开发人员给相关表增加version字段,修改前,先将version查询出来,然后将查询的结果做为where中的一个条件,满足条件时,表明没有其他操作同时进行,可以对数据进行更新,并将version+1,保证每次修改后version是一个新值。
如果条件不满足,表明有其他操作同时进行,本次操作失败,重新查询version值,并将结果再次做为where条件,进行判断
1.注册加载驱动
2.建立连接、
3.创建对象
4.执行sql语句
5.处理,访问结果集
6.最后关闭连接,释放jdbc资源
都属于jdbc的执行对象
关系:Preparedstatement继承自Statement,都是接口
1)Statement:内部是拼接的方法
Statement执行两条相同结构的语句,只是参数不同时被认定2个不同的SQL,需要创建两个执行计划;
所以Statement执行有条件的语句时效率低,更适合执行不带条件的静态语句(DDL)
2)Preparedstatement
可以使用占位符,是预编译的,下次再执行该对象,效率更高
可以防止sql注入,方法是:把用户非法输入的单引号用\反斜杠做了转义 提高了安全性
Servlet/JSP
一.Http协议也叫超文本传输协议:由w3c制订的一种网络应用层协议,
规定了浏览器与web服务器之间如何通信及相应的数据格式。
二.(1)请求数据包:Request
请求行:包含请求类型GET/POST、请求路径、协议类型/版本
消息头:访问主机的IP和端口号,浏览器版本,接受的资源类型等
实体内容:GET请求时为空,POST请求时为请求时,实体内容为要提交的表单数据
(2)响应数据包:Response
状态行: 包括协议类型/版本、状态码、状态描述
消息头:响应给浏览器的相关信息:响应数据类型,数据大小,服务器版本信息,响应时间等
实体内容:响应给浏览器的具体数据,浏览器逐行解析.
1.在本地文件夹 外部端的应用服务器server.xml,
2.在eclipese中进行修改 ,在idea/eclipse上修改
实例化:在第一次访问或启动tomcat时,tomcat会调用此无参构造方法实例化servlet
初始化:tomcat在实例化此servlet后,会立刻调用init方法初始化servlet
就绪:容器收到请求后会调用servlet的service方法来处理请求
销毁:容器依据自身算法删除servlet对象,删除前会调用destroy方法
其中实例化,初始化和销毁只执行一次,service方法执行多次,默认情况下servlet 是在第一次接收到用户请求的情况下才会被实例化,可以在web.xml中的标签内添加一个1配置,此时在启动tomcat时就会创建servlet实例.
当第一次访问jsp页面时,会向一个servlet容器(tomcat等)发出请求,servlet容器先要把 jsp页面转化为servlet代码(.java),再编译成.class 文件 再进行调用。当再次访问jsp页面时 跳过翻译和编译的过程 直接调用
**************61.JSP九大内置对象?其中哪4个是作用域对象?怎么从某个作用域中取值?《四–15 16 题》
session{会话};cookie{可以设置30天免密码登录}不安全,绑定ip能阻止75%的请求。
Cookie和Session都是负责状态管理的,因为HTTP协议是无状态协议,需要利用Cookie和Session来记录状态.
1.cookie在客户端保存信息,session在服务器端保存信息
2.cookie可以在客户端设置,也可以在服务端设置(response.add,添加到浏览器),session在服务端设置
3.cookie生命周期设置,setMaxAge(x秒),大于0时,保存到浏览器,到达设置秒销毁,小于0时,浏览器关闭时销毁,等于0时,直接删除
4.第一次请求时,会创建一个session对象存储到内存中,并生成一个SID,并将SID发送到cookie中,之后的请求时,会通过cookie中携带的SID,找到对应的session对象,获取存储的数据。
5.session默认生命周期30分钟,通过setMaxInactiveInterval(int seconds)设置,通过invalidate()删除session
转发和重定向都是解决WEB组件之间跳转问题的
转发:一次请求,地址不改变,共用1个request对象,只能转发到项目内组件。
request.getRequestDispatcher(“emp_list.jsp”).forward(req, res);
重定向:二次请求,向浏览器响应信息时会响应302状态码和要重定向的地址,地址会发生改变,两个请求中不能共享request对象,可以重定向到项目外的组件。
通常查询时候用转发,增删改之后重定向到查询。
response.sendRedirect(“findEmp”);
转发:return “forward:/findDog”; 转发到findDog请求
重定向:return “redirect:/findDog”; 重定向到findDog请求
get请求,浏览器默认发送get请求,使用请求路径传参,请求路径在请求行中,所以请求参数是可见的不安全,请求参数的大小有限制,一般小于2K,多用于到服务器请求数据
post请求,将参数存放在请求数据包的实体内容中,传递过程中不可见,隐私性好,参数大小无限制,用于向服务器提交数据
1.IOC 2.DI 3.AOP
Spring容器是Spring框架的一个核心模块,用来管理对象。
IOC是控制反转:对象之间的依赖关系交给容器来建立.
DI是依赖注入:容器通过调用对象的set方法或者构造方法来建立对象之间的依赖关系
注:IOC是目标,DI是手段.
依赖注入的方式有三种:
1.通过set方法注入 2.通过构造方法注入 3.通过自动装配
1)set 方法注入:
假设现在有两个类A类和B类,在A类中execute()方法中调用B类中的f1()方法,需要在A类中声明B类型的引用, 在创建该引用的set方法,并声明B类型参数,在set方法内部将参数赋值给B类型的引用.
2)构造器注入:
假设现在有两个类A类和B类,在A类中execute()方法中调用B类中的f1()方法,需要在A类中声明B类型的引用, 创建A类的有参构造器,并声明B类型参数,在构造方法内部将参数赋值给B类型的引用.
《假设现在有两个类,A类中的一个方法调用B类中的一个方法,需要A中声明B类的类型引用,》
3)自动装配:(了解)
默认情况下,容器禁止自动装配。
设置autowire属性让容器自动装配。比如:autowire=“byType”
byName:容器查找id等于属性名称的bean,然后调用对应 的set方法来完成注入。
注意:如果找不到对应的bean, 会注入null值。
byType:容器查找与属性类型一致的bean,然后调用对应 的set方法来完成注入。
注意:如果找不到对应的bean, 会注入null值。如果找到多个对应的bean,会出错。
constructor(肯死抓课特):类似byType,只不过调用的是构造器来 完成注入。
Spring IOC注解:
这组注解的作用是写在控制层/业务层/持久层类上,让Spring框架帮助创建对象并放入IOC容器中
@Component 通用IOC注解
@Controller 控制层IOC注解
@Service 业务层IOC注解
@Repository 持久层IOC注解(持久层目前只提供接口,所以不需要写该注解)
Spring DI注解:
这组注解的作用是在从IOC容器中取出来对应对象依赖注入到需要用的地方
@Autowired Spring提供的依赖注入注解 按by type自动注入;
@Resource (瑞骚死) Servlet提供的依赖注入注解 默认按byName自动注入;
@Qualifier(“bean的名字”)(狂雷法儿)一般作为@Autowired()的修饰用
mvc:model、view、controller,模型、视图、控制层、三层;
五大核心组件分别是:
DispatcherServlet (前端控制器) 接受所有所有请求
HandlerMapping (映射处理器)查找用户的请求与业务处理的映射
Controller (处理器)
ModelAndView 《一般是搭配jsp来使用的》一般不刷新,要钱啊
ViewResolver (视图解析器)实现路径的动态拼接
工作流程:
1.在tomcat启动时会实例化一个DispatcherServlet对象,该对象负责接收请求.
2.DispatcherServlet接收到用户请求后依据HandlerMapping中的配置路径与请求
路径进行比对,比对成功调用相应的Controller进行业务处理.
3.处理完毕后将结果封装到ModelAndView对象中(视图名和响应数据)返回给
DispatcherServlet, DispatcherServlet依据ViewResolver的解析,将视图名与
ViewResolver视图解析器中的前缀和后缀进行拼接得到一个具体的视图信息比如 hello.jsp,
调用相应的视图对象(比如jsp)来生成相应的页面.
4.然后DispatcherServlet将该页面响应给浏览器.
单列模式:
单例模式的核心:结构中只包含一个,被称为单例的特殊类。通过单例模式可以保证系统中
一个类只有一个实例, 可以减少频繁创建对象对内存的开销,(保证核心业务只有一个对象在进行处理);
(1) 懒汉式单例类:在第一次调用的时候实例化自己 (直接设置一个为null的对象);
(2) 饿汉式单例类:在类初始化时,已经自行实例化(是指一个实体对象);
(3) 线程安全单例类:对获取方法加锁,但性能稍慢(设置一个为空的用SingletonSync的对象);
(4) 双检锁线程安全单例类:使用同步块并进行双重判断;(用线程多做了个上锁在if判断中);
模板方法模式:
代理模式:就是给一个对象提供一个代理由这个代理对象就是控制原对象的引用,然后代理模式可以协调调用者和被调用者可以降低系统的耦合性;
就是比如说买机票,就是一般住的地方都是离机场比较远,这个时候我们就可以在一些渠道买,不如说携程,智行等app去购买,就好比中间商。就是把这个购买机票的动作为我们进行一个代理;
(在项目中主要是做利用框架自带的去完成一些东西)
工厂模式:
工厂模式分为:普通工厂模式,抽象工厂模式,工厂方法模式.
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
本人总结:一个父接口,有三个子接口,三个字接口有不同的方法,父接口可以让第一个字接口做第二个子接口的方法;
js版
1)首先创建xmlhttprequest对象
2)使用对象调用open方法,传入三个参数,(请求类型,请求地址,是否是异步请求,默认是)
3)对象上绑定事件处理函数onreadstatechange,当readstate值改变时,触发readstatechange函数
4)readstate由5个值,0是未初始化,1是正在发送请求,2是请求发送完成,3是正在接收响应数据,4是接收完成响应数据
5)然后用对象调用send方法,发送请求
jQuery版
1)$.Ajax({})
2)请求类型
3)请求url
4)返回类型
5)回调函数
6)$.axios({})
axios.get(url,请求参数)
.then(回调函数)
一种轻量级的数据交换格式,以kv键值对的形式存储,{“属性名”:属性值}
后端将对象转换为json数据,发给前端,前端将json数据,解析为js对象;
组件扫描是指容器自动扫描指定包及其子包下的所有类,如果这些类中包含指定的注解,就将这些类交给spring容器进行管理,容器创建对象,并管理对象
组件扫描注解:
@Component
@Service 业务层注解
@Controller 控制层注解
@Respository{瑞跑死特瑞} 可以不写
@Mapper/@MapperScan(包名)在主启动类上;
后两个作用相同,都是持久层注解
@RequestMapping url和控制器请求,映射注解,能够处理所有请求类型
也可以添加method属性处理特定请求。
@ResponseBody 返回json数据,Ajax请求结束,返回字符串本身,不执行mvc的视图解析器。
切面 = 切入点表达式 + 通知方法
AOP(面向切面编程) 主要利用(动态代理的模式) 降低程序的耦合度,扩展业务功能方法.
也就是说,可以在不修改原代码逻辑的基础上添加新的逻辑。
@Aspect{阿斯拜课的} 标注切面类注解
通知(Advice{饿德外死})方式:
before: 在目标方法执行之前执行
afterReturning: 在目标方法执行之后返回时执行
afterThrowing: 在目标方法执行之后,抛出异常时执行
after: 无论程序是否执行成功,都要最后执行的通知
around: 在目标方法执行前后 都要执行的通知(完美体现了动态代理模式)
功能最为强大 只有环绕通知可以控制目标方法的执行
关于通知方法总结:
1.环绕通知是处理业务的首选. 可以修改程序的执行轨迹
2.另外的四大通知一般用来做程序的监控.(监控系统) 只做记录
切入点:
1)使用注解做为切入点 @annotation(包名.注解名)
2)使用execution(访问权限 返回值类型 包名.类名.方法名(参数列表)) 万能切入点表达式,可以使用进行代替
3)bean(“bean的ID”) 根据beanId进行拦截 只能匹配一个
4)within(包名.类名)可以使用通配符? 能匹配多个
OOP是什么:oop 是面向对象编程,面向对象编程是一种计算机编程架构,OOP 的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组、合而成。
OOP有什么特性:(共五点)1. 类,2.对象,
3、封装性:也称为信息隐藏,有效避免程序间相互依赖,实现代码模块间松藕合。
4、继承性:继承增加了代码的可重用性。PHP 只支持单继承,也就是说一个子类只能有一个父类。
5、多态性:多态性增强了软件的灵活性。
使用OOP用什么好处:
1、易维护
采用面向对象思想设计的结构,可读性高,由于继承的存在,即使改变需求,那么维护也只是在局部模块,所以维护起来是非常方便和较低成本的。
2、质量高
在设计时,可重用现有的,在以前的项目的领域中已被测试过的类使系统满足业务需求并具有较高的质量。
3、效率高
在软件开发时,根据设计的需要对现实世界的事物进行抽象,产生类。使用这样的方法解决问题,接近于日常生活和自然的思考方式,势必提高软件开发的效率和质量。
4、易扩展
由于继承、封装、多态的特性,自然设计出高内聚、低耦合的系统结构,使得系统更灵活、更容易扩展,而且成本较低。
都能实现:权限认证,过滤方法;
拦截器是spring中的组件,在HandlerMapping之前执行,只能拦截action请求;
1.创建拦截器(Interceptor (音特色不特)),实现HandlerInterceptor接口,重写
preHandle():前端控制器调用的方法,结果为true是才能调用HandlerMapping处理器
postHandle():处理器执行完请求后返回结果之前执行,可以在该方法中设置ModleAndView对象
afterCompletion():最后执行的方法,处理处理器抛出的异常;
2.过滤器(filter(费油特)),是servlet中的组件,在servlet之前执行,可以对所有请求进行过滤
创建过滤器实现Filter接口,重写init()、doFilter()、destroy()方法,分别是初始化、过滤器逻辑、销毁过滤器的方法
1.#{} 表示创建的是prepareStatement,对象即sql 预编译,防止sql注入;
2.${}表示创建的是statement对象,即 sql 拼接,还需要加上单引号。
3.总结:能用#{}就不用或者少用¥{},要想插入一条不可变的sql,比如排序时,数据对象中的表名等,是可以用的;
77.spring cloud 介绍?
spring cloud 是一系列框架的集合。它利用 spring boot 的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用 spring boot 的开发风格做到一键启动和部署。spring cloud 并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过 spring boot 风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
项目
77.项目某模块思路
1)该模块是解决用户什么问题的?
2)牵涉到了那些数据库相关表,表里有哪些主要字段,多表的情况下表之间的关系?
3)项目中都用到了那些技术?每个技术都在请求流程中哪些环节生效?
4)从请求发起时以一个完整的流程把相关技术和业务穿插到该请求中?
提高题:
78.Nginx是什么技术?
Nginx是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务,主要用于负载均衡和反向代理. C语言开发,服务内存占用不超过3M,并发能力强,测试数据5万/秒,实际测试:2-3万/秒,开源免费.
一般情况下 正向代理和反向代理都会使用. 正向服务实现网络通讯,反向负责获取服务器数据.
正向代理:正向代理的典型用途是为在防火墙内的局域网客户端提供访问Internet的途径。
反向代理:反向代理服务器通常可用来作为Web加速,来降低网络和服务器的负载,提高访问效率。
总结:
正向代理是客户端代理,反向代理是服务端代理
正向代理,服务器不清楚真实的用户是谁.认为代理服务器就是用户,反向代理,用户不清楚真实的服务器是谁.认为代理服务器就是目标服务器.
正向代理 保护的是真实的用户.对于服务器而言屏蔽真实的用户信息,反向代理 保证的是后台的全部的服务器. 对于用户而言屏蔽服务器相关信息
79.Redis是什么技术?
1.Redis【集群规则、分片机制、缓存】;
Redis集群?
Redis哨兵虽然可以实现Redis的高可用,但是哨兵本身没办法实现高可用,程序调用存在风险,我们需要搭建集群来实现高可用.
Redis哨兵机制?
集群的工作原理:
1)集群中所有点都会保存集群中全部主从关系的信息并且所有节点之间可以互相通信.
2)定时向其他节点发送ping pong心跳检测,若某主机无法回应超一半以上则该主机宕机
3)剩余主机重新选举宕机主机的从机变为主机(从机只有判断宕机的投票权没有选举权)
4)此时新主机没有从机,若其他主机有可用从机借用其他主机的从机作为自己的从机
5)若宕机后无法借用也无法在推举新的主机发生主机数量减少则集群崩溃
哨兵机制是为了解决Redis分片存在的无法高可用的问题,因为如果redis分片的节点有一个服务器宕机,则直接影响用户的使用.
Redis分片机制?
单台Redis的内存大约是10M左右,若需要保存的缓存数据特别大,单台不够用,那么我们可以准备多台Redis来实现扩容.
Redis的缓存穿透,缓存雪崩,缓存击穿以及解决方案?
reids缓存的执行流程:
正常的使用缓存流程:数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并把查询到的数据,放进缓存。如果数据库查询数据为空,则不放进缓存。
!!!!!!!!!!!!!!!缓存穿透
说明: 在高并发的条件下,用户频繁访问<一个不存在的数据>.导致大量的请求直接发往数据库.导致服务器宕机.
解决方案:
布隆过滤器介绍?
布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难
Redis内存优化策略?
Redis的缓存数据都在内存中,若数据量越来越大,则内存压力也会越来越大,甚至出现内
存溢出,因为我们需要将不使用的数据进行淘汰.
LRU算法:按照时间维度,将时间特别久最近使用少的数据进行淘汰。
LFU算法:按照引用计数的次数将最少引用的数据进行淘汰,最少引用次数是将引用计数
寄存器定时向右移一位,形成指数衰减的平均使用次数。
----8848------关于Shiro技术?
Shiro框架介绍
是一个轻量级的安全框架,主要提供了 授权、认证、加密、会话管理这几个功能。
Shiro运行流程
比如一个登陆流程:
1、首先调用Subject.login(token)进行登录,他会委托给SecurityManager
2、SecurityManager负责真正的身份验证逻辑;它会委托给Authenticator进行身份验证;
3、Authenticator会把相应的token传入Realm,从Realm获取身份验证信息,如果没有就返回认证失败,有的话就继续执行操作。
Shiro 的优点
简单的身份认证, 支持多种数据源
非常简单的加密 API
对角色的简单的授权, 支持细粒度的授权(方法级)
支持一级缓存,以提升应用程序的性能;
内置的基于 POJO 企业会话管理, 适用于 Web 以及非 Web 的环境
不跟任何的框架或者容器捆绑, 可以独立运行
简述 Shiro 的3个核心组件
1.Subject
正与系统进行交互的人, 或某一个第三方服务。
所有 Subject 实例都被绑定到一个SecurityManager 上。
2.SecurityManager
Shiro 架构的心脏, 用来协调内部各安全组件, 管理内部组件实例, 并通过它来提供安全管理的各种服务.
当 Shiro 与一个 Subject 进行交互时, 实质上是幕后的 SecurityManager 处理所有繁重的 Subject 安全操作。
3.Realms
本质上是一个特定安全的 DAO. 当配置 Shiro 时, 必须指定至少一个 Realm 用来进行身份验证和授权.
Shiro 提供了多种可用的 Realms 来获取安全相关的数据. 例如关系数据库(JDBC), INI 及属性文件等.
可以定义自己 Realm 实现来代表自定义的数据源。
如何配置在 Spring 中配置使用 Shiro
1、在 web.xml 中配置 Shiro 的 Filter
2、在 Spring 的配置文件中配置 Shiro
3、配置自定义 Realm:实现自定义认证和授权
4、配置 Shiro 实体类使用的缓存策略
5、配置 SecurityManager
6、配置保证 Shiro 内部 Bean 声明周期都得到执行的 Lifecycle Bean 后置处理器
7、配置AOP 式方法级权限检查
8、配置 Shiro Filter
什么是MyCat:
MyCat是一个开源的分布式数据库系统,是一个实现了MySQL协议的服务器,前端用户可以把它看作是一个数据库代理,用MySQL客户端工具和命令行访问,而其后端可以用MySQL原生协议与多个MySQL服务器通信,也可以用JDBC协议与大多数主流数据库服务器通信,其核心功能是分表分库,即将一个大表水平分割为N个小表,存储在后端MySQL服务器里或者其他数据库里。
所以可以这样理解:数据库是对底层存储文件的抽象,而Mycat是对数据库的抽象。
Vue是啥?
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,
不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。
Vue的优点?
Vue 可以实现前后台分离开发,节约开发成本
并且Vue是中国人开发的,官方文档是中文,学习理解更轻松
Vue.js 的核心是一个允许采用简洁的模板语法来声明式的将数据渲染进 DOM,初始化根实例,vue自动将数据绑定在DOM模板上
声明式渲染与命令式渲染区别?
声明式渲染:所谓声明式渲染只需要声明在哪里,做什么,而无需关心如何实现
命令式渲染:需要具体代码表达在哪里,做什么,如何实践
API是啥?{application programming interface}
API就是应用程序编程接口,在不同场合,这个编程接口的含义不同。
是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节
说得更加通俗易懂一些,别人写好的代码,或者编译好的程序,提供给你使用,就叫做API。你使用了别人代码(或者程序)中的某个函数、类、对象,就叫做使用了某个API。
各种编程语言自带的标准库其实也是API。这些API由编程语言的开发者们编写,安全、高效、健壮,为我们实现了常见的功能,让我们不用再重复造轮子。
啥是JavaScript(动态效果)?Css? (颜色);
1)运行在客户端浏览器中的,每一个浏览器都有javascript的解析引擎
2)脚本语言:不需要编译,直接就可以被浏览器解析执行
功能:可以用来增强用户和html页面的交互过程,可以来控制html元素,让页面有一些动态的效果,增强用户体验。
javascript:一门客户端脚本语言
JavaScript 是一种轻量级的编程语言。
JavaScript 是可插入 HTML 页面的编程代码。
JavaScript 插入 HTML 页面后,可由所有的现代浏览器执行。
JavaScript 被数百万计的网页用来改进设计、验证表单、检测浏览器、创建cookies,以及更多的应用。
这门语言可用于 HTML 和 web,更可广泛用于服务器、PC、笔记本电脑、平板电脑和智能手机等设备。
js函数
函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块。
Jscript 支持两种函数:一类是语言内部的函数,另一类是自己创建的。
JavaScript 函数允许没有参数(但包含参数的小括号不能省略),也可以向函数传递参数供函数使用。
什么是单点登录?
单点登录SSO(Single Sign On)就是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任。,包括单点登录与单点注销两部分
实现方法是哪三种?
1.以Cookie作为凭证媒介
最简单的单点登录实现方式,是使用cookie作为媒介,存放用户凭证。
用户登录父应用之后,应用返回一个加密的cookie,当用户访问子应用的时候,携带上这个cookie,授权应用解密cookie并进行校验,校验通过则登录当前用户。
坏处?
***Cookie不安全
***不能跨域实现免登
2.通过JSONP实现
对于跨域问题,可以使用JSONP实现。
用户在父应用中登录后,跟Session匹配的Cookie会存到客户端中,当用户需要登录子应用的时候,授权应用访问父应用提供的JSONP接口,并在请求中带上父应用域名下的Cookie,父应用接收到请求,验证用户的登录状态,返回加密的信息,子应用通过解析返回来的加密信息来验证用户,如果通过验证则登录用户。
坏处?
***Cookie不安全
3.通过页面重定向的方式
最后一种介绍的方式,是通过父应用和子应用来回重定向中进行通信,实现信息的安全传递。
父应用提供一个GET方式的登录接口,用户通过子应用重定向连接的方式访问这个接口,如果用户还没有登录,则返回一个的登录页面,用户输入账号密码进行登录。如果用户已经登录了,则生成加密的Token,并且重定向到子应用提供的验证Token的接口,通过解密和校验之后,子应用登录当前用户。
好处是:
这种方式比较前面两种方式,解决了上面两种方法暴露出来的安全性问题和跨域的问题,但是并没有前面两种方式方便。
安全与方便,本来就是一对矛盾。
一、jsonp 原理
背景:
为安全考虑,浏览器会对脚本中的请求进行同源策略检查,跨域XHR 请求时,被请求服务的请求头必须设置Access-Control-Allow-Origin 头等。但对于css、script 文件的引用等,是允许跨域的,也正如此,平常的开发中可在html 头部通过或
jsonp 原理:
jsonp 技术就是利用了
Feign详解与实例?
Feign是一种负载均衡的HTTP客户端,它使得编写web服务客户端变得更加容易。使用Fegin创建一个接口并对它进行注解。它具有可插拔的注解支持包括Feign注解与JAX-RS注解,Feign还支持可插拔的编码器与解码器,Spring Cloud 增加了对 Spring MVC的注解,Spring Web 默认使用了HttpMessageConverters, Spring Cloud 集成 Ribbon 和 Eureka 提供的负载均衡的HTTP客户端 Feign。
SpringBoot优点?
SpringBoot程序启动会依次执行多个启动项,当pom.xml文件中添加某个特定的jar包文件时, 启动项就会加载该文件,实例化对象.完成自动化的装配.从而实现了开箱即用的效果.
SpringBoot官网提供了主流的装配的配置项,无需过多的配置即可实现功能,
但是如果官网没有提供配置项,则需要手动通过Configuration自定义配置类的方式进行手动的装配.