java基础-持续更新
第一季
java基础类型
基本类型
byte(1) short(2) int(4) long(8)float(4) double(8) char(2) boolean
引用类型:
类
接口
数组
JVM与字节码
JVM:java虚拟机是运行java字节码的虚拟机
jvm有针对不同系统的特定实现,目的是使用相同的字节码,会出现相同的结果
字节码文件:在java中,jvm可以理解的代码叫做字节码文件,它不面向任何特定的处理器,只面向虚拟机,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释性语言可移植的特点,所以java程序运行起来笔记高效。
简单介绍下多态、重载、重写
多态:同一种事务的多种形态
作用:1. 不必为每一个派生类编写功能调用,只需要对抽象基类进行处理即可,提高可复用性
2. 派生类的功能可以被基类的方法或引用变量所调用,提高可扩展性。
类型:
编译时多态 方法重载overload
方法名必须相同,形参必须不相同 与返回类型无关
运行时多态 方法重写overwrite
必须存在继承关系 重写的方法,返回值类型,参数列表必须与父类方法一致
子类的访问修饰符不能低于父类的方法的访问修饰符
java中的比较器(Comparable、comparator)
1. 两个都是接口 内部比较器(Comparable) 外部比较器(comparator)
2. 排序规则方法不一样:compareTo(Object o) compare(T 01, T 02)
3. Comparable接口用于在类的设计中使用,设计初期就实现这个接口,指定排序规则
comparator接口用于类设计已经完成,根据需求新建排序类实现排序。
5. java的栈与堆
类变量(static):在程序加载时系统就为他在堆中开辟了内存,堆中的内存地址存放在栈中,以便于高速访问,静态变量的周期持续到系统关闭。
实例变量:当使用new时,在堆中开辟相应的内存空间,当实例变量的引用丢失后,将被GC列会可回收名单。
局部变量:当执行到它的时候,在栈中开辟内存,当局部变量一旦脱离作用域,内存释放。
堆内存用来存放由new创建的对象或者数组,由GC管理,然后再栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象的再堆内存的首地址。栈中变量就变成可此对象或者数组的引用变量
6.final finally finalize
final:
1.修饰变量,被声明的变量必须再声明时给出变量的初始值,而在以后的引用中只能读取
2.final声明方法:方法不能被重写
3.修饰类,不能被继承
finally:
在异常处理中作为以恶搞必定会执行的语句
finalize:java技术允许使用finalize方法在垃圾回收将对象从内存中清除出去之前做必要的清理工作。
7.集合的概述以及底层数据结构
collection接口
list接口 有序的 可重复的
arrayList:Object数组
LinkedList:双向链表
Vectoer:Object数组
set 存储无序的 不可重复的
hashSet:基于hashmap的实现,底层使用hashmap来保存元素
LinkedHashSet:基于LinkedHashMap实现
Treeset:红黑树
例外;
arrayList与Vector的区别
arraylist:不适合做插入与删除,适合随机查找和遍历
Vector:线程同步,某一时刻只有一个线程能够写 Vector,避免多线程同时写而引起的不一致性
LinkedList是用链表结构存储数据的,很适合数据的动态插入和删除,随机访问和遍历速度比较慢
Arraylist是线程异步(ASynchronized)的,是不安全的。如果不考虑到线程的安全因素,一般用Arraylist效率比较高。
如果集合中的元素的数目大于目前集合数组的长度时,vector增长率为目前数组长度的100%,而arraylist增长率为目前数组长度的50%.如过在集合中使用数据量比较大的数据,用vector有一定的优势。
解决哈希冲突的主要有三种办法:定址法,拉链法,再散列法
map接口key-value键值对
hashmap:1.jdk8之后解决哈希冲突有了较大的变化,当链表长度大于阈值8时,将链表转化为红黑树,以减少搜索时间。
2.实现不同步,线程不安全。
3.hashmap可以存null键(null键只能有一个)和null值,不保证元素的顺序恒久不变,不能用get()判断是否具有一个键,只能使用containsKey()方法判断。
4.hashmap解决哈希冲突采用拉链法
LinkedHashMap:继承自hashmap,底层依旧时基于拉链式散列结构由数组和链表或红黑树组成,并在在此基础上,增加了一跳双向链表,使得上面的结构可以保持键值对的插入顺序,同时通过堆链表进行相应的操作。实现了访问顺序的逻辑
TreeMap:红黑树
Hashtable:数组+链表组成,数组时hashmap的主体,链表则是主要为了解决哈希冲突而存在的。并且同步,线程安全,键跟值不能为null;
什么是线程、进程
进程:是程序的一次执行,是具有一定独立功能的程序关于某个数据集合上的一次运动活动,是操作系统的资源分配和调度的最小单位
线程:是操作系统能够进行运算调度的最小单位,它包含在进程之中,是进程的最小实际运作单位
两者的关系:进程是程序执行时的一个实例,线程是进程的一个实体
线程必定只数据一个进程,而进程可以多个线程而且至少拥有一个进程
String Stringbuffer StringBuilder
string是一个字符常量被final修饰,不可被继承,String属于常量,被创建之后就不能被更改
Stringbuffer 也创建String对象,并且绝大多数加入了同步处理,具有的toString方法会进行对象缓存,以减少元素复制开销
StringBuilder创建String对象,方法不具有线程同步的修饰,不同之处在于最后toString的时候,会直接返回一个新对象。
10 值传递与引用传递的区别
值传递:指在调用函数时,将实际函数复制一份传递给函数,这样在函数中修改参数时,不会影响到实际参数,其实,就是说值传递,只会改变形参,不会改变实参。
引用传递:在调用函数时,将实际参数的地址传递给函数,这样函数中对参数的修改,会直接影响到实际参数。
11 关于static的说明:
1.可以直接用类名来访问类中的静态方法
2.静态块仅在类加载时执行一次
3.static方法不能有用this调用的方法
12 内部类知识点
内部类:
静态内部类:不可访问外部的非静态资源,可以有public static abstract class Demo
成员内部类:可以访问外部所有资源,但是本身内部不能具有静态属性(因为自己本身就需要依靠外部类的实例化)
局部内部类:不可被访问修饰符和static修饰,只能访问final变量和形参
局部静态内部类:再外部类的静态方法中
局部内部类:在外部类的一般方法中
匿名内部类:
没有构造器,没有静态资源,无法被访问修饰符,static修饰
只能创建匿名内部类的一个实例
创建的时候一定是在new的后面
13 创建对象的四种方式
1.new关键字直接创建
student student=new student();
2.class的反射调用(使用class的newInstanse()方法可以调用无参构造器创建对象)
class.forName();
3.使用clone创建对象
try{
student stu=(student)stu1.clone();
sout(stu)
}catch(Exception e){
e.printStackTrace();
}
4.使用序列化(实现serializable接口)
public class Student implements Serializable();
14 模运算
取模运算,余数的符号与被除数符号相同
System.out.println((-3)%2) ==== -1
System.out.println((-12%-5)) === -2
15 接口以及抽象类的区别
1. 抽象类可以有默认的方法实现,但是接口完全是抽象的,不存在方法的实现。
2. 抽象类通过extends关键字来继承候醒类,如果子类不是抽象类,需要提供抽象类所有方法的方法的实现。接口子类使用关键字implements来实现接口,它需要提供接口中所有的声明的方法的实现
3. 抽象类可以有构造器,但是接口不允许
4. 抽象类除了不能实例化外,几乎与正常类无差别,但是接口时完全不一样的类型
5. 抽象类可以有public,protected和default这些修饰符,但是接口默认为public,不能是其他的。
6.抽象类可以拥有main方法,但是接口不行
7. 抽象方法可以继承一个类和实现多个接口,但是接口只能继承一个或多个接口
8. 抽象比接口速度快,
9.抽象类可以添加新方法,但是接口需要改变实现该接口的类。
16 equals与==的区别:
==在基本类型以及引用类型是不同的,
基本类型比较的是值,而引用类型比较的是引用
equals本质上就是==,但是String以及integer重写的equals方法,变为了值比较。
多线程
1. 进程与线程的区别
进程;
-拥有独立的堆栈空间和数据段,系统开销大
-由于进程之间是独立的特点,使得进程的安全性比较高,有独立的地址空间,一个进程奔溃,不会影响其他进程
-进程的通信机制相对复杂,比如管道,信号,消息对列,套接字等
线程:
-线程拥有独立的堆栈空间,但是共享数据,他们彼此使用相同的地址空间,比进程开销小
-线程是一个进程中不同的执行路径,一个线程的死亡就等于整个进程的死亡
-通信相对方便
2. 创建线程的方法
1.继承Thread类重写run方法
2.实现Runable接口方式
3.实现Callable接口实现call方法,调用futureTask类构造函数
4.通过线程池创建线程
public static void main(String[] args){
//第一种
MyThread myThread=new MyThread();
myThread.start();
//二种
new Thread(()->System.out.println("run-2")).start();
}
public static class MyThread extends Thread{
@Override
public void run(){
System.out.println("run-1")
}
}
---
第三种
public static void main(String[] args) {
System.out.println("主线程开始执行,当前线程名称:" +Thread.currentThread().getName());
Callable<Integer> callable = new MyThirdThread();
FutureTask<Integer> futureTask = new FutureTask<>(callable);
new Thread(futureTask).start();
public class MyThirdThread implements Callable<Integer> {
@Override
public Integer call() throws Exception {
Thread.sleep(6 * 1000);
return new Random().nextInt();//可以返回一个结果
}
}
---
第四种:
newFixedThreadPool(int nThreads):创建固定数量的线程池
newCachedThreadPool():创建缓存线程池
newSingleThreadExecutor():创建单个线程
newScheduledThreadPool(int corePoolSize):创建定时器线程池
3. Thread类start()与run()的区别
run()是一个普通方法,调用之后程序会等待run()方法执行完毕,所以是串行,
start()方法会启动一个线程,当线程得到CPU资源后会自动执行run()方法体中的内容,实现真正的并发执行。
4. java种notify和notifyAll有什么区别
notify方法不能唤醒某个具体的线程,所以只有一个线程在等待的时候它才有用武之地
而notifyAll唤醒所有线程并允许他们争夺锁确保至少有一个线程能继续运行
5. sleep与wait的区别
sleep方式是线程的静态方法,让调用线程进入睡眠状态,让出执行机会给其他线程
等到休眠结束后,线程进入就绪状态和其他线程一起竞争cpu的执行时间
因为sleep是静态方法,不会改变对象的机锁,所以一个syncharnized中调用了sleep方法,线程虽然休眠,但是对象机锁没有改变,其他线程依旧无法访问。
wait()是object类的方法,当一个线程执行到wait方法时。进入到一个和该对象相关的等待池,同时释放对象的机锁,使得其他线程能够访问,可以通过notify,notifyAll来唤醒等待的线程
线程的生命周期
新建---就绪---运行---阻塞---死亡
7 创建线程池的七种方法
newSingleThreadExecutor();特点是工作线程数只能限制为1,操作一个无界的工作队列,保证所有任务都是顺序执行,最多只有 一个任务是处于活动状态下
newCachedThreadPool();一种处理大量短时间工作任务的线程池,特点是会试图缓存线程并重用,当无缓存线程可用时,就 会创建新的工作线程;如果线程闲置得时间超过60S,则将终止并移出缓存,内部使用SynchronousQueue作为 工作队列。
newFixedThreadPool(int nThread):重用指定数目(nThreads)得线程,其背后使用无界的工作队列,任何时候最多只有nThread 线程处于活动状态,超过即等待,不足即补充。
newSingleThreadScheduledExecutor();创建单线程池,返回ScheduledExectorService,可以进行定时或周期性的工作调度。
newScheduledThreadPool(int corePoolSize),创建的是个ScheduledExectorService,可以定时或者周期性工作调度,区别在于单一工作线程还是多个工作线程
newWorkStealingPool(int parallelism):java 8才加这个创建方法,其内部会构建ForkJoinPool,利用Work—Stealing算法,并行的处理任务,不保证处理顺序
8 多线程synchronized锁升级的原理什么?
synchronized锁升级原理:在锁对象的对象头里面有一个threadid字段,在第一次访问的时候threadid为空,jvm让其持有偏向锁,并将threadid设置为其线程id,再次进入时候会先判断threadid是否与线程id一致,如果一致则可以直接使用此对象,如果不一致,则升级偏向锁为轻量锁,通过自旋循环一定次数来获取锁,执行一定次数后,如果还没有正常获取到使用的对象,此时就会将锁升级为重量锁,此过程就构成了synchronized锁的升级。
锁升级的目的:锁升级是为了减低了锁带来的性能消耗,在java6之后优化synchronized的实现方式,使用偏向锁升级位轻量级锁在升级位重量级锁的方式,从而减低锁带来的性能消耗。
9 Volatile原理
Java语言提供了一种稍弱的同步机制,即volatile变量,同来确保将变量的更新操作通知到其他线程,当把变量声明为volatile类型后,编译器和运行时都会注意到这个变量时共享的,因此不会将该变量上的其他内存操作一起重排序。volatile变量不会被缓存在寄存器或者其他处理器不可见的地方,因此在读取volatile类型的变量时总会返回最新写入的值。
在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此volatile变量是一种比sychronized关键字更轻量级的同步机制。
io流
1.JavaIO流分为几种?
按功能划分:输入流、输出流
按类型来分:字节流和字符流
区别是:字节流按8位传输以字节位单位输入输出数据,字符流按照16位以字符为单位输入输出数据。
2.BIO,NIO,AIO的区别
BIO:blockIO同步阻塞式IO,它的特点是模式简单使用方便,并发处理能力低。
NIO:Non IO同步非阻塞式IO,是传统io的升级,客户端与服务器端通过channel(通道)通讯,实现多路复用异步非阻塞io,异步io的操作基于事件和回调机制。
反射以及序列化
反射以及序列化
反射:java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法。
对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象的方法的功能称为java反射
序列化:对象转换为二进制数据格式的过程。
2.创建反射的几种方式
1. Class class1=(类名).class;
2.Class class2=(已实例化对象).getClass();
3.Class class3=Class.forName("包名.类名")
3 动态代理是什么,有什么应用,怎么实现?
动态代理就是运行动态生成代理类
应用有Spring AOP ,hibernate数据查询,测试框架的后端mock,rpc,java注解对象获取等。
jdk原生动态代理和ciglib动态代理,jdk原生动态代理基于接口实现的,而ciglib是基于继承当前类的子类实现的。
4.深拷贝和浅拷贝区别是什么?
浅拷贝:当对象被复制只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制
深拷贝:除了对象本身被复制外,对象所包含所有成员变量也将复制。
数据库
使用JDBC的过程
1.加载JDBC驱动程序
2.提供jdbc的url
3.创建数据库链接
4.实现PreparedStatement
5.执行sql语句
6.处理结果 返回结果集 影响的记录数
7.关闭
2. 数据操作语句
Select * from 表 where 条件
可以为order by ASC|DESC 默认为升序
update table set id="id" where name="name"
insert into table(属性值) VALUES (值)
delete from table where 条件
主键:alter table 表名 add constraint 主键名 primary key 字段名
销毁:alter table 表名 drop constraint 主键名
外键:alter table 表名 add constraint 外键名 foreign key (‘从表外键字段’) references 主表(主表主键字段)
3. > ###### mysql的存储引擎,myisam和innodb的区别
MyIsam是非事务的存储引擎,适合用于频繁查询的应用,表锁,不会出现死锁,适合小数据,小并发
innodb是支持事务的存储引擎,合于插入和更新操作比较多的应用,设计合理的话是行锁,适合大数据,大并发。
```
```
数据表的类型
MyISAM、InnoDB、HEAP、BOB,ARCHIVE,CSV
MyISAM:成熟、稳定、易于管理,快速读取。一些功能不支持(事务等),表级锁。
InnoDB:支持事务、外键等特性、数据行锁定。空间占用大,不支持全文索引等。
如何sql优化
1.选用正确的存储引擎
2.优化字段的数据类型
3.为搜索字段添加索引
4.避免使用Select *从数据库里读出越多的数据,那么查询就会变得越慢
5.使用 ENUM 而不是 VARCHAR
6.尽可能的使用 NOT NULL
7.固定长度的表会更快
优化数据的方法
1. 选取最适用的字段属性,尽可能减少定义字段宽度,尽量把字段设置NOTNULL,例如’省份’、’性别’最好适用ENUM
2. 使用连接(JOIN)来代替子查询
3. 适用联合(UNION)来代替手动创建的临时表
4. 事务处理
5. 锁定表、优化事务处理
6. 适用外键,优化锁定表
7. 建立索引
8. 优化查询语句
事务的概念以及特性
事务时并发控制的基本单位,所谓事务,他是一个操作序列,这些操作要么不执行,要么都执行,是一个不可分割的工作单位。
特性:
原子性:事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行
一致性:事务应确保数据库的状态从一个一致状态转变为另一个一致状态
隔离性:多个事务并发执行时,一个的事务的执行不应影响其他事物的执行
持久性:已提交的事务对数据库的修改应该永久保存在数据库中
8.索引
索引相当于目录,可以更加方便地用于查询
MySIAM引擎使用B+Tree作为索引结构,叶节点的data域存放的时数据记录的地址。
InnoDB也是使用B+Tree作为索引结构,因为数据文件本身就是索引文件,所以它的叶子节点data保存了完整的数据信息,InnerDB必须要求有主键
9 范式
第一范式:要求数据表的每一个列都是不可分割的基本数据项
第二范式:每一行的所有非主属性都必须完全依赖主键,非主属性完全依赖于主键
第三范式:属性不依赖其他非主属性,消除传递依赖
10 MYSQL与OCACLE的区别
1.Ocacle是大型数据库而mysql只是小型数据库,mysql是开源的
2.oracle支持高并发,大访问量的问题
3.操作的区别,mysql支持主键自动增长型,而oracle,主键一般使用的序列,插入记录时候将序列号的下一个值付给该字段即可
4.单引号的处理,mysql可以用双引号包裹起来的字符串,但是Oracle只是单引号包裹
5.处理分页策略,mysql可以使用limit字段进行限制,但是oracle需要rownum进行限制,操作比较繁琐
数据结构
冒泡排序
public class poSort {
public static void main(String arg[]){
int px[]=new int [] {9,7,8,6,4,1,3,2,5};
for(int x=0;x<px.length;x++){ //控制排序的次数
for(int y=0;y<px.length-1;y++){
if(px[y]>px[y+1]){
int temp=px[y]; //换序
px[y]=px[y+1];
px[y+1]=temp;
}
}
}
for (int x=0;x<px.length;x++){
System.out.println(px[x]+",");
}
}
}
时间复杂度时O(n^2)
选择排序
package com;
public class SelectSort {
public static void main(String[] args) {
int arr[]= {21,3,43,5,7,1}; //定义数组
//遍历排序前的数组
System.out.print("排序前数组元素为:");
for(int i=0;i<arr.length;i++) {
System.out.print(arr[i]);
if(i<arr.length-1) { //除最后一个元素外,依次添加“,”进行分割
System.out.print(",");
}
}
System.out.println(); //换行
selectSort(arr); //调用selectSort()方法,并将实参arr数组传进去
}
public static void selectSort(int[] arr) {
for(int j=0;j<arr.length;j++) { //控制轮数
for(int i=0;i<arr.length-1;i++) { //每循环一次找出一个最值
//比较元素大小,此为从大到小排序,若想从小到大进行排序,只需改为 arr[i]>arr[j] 即可
if(arr[i]<arr[j]) {
//交换位置
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
//遍历排序后的数组,查看效果
System.out.print("排序后数组元素为:");
for(int i=0;i<arr.length;i++) {
System.out.print(arr[i]);
if(i<arr.length-1) { //除最后一个元素外,依次添加“,”进行分割
System.out.print(",");
}
}
}
}
快速排序
package com;
public class quickSort {
public static void main(String[] args) {
int[] arrat = {4, 8, 6, 9, 8, 2, 5, 4, 2, 1};
QuickSort(arrat,0,arrat.length-1);
for (int i=0;i<arrat.length;i++){
System.out.print(arrat[i]);
}
}
public static void QuickSort(int[] array,int start,int end){
int low=start;
int high=end;
int key=array[low];
while(low<high){
while (low<high&&array[high]>=key)
high--;//当end结点值大于基准值事,向前移动
if (low<high){
array[low]=array[high];
low++;
}
while (low<high&&array[low]<=key)
low++;
if(low<high){
array[high]=array[low];
high--;
}
}
array[low]=key;
if(low-1>start) QuickSort(array,start,low-1);
if(high+1<end) QuickSort(array,high+1,end);
}
}
红黑树:
三次握手,四次挥手
网络协议
web技术
九大内置对象
request:封装客户端的请求,其中包含来自GET或POST请求的参数
response:封装服务器对客户端的响应
session:封装用户会话的对象
application:封装服务器运行环境的对象
pageContext:通过该对象可以获取其他对象
page:JSP页面本身
out:输出服务器响应的输出流对象
config:web应用的配置对象
exception:封装页面抛出的异常。
cookie与session
由于http协议事无状态的协议,所以服务器需要记录用户的状态时,就需要用某种机制来识别具体的用户,这个机制就是session,典型例子就是购物车。
这个session是保存在服务端的,有一个唯一标识,在服务器保存session的方法有很多,内存、数据库、文件都有。
集群的时候也要考虑Session的转移,在大型的网站,一般会有专门的Session服务器集群,用来保存用户会话,这个时候Session信息都是放在内存的,使用一些缓存服务比如Memcached之类的来放Session。
cookie:浏览器A访问服务器的时候,服务器就给这个A一个id,浏览器就会将这个id保存在本地cookie中,由web服务器在http响应头中附带给浏览器,一旦浏览器保存了cookie每次访问web服务器时,都会将http请求头的cookie回传给web服务器。
过滤器与监听器以及拦截器
Jquery技术
1. $(document).ready()是个什么函数?为什么要用它?
ready()函数用于文档进入ready状态执行代码,当DOM完全加载,jquery允许你执行代码,使用$(document).ready()的最大好处在于它适用于所有的浏览器,jquery解决了浏览器的难题。
2. $(this)和this关键字在jQuery中有何不同?
$(this)返回一个jquery对象,你可以对它调用多个jquery方法,比如用text()获取文本,用val获取值,而this代表当前元素,他是jquery关键词中的一个,表示上下文中的当前DOM元素,你不能对他调用jquery方法
3. jquery中的选择器,请讲一下有哪些选择器?
大致分为:基本选择器,层次选择器,表单选择器,过滤选择器
基本选择器:id选择器,标签选择器,类选择器
层次选择器:如$("form input")选择所有的form元素中的input元素
过滤选择器:$(tr:frist)选择所有tr元素的第一个
表单选择器:$(":input")选择所有的表单输入元素$(":text")选择所有的text的input元素。
4. jquery的优点:
1) 因为jQuery是轻量级的框架
2) 具有强大的选择器,出色的DOM操作的包装
3) 可靠的时间处理机制(JQuery在处理时间绑定的时候相当可靠)
4) 完善的AJAX
5) 出色的浏览器的兼容性
6) 支持链式操作,隐式迭代
7) 行为层和结构层的分离,还支持丰富的插件
text() - 设置或返回所选元素的文本内容
html() - 设置或返回所选元素的内容(包括 HTML 标记)
val() - 设置或返回表单字段的值
5. Vue与jquery有什么区别
vue是数据驱动,是MVVM框架
jquery是模型驱动
jsp与servlet的区别
jsp是servlet技术的扩展,本质就是servlet的简易方式,servlet和jsp最主要的不同点在于,servlet的应用逻辑是在java文件中,并且完全从表示层中的html里分离出来,而jsp的情况是java和html可以组合位jsp问价,jsp侧重于视图,servlet主要用于控制逻辑。
struts与spring mvc的区别是什么?
拦截级别:struts2是类级别的拦截,springMVC是方法级别的拦截
数据独立性:springMVC的方法之间基本上独立的,独享request和response数据,请求数据通过参数获取,处理结果通过 ModelMap交回给框架,方法之间不共享变量;而structs2虽然方法之间也是独立的,但是其所有的action变量是共 享的,这不会影响程序运行,却给我们编码和读程序时带来了一定的麻烦。
拦截机制:struts2有以自己的interceptor机制,spring用的独立AOP方式,这样导致struts2的配置文件量比springmvc大
对ajax的支持:springmvc集成了ajax,所有ajax使用方便,只需要一个注解@requestbody就可以实现,而struts2一般需要安装插件或者自己写代码才行。
设计模式
说一下熟悉的设计模式?
单例模式:保证被创建一次,节省系统开销。
工厂模式:简单工厂,抽象工厂:解耦代码
观察者模式:定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,他的所有的依赖着都会收到通知并自动更新。
外观模式:提供一个统一的接口,用于访问子系统的一群接口,外观定义了一个高层的接口,让子系统更容易使用。
模板方式模式:定义了一个算法的骨架,而将一些步骤延迟到子类,模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的步骤。
状态模式:允许对象在内部状态改变时改变他的行为。对象看起来好像修改了它的类。
简单工厂与抽象工厂的区别
简单工厂:用来生产同一等级结构中的任意产品,对于增加新的产品,无能为力
工厂方法:用来生产同一等级结构中的固定产品,支持增加任意产品
抽象工厂:用来生产不同产品的全部产品,对于增加新的产品,无能为力,支持增加产品族
spring与springMVC
为什么使用spring?
spring提供了ioc技术,容器帮我们管理依赖的对象,从而不需要自己创建和管理依赖对象了,更轻松的实现了程序的解耦。
spring提供了事务支持,使得事务操作更加方便
spring提供了面向切面编程,可以更方便的处理某一类的问题
更方便的框架集成,spring可以很方便的集成其他框架,比如MyBatis,hibernate等。
spring的注入方式?
setter属性注入
构造方法注入
注解方法注入
spring自动装配bean有哪些方式?
no:默认值,表示没有自动装配,应使用显示bean引用进行装配
byName:它根据bean的名称注入对象依赖项
byType:它根据类型注入对象依赖项
构造函数:通过构造函数来注入依赖项,需要设置大量的参数
autodetect:容器首先通过构造函数使用autowire装配,如果不能,则通过bytype装配
springmvc运行流程
springMVC先将请求发送给dispatcherServlet
dispatcherServlet查询一个或者多个handlerMapping,找到处理请求的controller。
在把请求提交到controller
Controller进行业务逻辑处理后,会返回一个ModelAndView。
Dispathcher查询一个或者三个ViewResolver视图解析器,找到ModelAndView对象指定的视图对象
视图对象负责渲染返回给客户端。
mvc的组件:
DispatchServlet前置控制器
handlermapping映射控制器
controller处理器
ModelandView模型与视图
ViewResolver视图解析器
SpringBoot以及springcloud
springBoot的优点:
配置简单
独立运行
自动装配
无代码生成和xml配置
提供应用监控
易上手
提升开发效率
怎么实现热部署?
热部署为了解决什么问题:
方便了开发项目时,修改静态文件不需要重新启动项目,而达到刷新页面的功能
使用devtools启动热部署,添加devtool库,在配置文件把spring,devtools.restart.enable=true
也可以通过idea工具中开启自动编译
什么是springCloud?
springcloud是一系列框架的有序集合,它利用springboot的开发便利性巧妙地简化了分布式系统基础设施地开发,如服务发现注册、配置中心、消息总栈、负载均衡、断路器、数据监控,都可以用springboot地开发风格做到一键启动和部署。
核心组件:
Eureka:服务注册于发现
Feign:基于动态代理机制,根据注解和选择地机器,拼接请求url地址,发起请求。
Ribbon:实现负载均衡,从一个服务的多台机器中选择一台
Hystrix:提供线程池,不同的服务走不同的线程池,实现了不同服务调用的隔离,避免了服务雪崩的问题
Zuul:网关管理,由Zuul网关转发请求给对应得服务。
hibernate与mybatis
hibernate的优点?
hibernate是对jdbc的封装,大大简化了数据访问层的繁琐的重复性代码
hibernate是一个ORM实现,很大程度上简化了DAO层的编码功能
可以恒方便的进行数据库的移植工作
提供了缓存机制,是程序执行更改的高效。
hibernate是如何进行工作的
读取并配置文件->读取并解析映射文件->打开session->创建事务->进行持久化操作->提交事务-关闭session-关闭sessionFactory
hibernate实体类必须要有无参构造函数吗?为什么?
hibernate中每个实体类必须提供一个无参构造函数,因为hibernate框架要使用reflecttion API,通过调用ClassnewInstance()来创建实体类的实例,如果没有无参的构造函数就会抛出异常。
mybatis有几种分页?
分页方式:逻辑分页跟物理分页
逻辑分页:使用mybatis自带的RowBounds进行分页,他是一次性查询很多数据,然后在数据中在进行检索。
物理分页:自己手写SQL分页或使用分页插件PageHelper,去数据库中查询指定条目的分页数据的形式。
逻辑分页是一次性查询很多数据,然后再结果中检索分页的数据,这样做的弊端是需要消耗大量的内存,有内存溢出的风险,对数据库的压力较大。
物理分页是从数据库查询指定条数的数据,弥补了一次性全部查询出的所有数据的种种缺点,比如需要大量的内存,对数据库查询压力较大等问题。
第二季–即将更新中