Java面试、Java八股文(适用无工作经验者)

本篇文章适用于0工作经验的刚毕业的应届生,跨专业培训班的转行生,考研失败的非应届毕业生,纯纯干货,希望大家多多点赞,需要电子版的可以评论区留言!!!

一、Java基础

1.什么是面向对象?谈谈你对面向对象的理解?

面向过程:比如洗衣机洗衣服,将任务拆解成一系列步骤(也就是函数),第一步打开洗衣机,第二步放衣服,第三步放洗衣粉,第四步清洗,第五步烘干

面向对象:人和洗衣机两个对象,分析每个对象要做的事情,人:打开洗衣机,放衣服,放洗衣粉,洗衣机:清洗,烘干

面向过程更加注重步骤以及顺序,面向对象注重有哪些对象,每个对象要做具体的事情。

面向过程比较直接高效,而面向对象易于复用、扩展和维护

2.Java面向对象有哪些特征?

封装:封装了类的内部实现机制,和方法封装了一些实现机制一样,可以在不影响使用的情况下改变类的内部的结构。只要对应的接口不变,类内部的结构随意改变,同时也保护了数据,在面向对象编程中是一大改进,主要增加了代码的可维护性,便于修改。(封装好的代码可以重复使用,增加了代码的复用性)

继承:如果有一个父类,例如动物,有一些自己的属性和方法,在封装好的前提下,在它的子类中狗猫就没有必要重新来一遍,可以直接从父类中直接继承过来,复用的概念,可以增加方法的复用性。(增加了代码的复用性)

多态:多态是指类和类之间的关系,第一要有继承,第二要有重写,第三父类引用指向子类对象

Animal animal = new Dog();当调用方法时,是狗在叫唤而不是父类在叫唤(增加了代码的可移植性、健壮性、灵活性,因为实现随意改变)

多态中无法调用子类特有的功能,因为前提是方法重写

3.JDK、JRE、JVM三者区别和联系?

JDK:Java开发工具(开发人员使用)

JRE:Java运行时环境(用户使用)

JVM:Java虚拟机(解释class文件,让操作系统可以执行)

JDK包含JRE,JRE中的bin文件夹实际上就是JVM,lib文件夹是类库。

JDK还包含Java工具(javac、java等)

.java文件由java工具中的javac编译成.class文件,.class文件会放到JVM上面,JVM有很多版本,JVM拿到.class文件之后会根据lib目录中的类库解释class文件,翻译成机器码然后映射到操作系统。
![在这里插入图片描述](https://img-blog.csdnimg.cn/2f6ccb9dfb0144389ab2ca91fe5788bd.png

4.Java中==和equals有哪些区别?

==对比的是地址:基本数据类型比的是栈中的变量值,引用类型比较的是堆中内存对象的地址

equals:objcet中默认也是采用==比较,通常会重写——把字符串中每个字符取出来比较是否相等

一个是方法一个是运算符

在这里插入图片描述

str1是在堆中的常量池分配,str2是堆中分配

5.final

最终的

  • 修饰类:表示类不可以被继承
  • 修饰方法:表示方法不可以被子类重写,可以重载(形参列表改变是可以的)
  • 修饰变量:表示变量一旦被赋值就不可以更改他的值

6.String、StringBuffer、StringBuilder区别及使用场景?

String是final修饰的,不可变的字符串,s对象是String类型执行一个字符串abc,若想变成abcdef则会变成一个新的地址(针对地址来讲,若地址不变则内容不可变)

StringBuilder底层原理是数组扩容,当声明一个StringBuilder对象时,实际上指向一个对应空间,对应的空间指向一个value属性,一个count属性,value属性就是一个数组,count是有多少个长度被占用,一旦放不下了就会实现数组扩容,此时地址会变,会指向长度更长的数组的地址

StringBuilder线程不安全,效率高

StringBuffer线程安全,效率低(StringBuffer每个方法都用synchronized修饰)

对象是否线程安全——多线程、共享变量、结果不变

优先使用StringBuilder,多线程使用共享变量时使用StringBuffer

7.重载和重写的区别

重载:发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同(重载和返回值无关)

重写:发生在父子类中,方法名、参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类,如果父类方法中访问修饰符private,子类不能重写

8.List和Set区别

List:有序,按对象进入的顺序保存对象,可重复,允许多个Null元素对象,不仅可以使用迭代器取出元素,也可以通过get下标获得元素

Set:无序,不可重复,最多允许一个null元素对象,取元素只能用迭代器取

9.Java接口和抽象类有哪些区别?

  • 抽象类除了有抽象方法还可以有普通方法,接口中只能存在抽象方法
  • 抽象类只能继承一个,接口可以实现多个
  • 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的

抽象类更重点描述抽象的概念,比如动物、植物、食物

接口描述某些共同事务之间所具有的共同的特征,flyable会飞的,飞机、鸟

(描述概念用抽象类,描述特征用接口)

相同点:

1.不能够实例化

2.可以将抽象类和接口类型作为引用类型

3.一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进行实现,否则该类仍然需要被声明为抽象类

不同:

抽象类:

1.抽象类可以定义构造器

2.可以有抽象方法和具体方法

3.接口中的成员都是public的

4.抽象类中可以定义成员变量

5.有抽象方法的类必须被声明为抽象类,二抽象类未必要有抽象方法

6.抽象类可以包含静态方法

7.一个类只能继承一个抽象类

接口:

1.接口中不能定义构造器

2.方法全部都是抽象方法

3.抽象类中的成员可以是private、默认、protected、public

4.接口中定义的成员变量实际上都是常量

5.接口中不能有静态方法

6.一个类可以实现多个接口

10.hashcode和equals如何使用?

JDK8之前哈希表是由数组+链表构成,JDK8之后哈希表由数组+链表+红黑树构成

对象地址对数组长度取余得到哈希值,若在同一个数组下标位置出现,则调用equals方法判断地址是否相同,若相同则不写,若不同则存入链表中。

当链表长度大于超过8时自动转为红黑树。

数组扩容:

数组默认长度16,加载因子0.75,16*0.75=12,则当数组存满到12时就扩容,默认每次扩容时原先的两倍

11.ArrayList和LinkedList的区别?

ArrayList和LinkedList都实现了List接口,但是底层实现的数据结构不同。

ArrayList底层是由数组实现的,每个数据是 挨着的底下带索引的,012345678。(随机访问)

LinkedList底层是有链表实现的,链表的结点不仅存储数据还要存储指向下一个数据的指针。(更加占用内存,因为每一个结点存储2个引用,一个纸箱前一个元素,一个指向后一个元素)

在插入、删除数据较多时使用链表结构,访问数据较多时用数组结构,若访问数据使用链表则会从头结点开始挨个访问。

ArrayList更适合随机查找

12.HashMap和HashTable的区别?

HashMap方法是线程非安全的

HashTable里面每个方法都加了锁——效率较低

13.ConcurrentHashMap原理?

分段锁机制,线程安全且效率更高

JDK7:ReentrantLock+Segment+HashEntry,一个Segment包含一个HashEntry数组,每个HashEntry又是一个链表结构,第一步K定位一个段,其他的Segment不受影响

元素查询:第一次Hash定位Segment,第二次Hash定位数组下标

JDK8:synchronized+CAS(乐观锁)+Node+红黑树,扩容和哈希冲突是使用synchronized,锁的是head节点,效率更高

14.如何实现一个IOC容器

(1)写一个配置文件,包扫描路径

(2)获取.class文件

(3)反射获取需要的IOC管理的类

(4)对需要注入的类进行依赖注入

15.什么是字节码?采用字节码的好处是什么?

机器和编译程序之间加入了虚拟的机器JVM,JVM帮助我们进行适配可以将程序在不同的操作系统运行。javac把java程序编译成字节码文件,解释器将字节码文件解释称特定系统的机器码运行。

字节码并不专一对待一种特定的机器,因此,java程序无需重新编译就可以在不同的计算机上运行

16.Java类加载器有哪些?

JDK自带三个类加载器:BootStrapClassLoader、ExtClassLoader、AppClassLoader

BootStrapClassLoader是ExtClassLoader的父类加载器,默认负责加载JAVA_HOMElib下的jar包和class文件

ExtClassLoader是AppClassLoader的父类加载器(都是通过parent变量维护,不是继承关系),扩展器加载器加载ext文件的jar包

AppClassLoader加载的是classpath下的类文件(默认的系统类加载器),是自定义加载器的父类,线程上下文加载器

17.双亲委派模型

main方法启动,main方法由AppClassLoader加载,AppClassLoader加载的时候要向上委派,实际上就是查找缓存,如果没有继续向上委派,如果找到就直接返回。如果还是没有找到就向下查找,在加载路径下加载,如果有就返回,如果没有继续向下查找。(向上委派查找缓存,向下委派查找加载路径

在这里插入图片描述

优点:

  • 安全性,比如String类如果自己写不会被加载会向上委派,java中所有以java.开头的都不会被加载
  • 避免了类的重复加载,相同的class文件被不同的类加载器加载就是不同的两个类

18.Java中的异常处理机制是什么?

Java中所有的异常都来自父类Throwable

Throwable有两个子类Exception和Error

Error会导致程序停止

Exception不会导致程序停止(运行时异常,编译时异常)

运行时异常会导致当前线程执行失败,不会影响其他线程

抛出异常:throw,在方法内部,要加具体异常对象,手动制造一个异常

异常捕获:try捕获可能出现异常的代码,先和catch异常类型判断,若相同则执行catch中的代码,可以写多个catch,finally一般进行io流的关闭,无论是否出现异常,finally都执行

声明异常:throws,声明在方法处,整个方法可能出现某种异常类型

19.JDK1.8的新特性有哪些?

接口的默认方法:接口中的方法是不允许实现的,在JDK1.8中为了兼容Lambda表达式,接口中可以默认带实现(也就是可以添加非抽象方法的实现)

Lambda表达式:面向函数编程,简化编程

函数式接口:简化变成的方式

集合类中产生了许多新的接口Stream接口——简化集合和数组操作的API,结合了Lambda表达式,使用filter过滤

20.计算机中的最小单位?

1字节=8位,字节是计算机中的最小单位

21.短路运算符左边执行成功,右边不执行

&&、||

22.冒泡排序

每次从数组中找到最大值放在数组后面(最后一个位置确定后,无须比较替换)

23.方法调用的内存原理

方法没被调用时,在方法区中的字节码文件中存放

方法被调用时,进入栈中执行

方法执行完后移出栈内存,main方法最后移出

24.抽象类为什么不能创建对象?

因为抽象类有抽象方法,抽象方法不能被调用

25.JDK1.8新特性Stream流

简化集合和数组操作的API
List<String> names = new ArrayList<>(); names.stream.filter(s->s.startswith("张").filter(s->s.length()==3).forEach(s->System.out.println(s)));
先得到集合或数组的Stream流,把元素放上去然后用Stream流简化的API来方便的操作元素,再把流收集起来Collections.toList()

26.Java代理的几种实现方式?

代理模式:代理类的对象本身不直接实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务

静态代理:通常只代理一个类,代理模式实现使用者与真实处理这的分离,降低耦合度(静态代理在程序运行前就存在)

JDK动态代理:通过反射来实现(动态代理在程序运行前不存在),动态代理最关键的一个接口InvocationHandler和一个类Proxy,动态代理实际上就是AOP的简单实现,动态代理类需要实现InvocationHandler接口,测试时需要Proxy类

27.static的作用

static是静态的,修饰成员变量,表示该成员变量只在内存中存储一份,可以被共享、访问修改

28.Java死锁如何避免?

产生死锁的几个原因:

(1)一个资源每次只能被一个线程调用

(2)一个线程在阻塞等待时,不释放占有的资源

(3)一个线程已经获得的资源,在未使用前,不能被剥夺

(4)若干线程首尾循环等待的资源关系

解决:

(1)要注意加锁的顺序,保证每个线程按照同样的顺序加锁

(2)要注意加锁的时限

(3)死锁检查,是一种预防机制

29.关于IO流

在这里插入图片描述

30.怎么判断String=“”?

使用s.empty()、s.length()0、s""

31.常量用static修饰的好处?

在创建类的多个对象时,用static修饰的常量在内存中只有一份拷贝。不用static修饰则可能有多份拷贝

二、多线程与并发

1.线程和进程?

进程是操作系统分配资源的最小单位,线程是CPU调度的最小单位,一个进程可以包含多个线程

不同进程之间的数据很难共享,同一进程下的不同线程之间数据很容易共享

进程间不会相互影响,一个线程挂掉整个进程都会受到影响

2.线程的生命周期,线程有那些状态?

(1)线程有五种状态:创建、就绪、运行、阻塞、死亡

(2)阻塞有三种:

<1>等待阻塞:运行的线程执行了wait()方法,线程会释放占用的所有资源,JVM会把该线程放入等待池中,不能被自动唤醒,需要其他线程调用notify或notifyAll才能被唤醒,wait是Object中的方法

<2>同步阻塞:运行的线程在获取对象的同步锁时,JVM会把没抢到锁的线程放入锁池中。

<3>其他阻塞:sleep或者join、或者IO请求,当sleep状态超时,join等待线程终止,IO处理完毕,线程重新进入就绪状态。sleep是Thread类中的方法

1.新建状态:新创建了一个线程对象

2.就绪状态:线程对象创建好了,调用了start方法。调用了start方法变成就绪状态,位于可运行线程池中,等待CPU的分配

3.运行状态:就绪状态的线程获取CPU

4.阻塞状态:线程因为某些原因放弃了CPU的使用权,暂时停止运行,直到线程进入就绪状态,才有机会运行

5.死亡状态:线程执行完了或者因为异常推出了run方法

3.sleep()、wait()、join()、yield()的区别?

(1)锁池:所有竞争同步锁的线程都会放在锁池中,当前对象的锁已经被其中一个线程得到,则其他线程需要在这个锁池进行等待,当前面的线程释放同步锁后,所持重的线程再去竞争同步锁,当某个线程得到后进入就绪状态等待CPU分配资源

(2)等待池:当我们调用wait方法后,线程会放到等待池中,只有notify或notifyAll才可以唤醒,notify随机在等待池中选一个线程放到锁池中,notifyAll把所有线程放到锁池

<1>sleep是Thread类的静态方法,wait是Object中的方法

<2>sleep方法不会释放lock,但是wait会释放。如果sleep时该线程有锁,那么sleep不会释放这个锁,把锁带着一起进入冻结状态

<3>sleep方法不依赖synchronized,wait需要依赖synchronized

<4>wait需要被唤醒,sleep不需要被唤醒

<5>sleep一般用于当前线程休眠,wait用于多线程之间的通信

<6>sleep会让出CPU执行时间,强制切换上下文,wait不一定让出CPU,wait之后有机会重新竞争所

yield()执行后线程直接进入就绪状态,马上释放了CPU,保留了cpu执行资格,有可能cpu下次继续执行

join()执行后线程进入阻塞状态,例如线程B中调用线程A的join,那么线程B会进入阻塞状态,直到 线程A执行完才能继续执行——join一定先执行

4.说说你对线程安全的理解

不是线程安全,应该是内存安全,堆内存是共享内存,可以被所有线程访问

当多个线程访问同一个对象时,对象都是存在堆中的,调用这个对象的行为都能获得正确结果称为线程安全

堆是进程和线程公有的空间,没有分配的空间是全局堆,局部堆是用户分配的空间

栈是每个线程独有的,保存其运行状态和局部变量。栈在线程开始的时候初始化,每个线程的栈互相独立,栈是线程安全的

5.Thread和Runnable的区别?

Thread本身是实现Runnable接口的

Thread提供了更多的功能

6.说说你对守护线程的理解?

守护线程:为所有的非守护线程提供服务的线程(Java有两种线程,守护线程、用户线程)(只要是守护线程就是所有非守护线程的保姆)

守护线程的终止自身无法控制,当其他线程结束了,守护线程就中断了

守护线程的作用:GC垃圾回收线程,当程序中不再运行任何运行的线程,垃圾回收线程就会中断,

为其他线程提供服务,程序结束时这个线程必须正常且立即关闭

start()之前设置成守护线程

7.ThreadLocal的原理和使用场景

(1)线程本地存储机制,可以利用这个机制将数据缓存在线程内部,缓存到线程的map容器中

(2)底层是ThreadLocalMap实现的,Map的key是ThreadLocal对象,value是需要缓存的值

(3)线程池中的线程有可能内存泄露,在处理任务过程中不停地存储数据,存储空间可能会满,所以使用remove方法移除数据

ThreadLocalMap是一个弱引用,如果没有指定key,就会被垃圾回收

(4)ThreadLocalMap是当前线程私有的,所以不用考虑线程安全问题

8.并发、并行、串行的区别?

串行:在时间上不可能发生重叠,前一个任务没搞定,下一个任务就只能等着

并行:在时间上重叠,两个任务在同一时刻互不干扰的同时执行

并发:允许两个任务彼此干扰,同意时间点、只有一个任务运行,交替执行

9.并发的三大特性

(1)原子性:如果方法是原子操作,CPU在这行这个代码的时候必须全部执行完

(2)可见性:当多个线程访问同一个变量时,一个线程修改了变量的值,其他线程能够立即看得到修改的值

(3)有序性:JVM为了执行效率不保证执行顺序一致,但是保证执行结果一致

10.为什么用线程池?解释下线程池参数?

(1)降低资源消耗,线程创建以及销毁比较消耗资源,使用线程池可以提升线程利用率

(2)提高响应速度,任务来了,直接有线程可用可执行,省去了创建线程操作

(3)提高线程的可管理型,线程个数是有限的,使用线程池可以统一分配监控

在这里插入图片描述

在这里插入图片描述

11.简述线程池处理流程

创建了一个线程池,若要加入任务,首先判断核心线程是否已满,未满就创建核心线程执行,如果核心线程已满,判断任务队列是否已满,如果队列没满,将任务放到队列中,如果任务队列已满,判断最大线程数是否达到,如果最大线程数没有达到,创建临时线程(临时线程若空下来超过超时时间,就会被回收),若已达到最大线程则会根据拒绝策略处理任务

在这里插入图片描述

12.线程池中阻塞队列的作用?为什么是先添加队列而不是先创建最大线程?

(1)一般队列只能保证作为一个有限长度的缓冲区,超过长度就无法保留当前任务,阻塞队列通过阻塞可以保留住当前想要继续入队的任务。

阻塞队列可以保证任务队列中没有任务时阻塞获取任务的线程(阻塞队列可以帮忙让没有任务的核心线程wait进入等待池)

阻塞队列也自带唤醒功能。(保存任务,阻塞线程,唤醒线程)

(2)在创建线程的时候要获取一个全局锁,其他线程都会阻塞,影响整体效率(线程创建以及销毁很消耗性能)

13.线程池中线程复用原理

线程池将线程和任务解耦,线程是线程,任务是任务。(摆脱了一个线程必须执行一个任务)

在线程池中可以从阻塞队列中不断获取新任务执行,核心原理线程池对Thread进行了封装,并不是每次都调用satrt()方法,而是让每个线程去执行一个循环任务,调用的是run方法

业务逻辑并没有写在线程池中的线程的run方法中,而是利用线程调用任务中的run方法

14.新任务拒绝策略

丢弃任务并抛出

丢弃任务不抛出

丢弃队列中等待最久的任务,把当前任务加入队列

由主线程负责调用任务的run()方法,绕过线程池

三、JavaWeb

1.http的长连接和短连接

HTTP/1.0默认使用短连接,客户端和服务器每进行一次HTTP操作,就建立一次连接

HTTP/1.1默认使用长连接,当网页打开后,客户端和服务器用于传输数据的TCP连接不会关闭

2.http常见状态码

404请求资源不存在

500服务器异常

3.GET请求和POST请求区别?

(1)GET请求的数据会附在URL之后,以问号分割URL和数据,POST请求把数据放在HTTP的包体中

(2)GET请求通过URL传输数据,浏览器对URL的长度有限制

(3)POST的安全性比GET的更高,通过GET请求提交数据,会在URL后面显示用户名和密码等

(4)GET向服务器发起索取请求,POST向服务器发送提交请求

4.Cookie和Session的区别?

Cookie是Web服务器发送给浏览器的一块信息,浏览器会在本地的一个文件中给每个Web服务器存储cookie,以后浏览器再给Web服务器发送请求时,同时会发送所有为该服务器所存储的cookie。

Session是存储在Web服务器的一块信息,Session对象存储指定用户所需要的属性及配置信息。当用户在页面跳转中,存储在Session对象中的变量不会丢失。

无论客户端怎样设置,Session都能正常工作。当客户端禁用cookie时,无法使用cookie。

在存储数据量方面:session能够存储任意java对象,cookie只能存储string类型的对象

5.在单点登录中Cookie被禁用了怎么办?

单点登录的原理是后端生成一个sessionID,然后设置到Cookie中,我们是从Cookie中获得sessionID,我们还可以通过HTTP请求头手动设置sessionID。

6.什么是JSP?什么是Servlet?JSP和Servlet有什么区别?

JSP本质上是一个Servlet,它是Servlet的一种特殊形式,每个JSP页面都是一个Servlet实例。

JSP是html中内嵌的Java代码,侧重页面显示

Servlet是html和Java代码分离,更侧重业务逻辑,mvc设计模式中Servlet位于控制层,JSP位于视图层。

JVM 只能识别 Java 类,并不能识别 jsp 代码!web 容器收到以.jsp 为扩展名的 url 请求时,会将访问请求交给tomcat 中 jsp 引擎处理,每个 jsp 页面第一次被访问时,jsp 引擎将 jsp 代码解释为一个 servlet 源程序,接着编译servlet 源程序生成.class 文件,再有 web 容器 servlet 引擎去装载执行servlet 程序,实现页面交互。

7.Servlet的生命周期

Servlet加载和实例化–>初始化–>服务–>销毁

(1)当Servlet被访问时由容器创建Servlet对象

(2)在Servlet实例化之后调用init()初始化方法,完成一些加载配置文件,创建连接之类的方法,该方法只调用一次

(3)每次调用Servlet时都会执行service()方法

(4)当执行destroy()方法后,容器会释放掉该Servlet实例,然后该实例被垃圾回收

8.Servlet如何与Tomcat结合工作?

(1)客户端浏览器向服务端(Tomcat)发送一个HTTP请求

(2)Servlet容器接收客户端浏览器的请求

(3)Servlet容器创建一个HttpRequest对象,将Web Client请求的信息封装到这个对象中。

4、Servlet容器创建一个HttpResponse对象

5、Servlet容器调用HttpServlet对象的service方法,把HttpRequest对象与HttpResponse对象作为参数传给HttpServlet 对象。

6、HttpServlet调用HttpRequest对象的有关方法,获取Http请求信息。

7、HttpServlet调用HttpResponse对象的有关方法,生成响应数据。

9.Servlet特性

单例多线程

10.转发和重定向的区别?

转发在服务器端完成的;重定向是在客户端完成的
转发的速度快;重定向速度慢
转发的是同一次请求;重定向客户端发送两次不同请求
转发不会执行转发后的代码;重定向会执行重定向之后的代码
转发地址栏没有变化;重定向地址栏有变化
转发必须是在同一台服务器下完成;重定向可以在不同的服务器下完成
转发可以使用request域共享数据;重定向是两次请求不可以

11.Cookie过期和Session超时的区别?

Cookie过期:

Cookie由浏览器管理,如果Cookie有过期时间,浏览器会在过期时间将其销毁。如果没有设置过期时间浏览器关闭后Cookie会过期

Session超时:

Session对象由服务器管理,服务器会计算Session对象的不活动时间,如果Session对象设置了超时时间,Session对象超过此时间会被销毁。如果没有设置默认30分钟会被销毁(服务器默认配置)。

12.jquery如何发送ajax请求?

1、 . g e t ( ) , .get(), .get(),.post()

两个方法使用基本一样,根据需要传入四个参数,请求地址、参数列表、回调函数以及服务器响应数据类型。Get方法会有浏览器缓存问题、Post方法没有。

2、$.ajax()

这个方法需要通过js对象配置请求的相关参数,例如:

$.ajax({

type:请求方式,

url: 请求地址,

data:请求参数,

dataType: 服务器返回值类型,

success:回调函数

});

13.JSP的内置对象有哪些?

1、pagecontext pagecontext 对象的作用是取得任何范围的参数,通过它可以获取 jsp页面的out、request、response、session、application 等对象

2、request 服务器端取得客户端的信息:头信息、Cookie、请求参数、MVC设计模式

3、response 服务器端回应给客户端信息:Cookie、重定向

4、session 表示每一个用户,用于登录验证上

5、application application对象可将信息保存在服务器中,直到服务器关闭,否则application对象中保存的信息会在整个应用中都有效。

6、config config 对象的主要作用是取得服务器的配置信息。

7、exception 表示的是错误页的处理操作

8、page 如同this一样,表示整个JSP页面

9、out 输出,但是尽量使用表达式输出

14.什么是时间戳?

时间戳就是利用时间来标记一个事件,能够表示一份数据在一个特定时间点已经存在的完整的可验证的数据。时间戳证明在这个时间点发生了什么,任何人都不能篡改,可以一定程度上解决版权问题。

四、MySQL

1.JDBC操作流程

(1)Class.forName()注册驱动

(2)DriverManager.getConnection()获取连接

(3)获取执行sql对象Statement、PreparedStatement

(4)执行sql

(5)释放资源
@Test public void test12() throws SQLException { String sql = "select * from dept"; Statement st = conn.createStatement(); ResultSet rs = st.executeQuery(sql); System.out.println("--------------所有部门信息------------------------"); while (rs.next()) { System.out.println("部门编号:"+rs.getInt("deptno")); System.out.println("部门名:"+rs.getString("dname")); System.out.println("部门所在地:"+rs.getString("loc")); System.out.println(); } System.out.println("----------------------------------------"); }

2.数据库连接池作用?

数据库连接池一直保持一个不小于最小连接的数量,当数量不够时会创建连接,直到最大连接数量,之后数据库就会等待,避免数据库连接资源浪费

3.MySQL性能优化

(1)当只有一行数据使用limit 1:找到一条停止,而不是继续查找下一条符合条件的数据

(2)选择正确的数据库引擎:

MyISAM存储引擎对于大量查找操作非常快,但是对于写操作应用不是很好,甚至一条update操作会锁住整张表,知道update操作结束才能继续使用。

InnoDB对于一些小的应用会比MyISAM还慢,但是支持行锁,所以在写的操作更优秀,还支持很多高级应用,事务。

4.SQL语句优化

(1)尽量让数据表中数据not null

(2)多个表连查效率较低,尽量涉及多表联查的情况分解成多个查找

(3)limit后基数较大时,使用between,and

(4)尽量避免列上运算,这样会导致索引失效

5.索引的基本原理

索引的作用:索引用来快速地寻找那些具有特定值的记录,如果没有索引,一般来说就会遍历整张表查询。

索引原理:把无序的数据变成有序的查询

哈希索引:将每个数据的值获取一个哈希值,把所有哈希值放到哈希表中

6.MySQL聚簇索引和非聚簇索引区别?

聚簇和非聚簇索引数据结构都是B+树

聚簇索引和非聚簇索引的非叶子结点都没有数据,存的都是索引

聚簇索引:非叶子结点存储索引不存储数据,叶子结点将数据和索引存在一起,并且按照一定顺序组织,找到索引就找到数据,数据的物理存放顺序和索引顺序一致,索引是相邻的对应的数据也一定是相邻的(索引挨在一起,那么数据也挨在一起)

非聚簇索引:非叶子结点存储索引不存储数据,叶子结点不存数据,存储的都是数据行地址(根据地址查找数据)

聚簇索引优势:

查询聚簇索引可以直接获得数据,非聚簇索引需要查找两次;

聚簇索引对于范围查询的效率很高(聚簇索引有一定的顺序)

聚簇索引适合排序

聚簇索引劣势:

维护索引很昂贵,当插入新数据,本页的数据满了会移到新页中,因为他是顺序存储的;

如果使用随机ID作为主键,数据存储比较稀疏,每次插入新数据都会重新排序

如果主键占的内存比较大,那么辅助索引将会变大(其他索引,存的不是数据地址行存的是主键之类的)

7.MySQL索引的数据结构,各自优劣

哈希索引只适合单条等值查询

InnoDB默认使用B+树索引

B+树:(根节点往下找)

B+树是一个平衡的多叉树,从根节点到每个子节点的高度差值不超过1,同层级的节点间有指针相互连接(是双向的指针,这幅图没显示)。有顺序,有双向指针快速移动,效率很高

在这里插入图片描述

哈希索引:

哈希索引采用一定的哈希算法,把键值换算成哈希值,检索时不需要类似B+树那样从根节点到叶子结点逐级查找,只需要一次哈希算法找到哈希值,只适合等值查询,因为哈希索引没有顺序

在大量重复键值情况下,还会产生哈希碰撞

8.索引设计的原则

查询更快、占用空间更小

9.MySQL锁的类型有哪些?

基于锁的属性:共享锁、排它锁

基于锁的粒度:行级锁、表级锁

共享锁:当一个事务为数据加了一个读锁,其他事务只能为这个数据加读锁不能加写锁

排它锁:一个事务为数据加了一个写锁,其他事务不能为这个数据再加写锁和读锁

表锁:锁住的是整个表,下一个事务要访问只能等锁释放

行锁:只锁住某一行或多行,当其他事务如果访问不是锁住的行是可以访问的

记录锁:行锁的一种,一条记录,命中的字段是唯一索引

页锁:锁一页数据(介于表锁和行锁之间)

10.MySQL执行计划怎么看?

(1)Explain的作用: 使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的。分析你的查询语句或是表结构的性能瓶颈。

(2)id:表的读取顺序。id号每个号码,表示一趟独立的查询。一个sql 的查询趟数越少越好。

(3)type:数据读取操作的操作类型。出现all(全表扫描太慢)、index(只遍历索引树)、range(范围查询)等类型需要建索引优化。

(2)key_len:查询中使用索引的长度,数值越大越好

(3)rows:被物理扫描的行数,数值越小越好

(4)extra:额外信息,反映排序、分组、关联的问题,如出现Using filesort、Using temporary、using join buffer等信息,必须建索引优化

11.事务的基本特性和隔离级别?

  • 原子性(Atomicity):事务是不可分割的最小操作单位,要么同时成功,要么同时失败
  • 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态
  • 隔离性(Isolation):如果有两个事务,运行在相同的时间内,执行相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。
  • 持久性(Durability):事务一旦提交,会更持久的保存在数据库中,不会被回滚

不同的事务有不同的id

隔离有4个隔离级别:

read uncommit读未提交(不能忍受的):可能会读到其他事务未提交的数据,也叫脏读

read commit读已提交:A事务可能提交了2次,B事务读取到了前后两个结果,不可重复度(Oracle)

repeatable read可重复度:MySQL默认级别,第一次读到500数据,第二次读不管是否改变只是用第一次读取的数据(一直读取一样的数据,会出现幻读)

serializable串行:为每行数据加锁,会导致大量超时和锁竞争问题

12.简述MyISAM和InnoDB的区别?

MyISAM:(非聚簇索引)

不支持事务,但是每次查询都是原子的;

每次操作都对整个表加锁

存储表的总行数

一个MyISAM表有三个文件:索引文件、表结构文件、数据文件

采用非聚簇索引,在索引文件查找数据地址,再去数据文件中查找

适合大量查找(索引占的内存空间小)

不支持外键

InnoDB:

支持事务

行锁

支持ACID,支持事务的四个隔离级别

不存储总行数,需要进行全表扫描

采用聚簇索引,一个InnoDB文件中主键和数据存在一起,索引是有顺序的,最好采用自增主键

支持外键

13.SQL语句练习

(1)查询重复姓名的SQL

having可以用聚合函数,where不可以用聚合函数

select 姓名,count(姓名) from 学生表 group by 姓名 having count(姓名)>=2

14.怎么处理慢查询?

在业务系统中,使用主键查询,一般不会出现慢查询,关联查询还有复杂的sql可能会出现慢查询

首先要搞明白慢查询的原因,查询没有命中索引,加载了不需要的数据列,还有可能数据量太大

(1)首先分析sql语句,看是否加载了不需要的数据列

(2)分析语句的执行计划,是否命中了索引,还有效率比较高的索引(最重要的一步)

(3)数据量太大,需要进行分表

15.什么是左外连接?

左外连接:除了匹配两张表中相关联的记录,还会匹配左表中剩余的记录,右表未匹配到的字段用null来表示

16.数据库的3种时间类型?

Date、Datetime、Tempstamp

17.having和where的区别?

having可以用聚合函数,where不能用聚合函数

五、Spring

1.Spring创建Bean对象的过程

1.1Spring如何创建对象?

通过ApplicationContext创建一个bean容器,然后通过getBean()方法得到bean对象,就可以调用对象中的方法了。

正常通过new一个对象创建的对象是没有值的,bean对象通过依赖注入会赋值(通过依赖注入才会成为bean对象

UserService类–>推断构造方法–>对象–>依赖注入–>初始化前–>初始化–>初始化后(AOP)–>代理对象–>放入map(这个map叫做单例池)–>bean对象

1.2什么是单例池?作用是什么?

Map的key是bean的名字,value是bean对象

若是多例bean就没有必要使用map了,因为每次都创建一个新的对象

1.3bean对象和普通对象的区别是什么?

普通对象经过依赖注入,等操作变成bean对象,不需要实例化对象,只需要在Spring容器中就可以获得bean对象

1.4@PostConstruct注解如何工作

初始化前调用的方法

1.5bean初始化如何工作?

实现InitializingBean接口,重写afterPropertiesSet()方法

1.6Bean的实例化和Bean的初始化有什么区别?

Bean的实例化:通过构造方法得到对象

Bean的初始化:创建Bean的过程中回去调用的方法

1.7什么是初始化后?

如果有AOP就把代理对象放到map单例池中

1.8推断构造方法?

当有无参构造方法时使用无参构造方法,如果没有无参构造方法有多个有参构造方法报错,有一个就使用那一个,使用@Autowired注解会指定使用构造方法

1.9Spring自动装配常用的两种装配模式

先根据类型byType去找,再根据名字byName去找

2.Spring是什么?

Spring是轻量级开源的J2EE框架。他是一个容器框架,用来装JavaBean(Java对象),也是中间层框架,可以起到一个连接作用,比如吧SpringMVC和MyBatis粘合在一起运用,可以让我们的企业开发更快、更简洁。

Spring是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器框架

–从大小和开销两方面而言,Spring都是轻量级的。

–通过控制反转(IOC)的技术达到松耦合的目的。(不需要对象之间进行强依赖)

–Spring使用JavaBean的set方法和构造方法等,在我们创建bean对象的同时自动注入数据

–提供了AOP面向切面编程,允许通过分离应用的业务逻辑与系统级服务进行内聚性的开发。(比如说日志,没有使用AOP打印日志要到处分散到代码中,使用AOP可以采用一个专门打印日志的切面)、权限管理、事务,AOP底层是动态代理

–管理对象(Bean)的配置和生命周期,如果没有Spring管理bean,往往通过new一个对象,对对象属性和赋值,有了Spring,对象整个生命周期由Spring管理,Spring是一个容器。

–将简单的组件配置组合成复杂的应用,MyBatis、Redis整合到Spring中。

3.谈谈你对AOP的理解?

面向切面编程,不修改原来代码的同时,增加系统的新功能。

在程序开发中,系统由许多不同的组件所组成的,每一个组件可能负责一块特定的功能,每一个接口除了实现自身的核心功能之外,比如商城项目有订单接口,支付接口,查询接口等等。每一个接口除了要实现自身的业务逻辑之外,例如查订单的除了要查询订单之外还要打印日志,处理异常,打印日志处理异常和核心逻辑无关,但是必须要做,AOP就是解决这些问题。

在各个业务逻辑中打印日志,重复打印日志操作,不利于各个模块的重用。

AOP将程序中的交叉业务逻辑(比如安全,日志,事务等),封装成一个切面,然后把切面注入到目标对象(具体业务逻辑)中去。

AOP可以自动对某个方法进行增强,可以在执行某个方法之前额外的做一些事情。

4.谈谈你对IOC的理解?

容器概念、控制反转、依赖注入。

  • 容器概念:

IOC本身是一个容器,实际上就是一个map(key,value),用来存放各种对象(在XML中配置的bean、以及注解修饰的类实例,也就是bean对象都是存放在IOC容器中),在项目启动时,会读取配置文件中的bean,将实例创建出来存放到map中。

此时map中有了各种对象,再通过DI注入(@autowired、@resource等注解,xml里bean结点内的ref属性,项目启动时会读取xml结点ref属性根据id注入,也会扫描这些注解,根据类型或id注入,id就是对象名),将对象注入值。

  • 控制反转:

在没有引入IOC容器之前,对象A依赖对象B,需要在A中new一个B对象,控制权都是在A对象。

引入IOC之后,对象A与对象B之间失去了直接联系,A对象和B对象都放入IOC容器中,A和B都依赖IOC容器。如果对象A需要B对象时候,IOC会主动创建一个对象B,然后注入到A中。

通过前后对比,对象A依赖对象B由主动行为变为了被动行为。全部对象控制权全部上缴给IOC容器中,所以,IOC容器成了整个系统的关键核心,把系统中所有对象粘合在一起发挥作用。

  • 依赖注入:

用来实现控制反转,获得依赖对象的过程被反转了,依赖注入是实现IOC的方法,在IOC容器运行期间,动态地将某种依赖关系注入到对象中。

例如我们通常在 Service 层 注入 它所依赖的 Dao 层的实例;在 Controller层注入 Service层的实例。

5.BeanFactory和ApplicationContext有什么区别?

都是Spring中的Bean容器。

ApplicationContext是BeanFactory的子接口。

ApplicationContext还有一些获取环境变量的功能、支持国际化、时间发布、资源解析器

  • ApplicationContext提供了更完整的功能:

继承了MessageSource,因此支持国际化

统一的资源文件访问方式

提供在监听器中注册Bean的事件

同时加载多个配置文件

载入多个上下文,是的每一个上下文都专注于一个特定的层次,比如应用的web层

  • 区别:

BeanFactory采用延迟加载的形式来注入Bean的,而是使用到某个bean(调用getBean()),才对该Bean进行加载实例化。程序在启动时不能发现存在的一些配置问题,只有在运行期才能发现。

ApplicationContext在容器启动时,一次性创建了所有的Bean。在容器启动时,我们就可以发现Spring中存在的配置错误。

相对于BeanFactory,ApplicationContext唯一的不足就是占用内存空间。当应用程序配置Bean较多时,程序启动较慢,但是运行时就快了。

BeanFactory通常以编程的方式被创建(代码中被创建),ApplicationContext还能以声明的方式创建,如使用ContextLoader去创建ApplicationContext。

BeanFactory和ApplicationContext都支持后置处理器,但是两者有区别,BeanFactory需要手动注册,ApplicationContext自动注册即可。

6.描述一下Spring Bean的生命周期?

UserService类–>推断构造方法–>对象–>依赖注入–>初始化前–>初始化–>初始化后(AOP)–>代理对象–>放入map(这个map叫做单例池)–>bean对象

1.解析类得到Bean定义(扫描路径,找到里面的类解析类创建bean定义)

2.如果有多个构造方法,则要推断构造方法

3.确定好构造方法后,进行实例化得到一个对象

4.对Bean对象中的属性通过@Autowired注解进行依赖注入

5.回调Aware方法,比如BeanNameAware、BeanFactoryAware接口

6.调用BeanPostPorcessor的初始化前的方法(后置处理器的前处理)

7.实现InitializingBean接口,调用初始化方法Init

8.调用BeanPostProcessor的初始化后的方法,这里进行AOP动态代理创建

9.如果当前创建的Bean是一个单例的,则会把bean放入单例池

10.使用bean(程序运行期)

11.Spring容器关闭时调用DisposableBean中的destory()方法

7.解释下Spring支持的几种bean的作用域?

singleton:默认,单例模式,每个容器中只有一个bean的实例(单例相对于容器来说),单例的模式由BeanFactory自身来维护。生命周期与IOC容器一致。(不是应用中只有一个实例)

prototype:每次getBean()都会获得一个新的对象

request:bean被定义为每个HTTP请求中创建一个单例对象,请求结束实例会回收

session:一个会话有多次请求响应,每一个session中都有一个bean实例,在session过期后,bean会随之失效。

application:bean被定义为ServletContext,在Servlet容器中复用一个单例对象。(可以跨SpringIOC容器使用,一个程序中有多个容器,Servlet上下文只有一个)

websocket:bean被定义在websocket生命周期中复用一个单例对象。

global session:全局会话内有效

8.Spring框架中的单例Bean是线程安全的吗?

单例模式在Spring容器中,只有一个Bean,不管有多少个线程访问都有一个bean,也就是说这个bean是共享的资源。

在Spring框架中,Bean不是线程安全的。

Spring容器中,Bean单例模式并没有对多线程进行线程安全的处理,如果bean是一个有状态的,比如service中存在一个count计数,count存的数据意味着有状态的。如果service依赖了dao或者依赖了别的service没有存储数据就是没状态的。有状态就是有数据保存,无状态就是不保存数据。controller、service、dao层本身并不是线程安全的,若要存储共享数据需要自己加锁。

可以使用ThreadLocal解决

9.Spring框架中都用到了哪些设计模式?

  • 简单工厂:由一个工厂类根据传入的参数,动态决定应该创建那一个产品类。

Spring中的BeanFactory就是一个简单工厂模式,根据传入一个唯一的标识来获得Bean对象。(BeanFactory可以通过getBean方法获得bean对象)

  • 单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

Spring中帮我们创建实例时默认都是单例。

  • 适配器模式:

SpringMVC中有一个Handler和Adater,在SpringMVC中通过适配器调用

  • 装饰器模式:动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。

Spring所有类名中含有wrapper和Decorator中都使用了装饰器模式

  • 动态代理:

AOP

  • 观察者模式:

Spring监听器中使用观察者模式

  • 策略模式:

Spring框架资源访问Resource接口,针对不同类型文件采用不同的Resource进行访问

10.Spring事务的实现方式和原理以及隔离级别?

事务的实现方式:编程式(begin一个事务rollback等,程序员手动写的,直接调用API)、声明式(使用注解@Transaction)

事务这个概念是数据库层面的,Spring只是基于数据库中的事务进行了扩展

在一个方法上加了@Transactional注解后,Spring会基于这个类生成一个代理对象,会将这个代理对象作为bean,放到IOC容器中。在使用代理对象的方法时,如果这个方法上存在@Transactional注解,那么代理逻辑会先把事务的自动提交设置为false,再去执行原本的业务逻辑,若没有异常,那么代理逻辑就会把事务提交,如果出现异常,那么事务回滚。

针对异常回滚事务可以配置,可以利用@Transactional注解中的属性配置,默认情况下RuntimeException和Error事务回滚

Spring事务隔离级别就是数据库的隔离级别:外加一个默认级别(越往下隔离级别越严,效率越来越低)

  • read uncommitted(未提交读)
  • read committed(提交读、不可重复读)——Oracle默认隔离级别
  • repeatable read(可重复度)——MySQL默认隔离级别
  • serializable(可串行化)

若数据库隔离级别是rc,Spring隔离级别为rr,那么最终隔离级别为rr,如果Spring设置的隔离级别数据库不支持,效果取决于数据库。(以Spring设置的隔离级别为准)

11.Spring事务传播机制?

  • 多个事务方法相互调用时,事务如何在这些方法间传播:

方法A是一个事务方法,A执行过程中调用方法B,那么方法B有无事务以及方法B对事务的要求不同都会对方法A的事务具体执行造成影响。A调用B方法,A有事务,B也有事务。

  • 传播机制:

REQUIRED(Spring默认的传播类型):如果A调用B,A没有事务,B就新建一个事务,如果A有事务那么B就加入A事务

REQUIRES_NEW:如果A有事务,B把A事务挂起,B自己处理自己的事务,A自己处理自己的事务

12.Spring事务什么时候失效?

Spring事务原理是AOP

Spring事务一般使用@Transaction,会帮助我们生成一个代理对象

(1)发生自调用,使用this调用,需要使用@Autowired调用

(2)方法不是public,@Transaction一定用在public上面

(3)数据库不支持事务,MySQL中的MyISAM引擎不支持事务

(4)没有被Spring管理,对象本身没有放在IOC容器中

(5)发生异常,事务不会回滚

13、SpringBoot、SpringMVC、Spring有什么区别?

Spring是一个IOC容器,用来管理Bean,使用依赖注入实现控制反转,使程序降低耦合,很方便整合各种框架,提供了AOP机制可以弥补面向对象代码重复问题,可以将一些日志、异常等封装成切面

SpringMVC是Spring对Web框架的一个解决方案,提供了一个前端控制器Servlet,用来接收请求,定义了一套路由策略,及适配器执行handle,将处理器结果使用视图技术生成视图展现给前段

SpringBoot是Spring提供的一个快速开发工具包,让程序员更方便、快速开发Spring+SpringMVC应用,简化了配置(约定了默认配置,约定大于配置),整合了一系列starter机制引用redis等技术

14、SpringMVC工作流程

(1)用户发送请求至前端控制器DispatcherServlet

(2)DispatcherServlet收到请求调用HandlerMapping处理器映射器,用来维护url到handler的映射关系(处理请求的方法),根据url找到handler

(3)处理器映射器HandlerMapping找到了具体的处理器(根据xml配置),找到handler返回给DispatcherServlet

(4)DispatcherServlet拿到处理器后,调用HandlerAdapter处理器适配器(SpringMVC中有很多种类的handler)

(5)根据适配器HandlerAdapter根据support()方法调用具体的处理器(Controller,也叫后端控制器)

(6)controller执行完返回一个ModelAndView

(7)HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet

(8)DispatcherServlet将ModelAndView传给ViewReslover视图解析器

(9)ViewReslover解析后返回具体的View

(10)DispatcherServlet根据View进行视图渲染

(11)DispatcherServlet响应给前端用户

在这里插入图片描述

15、SpringMVC的主要组件

Handler:处理器,主要处理业务逻辑,@RequestMapping标注的方法都可以看成一个Handler处理器

1.HandlerMapping:处理器映射器,维护url和handler的映射<url,handler>

2.HandlerAdapter:针对不同类型的处理器,都有不同的适配器,拿到handler之后调用HandlerAdapter的适配器方法,support方法判断是哪种处理器

16、SpringBoot自动配置原理

在启动Springboot时,只需要写一个start类,在类上面用@SpringbootApplication注解

@SpringBootConfiguration+@EnableAutoConfiguration+@ComponentScan

@EnableAutoConfiguration自动装配,又分成2个分支,一个是@AutoConfigurationPackage,通过@Import导入一个Registrar注册扫描路径到全局变量,另一个是自动装配@Import导入一个AutoConfigurationImportSelector,里面有一个方法selectImports返回一个字符串数组,字符串数组放的是一个类的全路径会通过反射的方式加载到IOC容器中。

在这里插入图片描述

17、如何理解SpringBoot中的Starter

使用Spring+SpringMVC时,需要引用MyBatis框架,需要到xml中定义MyBatis中需要的bean

如果使用SpringBoot,MyBatis自己定义一个starter的jar包,写一个@Configuration配置类,bean都在配置类中,starter只需要配置类的全路径放到下面,SpringBoot会按照约定扫描加载该配置类,只需要将依赖引入pom文件中即可,进行属性配置

18、SpringMVC中如何实现重定向和转发?

在这里插入图片描述

19、SSM-Spring依赖注入有哪几种方式?

set注入、构造器注入、静态工厂、实例工厂4种注入形式

通过注解和xml形式@Autowired

20、ssm-mybatis当实体类中的属性名和表中的字段名不一样 怎么办?

在这里插入图片描述

21.Spring中5个常用注解

[1]. @Component 基本注解,标识一个受Spring管理的组件

[2] @Controller](mailto:.@Controller) 标识为一个表示层的组件

[3]. @Service 标识为一个业务层的组件

[4]. @Repository 标识为一个持久层的组件

[5]. @Autowired 自动装配

[6]. @Qualifier(“”) 具体指定要装配的组件的id值

[7]. @RequestMapping() 完成请求映射

[8]. @PathVariable 映射请求URL中占位符到请求处理方法的形参

22.三层架构和MVC模式

三层架构就是为了符合“高内聚,低耦合”的思想,把各个功能模块划分为表示层、业务逻辑层、数据访问层

MVC是模型层、视图层、控制层

M:业务逻辑与数据交互

V:负责显示数据和提交数据

C:获取请求和控制转发

23.Springboot如何实现热部署?

(1)添加Springboot-devtools依赖

(2)在yml文件中配置加载的路径

(3)网页的热部署需要在setting中的compiler中勾选auto

(4)还有Registry中的running勾选

24.@Bean和@Component的区别?

@Component注解表名一个类会作为组件类,告知Spring要为这个类创建bean

@Bean注解会告诉Spring这个方法会返回一个对象,这个对象要注册为Spring应用上下文的bean,通常方法体中会保留bean实例的一些逻辑

25.常用的日志框架有哪些?

log4j

logback性能优于log4j

六、MyBatis

1、MyBatis的优缺点

优点:

SQL写在xml中,解除了与程序代码的耦合

减少了大量冗余代码

使用JDBC连接数据库,支持多种数据库

很好与Spring集成

缺点:

SQL语句的编写工作量较大,字段多,关联表多

SQL语句依赖于数据库,不能随意更改数据库

2、#{}和${}的区别是什么?

#{}是预编译,是占位符,

${}是拼接符

${}在DBMS中替换成变量值

#{}对应的变量替换成问号,使用PreparedStatement,提高系统安全性,防止SQL注入——自动变成单引号

3.MyBatis的结果集映射有几种?

自动映射 ,通过resultType来指定要映射的类型即可。

自定义映射 通过resultMap来完成具体的映射规则,指定将结果集中的哪个列映射到对象的哪个属性。

4.为什么说Mybatis是一个半自动化的ORM框架?与全自动的区别在哪里?

Hibernate是一个全自动化的ORM框架,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以他是全自动化的。而MyBatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以称为半自动化OR映射工具。

ORM是对象关系映射,是通过使用描述对象和数据库之间映射的元数据,将面向对象程序中的对象自动持久化到关系数据库中。

常见的ORM框架有:Hibernate、MyBatis

但是Hibernate的灵活性不够用

5.MyBatis和Hibernate的对比?

开发速度对比:

Hibernate要比MyBatis难一些,一个项目中用到的复杂查询几乎没有,就是简单的增删改查,这样选择Hibernate效率更快,因为基本的sql语句已经被封装好了,节省大量时间。但是对于大型项目,语句比较复杂,涉及大量关联操作,批量操作,使用MyBatis会更好,但是MyBatis的代码量会更高一些。

开发工作量对比:

MyBatis需要手动编写SQL语句,以及ResultMap。而Hibernate有更好的关联映射

SQL优化:

MyBatis优势更大,因为sql是我们自己写的

对象管理:

Hibernate提供对象状态管理

缓存机制对比:

都可以使用自己的缓存或者第三方的缓存

Hibernate对查询对象有良好的管理机制,用户无需关心SQL,所以如果出现脏数据会自动报错,MyBatis则不会

Hibernate功能更加强大,数据库无关性更好

七、计算机网络

1.网络通信三要素

IP:定义网络上的设备

端口:计算机应用程序

协议:连接和通信数据的规则

2.网络通信协议模型

应用层

传输层

网络层

数据链路层+物理层

TCP三次握手——进行大量传输——效率低

UDP面向无连接、不可靠传输——速度快,每次64KB

  • 4
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值