面试题
面试题
- 面试题
- 面试题 2.13~ 2.16日
- 面试题 2.20~ 2.24日
- 1.线程有哪些状态?
- 2.sleep()和wait()有什么区别?
- 3.在java程序中怎么保证多线程的运行安全?
- 4.HashMap和Hashtable有什么区别?
- 5.说一下HashMap的实现原理?
- 6. 说一下HashSet的实现原理?
- 7.ArrayList和LinkedList的区别是什么?
- 8.ArrayList和Vector的区别是什么?
- 9.Array和ArrayList有何区别?
- 10.迭代器Iterator是什么?
- 11. Iterator怎么使用?有什么特点?
- 12.Iterator和ListIterator有什么区别?
- 13.并行和并发有什么区别?
- 14.线程和进程的区别?
- 15.创建线程有哪几种方式?
- 面试题 2.27~ 3.2日
- 面试题 3.6~ 3.10日
- 1.怎么防止死锁?
- 2.throw和throws的区别?
- 3.final、finally、finalize有什么区别?
- 4.1.try-catch-finally中哪个部分可以省略?
- 5.try-catch-finally中,如果catch中return了,finally还会执行吗?
- 6.数据库的三范式是什么?
- 7.说一下ACID是什么?
- 8.char和varchar的区别是什么?
- 9.float和double的区别是什么?
- 10.mysql的内连接、左连接、右连接有什么区别?
- 11.mysql索引是怎么实现的?
- 12.说一下数据库的事务隔离?
- 13.说一下乐观锁和悲观锁?
- 14.如何做mysql的性能优化?
- 15.get和post请求有哪些区别?
- 面试题 3.13 ~ 3.17日
- 1.session和cookie的区别?
- 2.session和cookie联系?
- 3.servlet的生命周期?
- 4.什么是web service?
- 5.jsp和servlet的区别、共同点、各自应用的范围?
- 6.forward 和 redirect 的区别?
- 7.request.getAttribute()和request.getParameter()有何区别?
- 8.jsp静态包含和动态包含的区别?
- 9.MVC的各个部分都有哪些技术来实现?如何实现?
- 10.jsp有哪些内置对象?作用分别是什么?
- 11.Http请求的get和post方法的区别。
- 12.tomcat容器是如何创建servlet类实例?用到了什么原理?
- 13.JDBC访问数据库的基本步骤是什么?
- 14.为什么要使用PreparedStatement?
- 15.数据库连接池的原理。为什么要使用连接池?
- 面试题 3.20 ~ 3.24日
- 面试题 3.27 ~ 3.31日
- 面试题 4.3~ 4.7日
- 1.解释Spring支持的几种bean的作用域?
- 2.在Spring中如何注入一个java集合?
- 3.什么是Springbean?
- 4.什么是spring自动装配?
- 5.自动装配有哪些方式?
- 6.自动装配有什么局限?
- 7.Spring的重要注解?
- 8.@Component,@Controller,@Repository,@Service有何区别?
- 9.列举spring支持的事务管理类型?
- 10.Spring框架的事物管理有哪些优点?
- 11.SpringAOP(面向切面)编程的原理?
- 12.SpringMVC框架有什么用?
- 13.Mybatis中#{}和${}的区别是什么?
- 14.Spring中@Autowire与@Resource的区别?
- 15.什么是控制反转(IOC),什么是依赖注入(DI)?
- 面试题 4.10~ 4.14日
- 面试题 4.17~ 4.21日
面试题 2.13~ 2.16日
1.JDK 和 JRE 有什么区别?
- JDK:Java Development Kit 的简称,java 开发工具包,提供了 java 的开发环境和运行环境。
- JRE:Java Runtime Environment 的简称,java 运行环境,为 java 的运行提供了所需环境。
具体来说 JDK 其实包含了 JRE,同时还包含了编译 java 源码的编译器 javac,还包含了很多 java 程序调试和分析的工具。简单来说:如果你需要运行 java 程序,只需安装 JRE 就可以了,如果你需要编写 java 程序,需要安装
JDK。
2.Java的基本类型
四类八种:
- 整数型 byte short int long
- 浮点型 float double
- 字符型 char
- 布尔型 boolean
包装类都有哪些?
- int == Integer
- float = Float
- char = Character
- byte = Byte
- double = Double
- boolean = Boolean
- short = Short
- long = Long
3.== 和 equals 的区别是什么?
== 对于基本类型来说是值比较,对于引用类型来说是比较的是引用;而 equals 默认情况下是引用比较,只是很多类重新了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等
4.final 在 java 中有什么作用?
-
final 修饰的类叫最终类,该类不能被继承。
-
final 修饰的方法不能被重写。
-
final 修饰的变量叫常量,常量必须初始化,初始化之后值就不能被修改。
5.java 中操作字符串都有哪些类?它们之间有什么区别?
操作字符串的类有:String、StringBuffer、StringBuilder。String 和 StringBuffer、StringBuilder 的区别在于 String 声明的是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象,而 StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String。
StringBuffer 和 StringBuilder 最大的区别在于,StringBuffer 是线程安全的,而 StringBuilder 是非线程安全的,但 StringBuilder 的性能却高于 StringBuffer,所以在单线程环境下推荐使用 StringBuilder,多线程环境下推荐使用 StringBuffer。
6.接口和抽象类有什么区别?
- 实现:抽象类的子类使用 extends 来继承;接口必须使用 implements 来实现接口。
- 构造函数:抽象类可以有构造函数;接口不能有。
- main 方法:抽象类可以有 main 方法,并且我们能运行它;接口不能有 main 方法。
- 实现数量:类可以实现很多个接口;但是只能继承一个抽象类。
- 访问修饰符:接口中的方法默认使用 public 修饰;抽象类中的方法可以是任意访问修饰符
7.String和 String Buffer 区别
- String:是对象不是原始类型.为不可变对象,一旦被创建,就不能修改它的值.对于已经存在的String对象的修改都是重新创建一个新的对象,然后把新的值保存进去。String是final类,不能被继承.
- String Buffer:是一个可变对象,当对他进行修改的时候不会像String那样重新建立对象它只能通过构造函数来建立,String Buffer sb = new String Buffer();对象被建立以后,在内存中就会分配内存空间,并初始保存一个null.通过它的append方法向其赋值.
8.重载和重写区别
- 重载:在同一个类中,拥有多个相同名的方法,但是这些方法的参数列表不同(参数个数,参数类型)(即:方法名相同,参数列表不同,返回值类型可以不同!
- 重写:在子父类之间,子类有父类相同名的方法 (即:方法名,参数列表和返回值类型都相同)
9.如何通过反射获得实例对象
- Class.newInstance()
- Constructor.newInstance()
10.java中IO流分为几种?
按功能来分:输入流(input)、输出流(output)。
按类型来分:字节流和字符流。
字节流和字符流的区别是:字节流按8位传输以字节为单位输入输出数据,字符流按16位传输以字符为单位输入输出数据
11.BIO、NIO、AIO有什么区别?
BIO、NIO、AIO是Java中用于处理IO的三种不同的方式,它们之间的区别如下:
-
BIO(Blocking IO):同步阻塞IO,传统的IO模型,也称为传统IO,是一种阻塞的IO方式,即在读取或写入数据时,如果没有数据可读或可写,则线程会一直等待,直到有数据可读或可写。BIO适合于连接数较小的场景,例如单机版的服务器。
-
NIO(New IO):同步非阻塞IO,是一种基于事件驱动的IO方式,也称为事件驱动IO,它可以处理多个连接,且不会阻塞线程。NIO适合于连接数较多的场景,例如高并发的网络服务器。
-
AIO(Asynchronous IO):异步非阻塞IO,是一种基于回调的IO方式,也称为异步IO,它可以处理多个连接,且不会阻塞线程。AIO适合于连接数较多且数据量较大的场景,例如文件传输、视频流传输等。
总结:BIO适合于连接数较小的场景,NIO适合于连接数较多的场景,AIO适合于连接数较多且数据量较大的场景,不同的场景选择不同的IO模型可以更好地发挥系统的性能。
12.静态变量和实例变量的区别
-
静态变量使用static修饰,而实例变量则不用。
-
静态变量不属于任何一个实例,而是属于类,所以在加载类的字 节码文件的时候,就会给静态变量分配空间,并且仅分配一次。
-
实例变量只有在实例化类的对象的时候才会分配空间,并且没实例化 一个对象的时候分配一次
面试题 2.20~ 2.24日
1.线程有哪些状态?
线程通常都有五种状态,创建、就绪、运行、阻塞和死亡。
-
创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态。
-
就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。
在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。
-
运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。
-
阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend,wait等方法都可以导致线程阻塞。
-
死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪
2.sleep()和wait()有什么区别?
- sleep():方法是线程类(Thread)的静态方法,让调用线程进入睡眠状态,让出执行机会给其他线程,等到休眠时间结束后,线程进入就绪状态和其他线程一起竞争cpu的执行时间。因为sleep()是static静态的方法,他不能改变对象的机锁,当一个synchronized块中调用了sleep()方法,线程虽然进入休眠,但是对象的机锁没有被释放,其他线程依然无法访问这个对象。
- wait():wait()是Object类的方法,当一个线程执行到wait方法时,它就进入到一个和该对象相关的等待池,同时释放对象的机锁,使得其他线程能够访问,可以通过notify,notifyAll方法来唤醒等待的线程
3.在java程序中怎么保证多线程的运行安全?
线程安全在三个方面体现:
- 原子性:提供互斥访问,同一时刻只能有一个线程对数据进行操作,(atomic,synchronized);
- 可见性:一个线程对主内存的修改可以及时地被其他线程看到,(synchronized,volatile);
- 有序性:一个线程观察其他线程中的指令执行顺序,由于指令重排序,该观察结果一般杂乱无序,(happens-before原则)。
4.HashMap和Hashtable有什么区别?
- hashMap去掉了HashTable的contains方法,但是加上了containsValue()和containsKey()方法。
- hashTable同步的,而HashMap是非同步的,效率上逼hashTable要高。
- hashMap允许空键值,而hashTable不允许
5.说一下HashMap的实现原理?
HashMap是一种基于哈希表实现的键值对存储容器,每个键值对都有一个对应的哈希值,该哈希值用于决定该键值对应该存储在HashMap的哪个位置上。HashMap内部是由数组和链表(或红黑树)组成的,数组用于存储桶,每个桶中存储着一个链表或红黑树。
在JDK1.8中,当链表长度超过8时,HashMap会将链表转换为红黑树,以提高查询效率。同时,当元素数量达到一定阈值时,HashMap会自动进行扩容,以保证哈希表的负载因子不超过0.75,从而避免哈希冲突过多导致的性能下降。
需要注意的是,在并发环境下,HashMap是非线程安全的,因此需要注意并发安全问题,可以使用ConcurrentHashMap来替代HashMap。
6. 说一下HashSet的实现原理?
- HashSet底层由HashMap实现
- HashSet的值存放于HashMap的key上
- HashMap的value统一为PRESENT
7.ArrayList和LinkedList的区别是什么?
区别是ArrrayList底层的数据结构是数组,支持随机访问,而LinkedList的底层数据结构是双向循环链表,不支持随机访问。
使用下标访问一个元素,ArrayList的时间复杂度是O(1),而LinkedList是O(n)。
8.ArrayList和Vector的区别是什么?
- Vector是同步的,而ArrayList不是。然而,如果你寻求在迭代的时候对列表进行改变,你应该使用CopyOnWriteArrayList。
- ArrayList比Vector快,它因为有同步,不会过载。
- ArrayList更加通用,因为我们可以使用Collections工具类轻易地获取同步列表和只读列表。
9.Array和ArrayList有何区别?
- Array可以容纳基本类型和对象,而ArrayList只能容纳对象。
- Array是指定大小的,而ArrayList大小是固定的。
- Array没有提供ArrayList那么多功能,比如addAll、removeAll和iterator等。
10.迭代器Iterator是什么?
迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需
要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。
11. Iterator怎么使用?有什么特点?
在Java中,Iterator是用于遍历集合类(如List、Set、Map等)中元素的接口。Iterator提供了一种统一的遍历机制,无需关心集合类的具体实现方式,只需要通过Iterator将元素逐个取出即可。
使用Iterator的步骤如下:
-
通过集合类的iterator()方法获取Iterator对象。
-
使用hasNext()方法判断集合中是否还有元素未被遍历。如果有,返回true;否则返回false。
-
使用next()方法取出集合中的下一个元素。
-
使用remove()方法删除集合中的当前元素(可选操作)。
Iterator的特点如下:
-
Iterator提供了一种统一的遍历机制,无需关心集合类的具体实现方式。
-
Iterator只能单向遍历集合中的元素,不能逆向遍历。
-
Iterator的remove()方法可以删除集合中的元素,但是只能在next()方法之后调用,否则会抛出IllegalStateException异常。
-
在使用Iterator遍历集合时,如果集合发生了结构性变化(如添加或删除元素),则会抛出ConcurrentModificationException异常,因此在遍历过程中不应该直接修改集合中的元素,应该使用Iterator的remove()方法来删除元素。
总之,Iterator提供了一种统一的遍历机制,可以方便地遍历集合中的元素,但是需要注意遍历过程中不要直接修改集合中的元素,应该使用Iterator的remove()方法来删除元素。
12.Iterator和ListIterator有什么区别?
-
Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。
-
Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。
-
ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。
13.并行和并发有什么区别?
- 并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔发生。
- 并行是在不同实体上的多个事件,并发是在同一实体上的多个事件。
- 在一台处理器上“同时”处理多个任务,在多台处理器上同时处理多个任务。如hadoop分布式集群。
所以并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理性能。
14.线程和进程的区别?
简而言之,进程是程序运行和资源分配的基本单位,一个程序至少有一个进程,一个进程至少有一个线程。
进程在执行过程中拥有独立的内存单元,而多个线程共享内存资源,减少切换次数,从而效率更高。
线程是进程的一个实体,是cpu调度和分派的基本单位,是比程序更小的能独立运行的基本单位。
同一进程中的多个线程之间可以并发执行。
15.创建线程有哪几种方式?
创建线程的方式有以下几种:
-
继承Thread类并重写run()方法。
-
实现Runnable接口并重写run()方法。
-
使用Callable和Future接口创建线程。
-
使用线程池创建线程。
-
使用Java8的Lambda表达式创建线程。
-
使用Executor框架创建线程。
其中,继承Thread类和实现Runnable接口是最常见的两种方式。其他方式都是在这两种方式的基础上进行了封装和简化。
面试题 2.27~ 3.2日
1.说一下runnable和callable有什么区别?
- Runnable接口中的run()方法的返回值是void,它做的事情只是纯粹地去执行run()方法中的代码而已;
- Callable接口中的call()方法是有返回值的,是一个泛型,和Future、FutureTask配合可以用来获取异步执行的结果。
2.notify()和notifyAll()有什么区别?
1.如果线程调用了对象的wait()方法,那么线程便会处于该对象的等待池中,等待池中的
线程不会去竞争该对象的锁。
2.当有线程调用了对象的notifyAll()方法(唤醒所有wait线程)或notify()方法(只随机
唤醒一个wait线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去
竞争该对象锁。也就是说,调用了notify后只要一个线程会由等待池进入锁池,而
3.notifyAll会将该对象等待池内的所有线程移动到锁池中,等待锁竞争。
优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在
锁池中,唯有线程再次调用wait()方法,它才会重新回到等待池中。而竞争到对象锁的
线程则继续往下执行,直到执行完了synchronized代码块,它会释放掉该对象锁,这
时锁池中的线程会继续竞争该对象锁。
3.线程的run()和start()有什么区别?
每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,方法run()称为
线程体。通过调用Thread类的start()方法来启动一个线程。
1.start()方法来启动一个线程,真正实现了多线程运行。这时无需等待run方法体代码执
行完毕,可以直接继续执行下面的代码;这时此线程是处于就绪状态,并没有运行。
然后通过此Thread类调用方法run()来完成其运行状态,这里方法run()称为线程体,
它包含了要执行的这个线程的内容,Run方法运行结束,此线程终止。然后CPU再调
度其它线程。
2.run()方法是在本线程里的,只是线程里的一个函数,而不是多线程的。如果直接调用
run(),其实就相当于是调用了一个普通函数而已,直接待用run()方法必须等待run()方法
执行完毕才能执行下面的代码,所以执行路径还是只有一条,根本就没有线程的特征,
所以在多线程执行时要使用start()方法而不是run()方法。
4.创建线程池有哪几种方式?
1.newFixedThreadPool(intnThreads)
创建一个固定长度的线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数
量,这时线程规模将不再变化,当线程发生未预期的错误而结束时,线程池会补充一个新的
线程。
2.newCachedThreadPool()
创建一个可缓存的线程池,如果线程池的规模超过了处理需求,将自动回收空闲线程,而当
需求增加时,则可以自动添加新线程,线程池的规模不存在任何限制。
3.newSingleThreadExecutor()
这是一个单线程的Executor,它创建单个工作线程来执行任务,如果这个线程异常结束,会
创建一个新的来替代它;它的特点是能确保依照任务在队列中的顺序来串行执行。
4.newScheduledThreadPool(intcorePoolSize)
创建了一个固定长度的线程池,而且以延迟或定时的方式来执行任务,类似于Timer。
5.线程池都有哪些状态?
线程池有5种状态:
Running
、ShutDown
、Stop
、Tidying
、 Terminated
6.线程池中submit()和execute()方法有什么区别?
- 接收的参数不一样
- submit有返回值,而execute没有
- submit方便Exception处理
7.什么是死锁?
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成
的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系
统产生了死锁,这些永远在互相等待的进程称为死锁进程。是操作系统层面的一个错误,是
进程死锁的简称,最早在1965年由Dijkstra在研究银行家算法时提出的,它是计算机操
作系统乃至整个并发程序设计领域最难处理的问题之一。
8.ThreadLocal是什么?有哪些使用场景?
线程局部变量是局限于线程内部的变量,属于线程自身所有,不在多个线程间共享。Java
提供ThreadLocal类来支持线程局部变量,是一种实现线程安全的方式。但是在管理环境下
(如web服务器)使用线程局部变量的时候要特别小心,在这种情况下,工作线程的生命
周期比任何应用变量的生命周期都要长。任何线程局部变量一旦在工作完成后没有释放,
Java应用就存在内存泄露的风险。
9.forward和redirect的区别?
forward(转发)是指当一个请求到达服务器时,服务器将该请求传递给另一个资源进行处理,而客户端并不知道这个过程。在转发中,请求的 URL 不会发生改变。在 Java Servlet 中,可以使用 RequestDispatcher 接口的 forward() 方法来实现转发。
Redirect(重定向)是指当一个请求到达服务器时,服务器将客户端重定向到另一个 URL。在重定向中,客户端会发起一个新的请求,请求的 URL 会发生改变。在 Java Servlet 中,可以使用 HttpServletResponse 接口的 sendRedirect() 方法来实现重定向。
下面是两种方式的一些区别:
- URL 是否发生变化:Forward 时 URL 不会发生变化,而 Redirect 时 URL 会发生变化。
- 请求方式:Forward 是在服务器内部转发请求,客户端只发出一次请求,而 Redirect 是客户端发出两次请求。
- 数据传递:在 Forward 中,数据可以在转发前后共享,而在 Redirect 中,由于两次请求的不同,数据无法在请求之间共享。
- 对搜索引擎的影响:由于 Forward 不会改变 URL,搜索引擎会将其视为同一页面,而 Redirect 会被视为两个不同的页面。
10.synchronized和Lock有什么区别?
总的来说,synchronized和Lock都是Java中实现并发同步的方式,它们的主要区别如下:
-
synchronized是Java内置的关键字,而Lock是一个Java类。
-
synchronized是可重入锁,同一个线程可以多次获得同一把锁,而Lock也是可重入锁。
-
synchronized是非公平锁,线程的获取锁的顺序是不可控的,而Lock可以是公平锁或非公平锁。
-
synchronized在获取锁时,如果锁已经被其他线程占用,则当前线程会一直阻塞等待,而Lock可以通过tryLock()方法尝试获取锁,可以设置等待时间,如果在指定时间内没有获取到锁,则返回false。
-
synchronized在执行完同步代码块后会自动释放锁,而Lock需要手动释放锁。
-
synchronized只能实现非常简单的线程同步,而Lock可以实现更加复杂的同步方式,比如可以实现公平锁、读写锁等。
在使用时,synchronized比较简单易用,而Lock需要手动控制加锁和解锁,因此更加灵活,可以实现更多的同步方式。但是需要注意的是,在使用Lock时需要注意手动释放锁,否则容易导致死锁等问题。
11.动态代理:
当想要给实现了某个接口的类中的方法,加一些额外的处理。比如说加日志,加事务等。
可以给这个类创建一个代理,故名思议就是创建一个新的类,这个类不仅包含原来类方法的
功能,而且还在原来的基础上添加了额外处理的新类。这个代理类并不是定义好的,是动态
生成的。具有解耦意义,灵活,扩展性强。
动态代理的应用:
- Spring的AOP
- 加事务
- 加权限
- 加日志
12.什么是 java 序列化?什么情况下需要序列化?
Java序列化是将Java对象转换为字节序列的过程,以便将其存储在文件中或通过网络传输。Java
序列化可以保留对象的状态信息,即包括对象的成员变量和方法。反序列化是将字节序列转换回
Java对象的过程,以便在需要时重新创建对象。
Java序列化是一种非常常用的技术,特别是在网络编程和持久化数据时。下面是一些常见的情况
下需要使用Java序列化的场景:
- 分布式应用:Java序列化可以用于在不同的机器之间传递对象,特别是在远程调用和分布式应用中。
- 持久化数据:Java序列化可以将对象转换为字节序列,以便将其保存到磁盘上,从而实现数据的持久化存储。
- 缓存数据:Java序列化可以将对象序列化后保存在缓存中,从而提高程序的性能。
- 多线程应用:Java序列化可以用于线程之间的数据共享,从而避免多线程并发修改数据的问题。
需要注意的是,Java序列化并不适用于所有场景。例如,如果对象的结构经常变化,或者需要在
不同的编程语言之间进行交互,则可能需要使用其他技术,比如JSON、XML等。此外,Java序列
化也可能存在安全问题,因为序列化后的字节序列可以被反序列化为原始对象,这可能会被攻击
者用于注入恶意代码或篡改数据等行为。
13.怎么实现动态代理?
在Java中,实现动态代理主要有两种方式:基于接口的动态代理和基于类的动态代理。
- 基于接口的动态代理:基于接口的动态代理是Java官方提供的一种动态代理机制。主要通过Java反射机制实现,需要实现一个InvocationHandler接口,重写invoke()方法,然后通过Proxy类的newProxyInstance()方法创建代理对象。
- 基于类的动态代理:基于类的动态代理主要通过字节码生成技术实现。一般使用第三方库,比如CGLIB和ByteBuddy等。这种方式可以代理非接口的类,并且不需要目标类实现任何接口。
14.如何实现对象克隆?
有两种方式:
- 实现Cloneable接口并重写Object类中的clone()方法;
- 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆
15.深拷贝和浅拷贝区别是什么?
- 浅拷贝只是复制了对象的引用地址,两个对象指向同一个内存地址,所以修改其中任意的值,另一个值都会随之变化,这就是浅拷贝(例:assign())
- 深拷贝是将对象及值复制过来,两个对象修改其中任意的值另一个值不会改变,这就是深拷贝(例:JSON.parse()和JSON.stringify(),但是此方法无法复制函数类型)
面试题 3.6~ 3.10日
1.怎么防止死锁?
死锁的四个必要条件:
- 互斥条件:进程对所分配到的资源不允许其他进程进行访问,若其他进程访问该资源,只能等待,直至占有该资源的进程使用完成后释放该资源
- 请求和保持条件:进程获得一定的资源之后,又对其他资源发出请求,但是该资源可能被其他进程占有,此事请求阻塞,但又对自己获得的资源保持不放
- 不可剥夺条件:是指进程已获得的资源,在未完成使用之前,不可被剥夺,只能在使用完后自己释放
- 环路等待条件:是指进程发生死锁后,若干进程之间形成一种头尾相接的循环等待资源关系
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和解除死锁。所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止进程在处于等待状态的情况下占用资源。因此,对资源的分配要给予合理的规划。
2.throw和throws的区别?
- throws是用来声明一个方法可能抛出的所有异常信息,throws是将异常声明但是不处理,而是将异常往上传,谁调用我就交给谁处理。
- 而throw则是指抛出的一个具体的异常类型。
3.final、finally、finalize有什么区别?
- final可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、修饰变量表示该变量是一个常量不能被重新赋值。
- finally一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码方法finally代码块中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。
- finalize是一个方法,属于Object类的一个方法,而Object类是所有类的父类,该方法一般由垃圾回收器来调用,当我们调用System的gc()方法的时候,由垃圾回收器调用finalize(),回收垃圾。
4.1.try-catch-finally中哪个部分可以省略?
答:catch可以省略
原因:
更为严格的说法其实是:try只适合处理运行时异常,try+catch适合处理运行时异常+
普通异常。也就是说,如果你只用try去处理普通异常却不加以catch处理,编译是通不过
的,因为编译器硬性规定,普通异常如果选择捕获,则必须用catch显示声明以便进一步处
理。而运行时异常在编译时没有如此规定,所以catch可以省略,你加上catch编译器也觉
得无可厚非。
理论上,编译器看任何代码都不顺眼,都觉得可能有潜在的问题,所以你即使对所有代
码加上try,代码在运行期时也只不过是在正常运行的基础上加一层皮。但是你一旦对一段
代码加上try,就等于显示地承诺编译器,对这段代码可能抛出的异常进行捕获而非向上抛
出处理。如果是普通异常,编译器要求必须用catch捕获以便进一步处理;如果运行时异常,
捕获然后丢弃并且+finally扫尾处理,或者加上catch捕获以便进一步处理。
至于加上finally,则是在不管有没捕获异常,都要进行的“扫尾”处理。
5.try-catch-finally中,如果catch中return了,finally还会执行吗?
答:会执行,在return前执行。
6.数据库的三范式是什么?
- 第一范式:强调的是列的原子性,即数据库表的每一列都是不可分割的原子数据项。
- 第二范式:要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性。
- 第三范式:任何非主属性不依赖于其它非主属性。
7.说一下ACID是什么?
ACID是数据库事务的四个特性,分别是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。
-
原子性(Atomicity):指事务是一个不可分割的操作序列,要么全部执行成功,要么全部执行失败。如果事务执行过程中出现错误,所有已经执行的操作都会被回滚,数据库状态恢复到事务执行前的状态。
-
一致性(Consistency):指事务执行后,数据库从一个一致性状态转换到另一个一致性状态。事务执行前和执行后,数据库都必须处于一致性状态。
-
隔离性(Isolation):指多个事务并发执行时,每个事务都应该与其他事务隔离开来,互不干扰。一个事务的执行不应该受到其他事务的影响,多个事务之间应该是相互独立的。
-
持久性(Durability):指事务提交后,对数据库所做的修改是永久性的,即使系统崩溃也不会丢失。数据库会将事务提交的数据保存到磁盘中,即使数据库发生故障,也能够保证数据的完整性和一致性。
ACID是数据库事务的四个基本特性,可以保证数据的完整性和一致性。在实际应用中,根据具体的业务场景和需求,可以灵活地选择不同的事务隔离级别,以达到更好的性能和数据一致性。
8.char和varchar的区别是什么?
- char(n):固定长度类型,比如订阅char(10),当你输入"abc"三个字符的时候,它们占的空间还是10个字节,其他7个是空字节。
- chat优点:效率高;缺点:占用空间;适用场景:存储密码的md5值,固定长度的,使用char非常合适。
- varchar(n):可变长度,存储的值是每个值占用的字节再加上一个用来记录其长度的字节的长度。
所以,从空间上考虑varcahr比较合适;从效率上考虑char比较合适,二者使用需要权衡。
9.float和double的区别是什么?
- float最多可以存储8位的十进制数,并在内存中占4字节。
- double最可可以存储16位的十进制数,并在内存中占8字节。
10.mysql的内连接、左连接、右连接有什么区别?
内连接关键字:innerjoin;左连接:leftjoin;右连接:rightjoin。
1.内连接是把匹配的关联数据显示出来;
2.左连接是左边的表全部显示出来,
3.右边的表显示出符合条件的数据;
4.右连接正好相反。
11.mysql索引是怎么实现的?
MySQL中的索引是一种基于B+树数据结构实现的数据结构,它可以以较高的效率查找数据。B+树可以降低磁盘I/O的次数,从而提高索引的查询效率,这是B+树相对于其他数据结构的优势之一。
因此,在创建索引时需要选择适当的索引列,并避免创建过多索引,以提高系统性能和可靠性。
12.说一下数据库的事务隔离?
MySQL的事务隔离是在MySQL.ini配置文件里添加的,在文件的最后添加:
transaction-isolation=REPEATABLE-READ
可用的配置值:READ-UNCOMMITTED、READ-COMMITTED、REPEATABLE-READ、SERIALIZABLE。
- READ-UNCOMMITTED:未提交读,最低隔离级别、事务未提交前,就可被其他事务读取(会出现幻读、脏读、不可重复读)。
- READ-COMMITTED:提交读,一个事务提交后才能被其他事务读取到(会造成幻读、不可重复读)。
- REPEATABLE-READ:可重复读,默认级别,保证多次读取同一个数据时,其值都和事务开始时候的内容是一致,禁止读取到别的事务未提交的数据(会造成幻读)。
- SERIALIZABLE:序列化,代价最高最可靠的隔离级别,该隔离级别能防止脏读、不可重复读、幻读。
- 脏读:表示一个事务能够读取另一个事务中还未提交的数据。比如,某个事务尝试插入记录A,此时该事务还未提交,然后另一个事务尝试读取到了记录A。
- 不可重复读:是指在一个事务内,多次读同一数据。
- 幻读:指同一个事务内多次查询返回的结果集不一样。比如同一个事务A第一次查询时候有n条记录,但是第二次同等条件下查询却有n+1条记录,这就好像产生了幻觉。发生幻读的原因也是另外一个事务新增或者删除或者修改了第一个事务结果集里面的数据,同一个记录的数据内容被修改了,所有数据行的记录就变多或者变少了。
13.说一下乐观锁和悲观锁?
- 乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。
- 悲观锁:每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻止,直到这个锁被释放。
数据库的乐观锁需要自己实现,在表里面添加一个version字段,每次修改成功值加1,这样每次修改的时候先对比一下,自己拥有的version和数据库现在的version是否一致,如果不一致就不修改,这样就实现了乐观锁。
14.如何做mysql的性能优化?
- 添加适当的索引(普通索引、主键索引、唯一索引、全文索引);
- 避免使用select*,列出需要查询的字段。
- 选择正确的存储引擎。
- 库表优化,表设计合理化,符合三大范式;
- 分库分表;读写分离等;
- sql语句优化,定位执行效率低,慢sql的语句,通过explain分析低效率的原因;
15.get和post请求有哪些区别?
- GET请求会将参数附加在URL后面,而POST请求会将参数放在请求体中。
- GET请求的参数有长度限制,一般不能超过2KB,而POST请求没有限制。
- GET请求的参数会被保存在浏览器历史中,而POST请求的参数不会被保存。
- GET请求会被浏览器主动缓存,而POST请求不会。
- GET请求的安全性较差,因为参数会暴露在URL中,容易被攻击者窃取或修改,而POST请求的参数放在请求体中,相对较安全。
- GET请求适用于获取数据,POST请求适用于提交数据和进行数据修改操作。
- GET请求可以被浏览器缓存,可以提高页面加载速度,而POST请求不能被缓存。
面试题 3.13 ~ 3.17日
1.session和cookie的区别?
Cookie是存储在浏览器中的,而Session是存储在服务器上的。Cookie可以设置过期时间,
Session在用户关闭浏览器或者Session过期后会被清除。同时,Cookie可以存储在客户端的任**
意数据,而Session通常存储用户的身份验证信息、用户的浏览历史等敏感信息。
2.session和cookie联系?
Cookie和Session之间的联系在于,服务器通常使用Cookie来存储Session ID。当用户与Web应用程序建立会话时,服务器将Session ID存储到Cookie中,并在后续请求中读取该Cookie以获取Session ID。服务器使用该Session ID来检索与该用户相关联的会话数据。因此,Cookie和Session都是用于跟踪用户在Web应用程序中的活动,但Cookie存储在客户端,而Session存储在服务器端。
3.servlet的生命周期?
Servlet是Java Web应用程序的基本构建块之一,它具有自己的生命周期。Servlet生命周期指的是Servlet从创建到销毁的整个过程,包括以下阶段:
- 加载阶段:在Web应用程序启动时,Web容器会加载Servlet类并创建Servlet实例,即调用Servlet的构造函数。这个阶段只会执行一次。
- 初始化阶段:在Servlet被创建后,Web容器会调用其init()方法,完成Servlet的初始化工作。在该方法中,可以进行一些初始化的操作,比如读取配置文件、建立数据库连接等。
- 请求处理阶段:在初始化完成后,Servlet可以接受来自客户端的请求,并处理这些请求。每个请求都将被包装成一个HttpServletRequest对象,Servlet会调用其service()方法处理请求,根据请求的类型(GET、POST等)调用相应的处理方法(doGet()、doPost()等)。
- 销毁阶段:当Web应用程序停止或Servlet容器关闭时,Servlet容器会调用Servlet的destroy()方法,完成Servlet的销毁工作。在该方法中,可以释放资源,如关闭数据库连接、释放文件句柄等。
在Servlet的生命周期中,有些方法是由Servlet容器自动调用的,而有些方法则需要Servlet开发人员手动调用。需要注意的是,每个Servlet实例只会创建一次,但可以处理多个请求。因此,Servlet应该设计成无状态的,不依赖于特定的请求或客户端状态。
4.什么是web service?
Web Service是一种用于在不同的计算机系统之间交换数据的技术。它基于标准化的Web协议,如HTTP、SOAP、XML和WSDL等,用于实现跨平台、跨语言的应用程序集成。通过使用Web Service,现有的应用程序或服务可以被发布为Web服务,并通过标准化的方式被其他应用程序或服务所访问和使用。这种访问和使用可以通过简单的HTTP请求和响应完成,无需考虑底层技术和平台的差异性。Web Service可以实现不同的应用程序和平台之间的互操作,促进了分布式应用程序和服务的整合。
5.jsp和servlet的区别、共同点、各自应用的范围?
JSP是Servlet技术的扩展,本质上就是Servlet的简易方式。JSP编译后是“类servlet”。
Servlet和JSP最主要的不同点在于,Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。
而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件。
JSP侧重于视图,Servlet主要用于控制逻辑。在struts框架中,JSP位于MVC设计模式的视图层,而Servlet位于控制层.
6.forward 和 redirect 的区别?
Forward(转发)是指当一个请求到达服务器时,服务器将该请求传递给另一个资源进行处理,而客户端并不知道这个过程。在转发中,请求的 URL 不会发生改变。在 Java Servlet 中,可以使用 RequestDispatcher 接口的 forward() 方法来实现转发。
Redirect(重定向)是指当一个请求到达服务器时,服务器将客户端重定向到另一个 URL。在重定向中,客户端会发起一个新的请求,请求的 URL 会发生改变。在 Java Servlet 中,可以使用 HttpServletResponse 接口的 sendRedirect() 方法来实现重定向。
下面是两种方式的一些区别:
- URL 是否发生变化:Forward 时 URL 不会发生变化,而 Redirect 时 URL 会发生变化。
- 请求方式:Forward 是在服务器内部转发请求,客户端只发出一次请求,而 Redirect 是客户端发出两次请求。
- 数据传递:在 Forward 中,数据可以在转发前后共享,而在 Redirect 中,由于两次请求的不同,数据无法在请求之间共享。
- 对搜索引擎的影响:由于 Forward 不会改变 URL,搜索引擎会将其视为同一页面,而 Redirect 会被视为两个不同的页面。
7.request.getAttribute()和request.getParameter()有何区别?
- request.getAttribute() 方法是用于获取在服务器端中存储在request对象中的属性值。这些属性值通常是在服务器端的Java代码中设置的,并且可以用于在不同的servlet或JSP页面之间共享数据。例如,一个servlet设置一个属性值,另一个servlet可以通过调用request.getAttribute()方法获取这个属性值。
- request.getParameter() 方法是用于获取客户端通过HTTP请求发送到服务器端的参数值。这些参数通常是通过表单提交、URL参数或AJAX请求等方式发送的。例如,在一个登录表单中,用户名和密码可以通过request.getParameter()方法获取。
- getAttribute是返回对象,getParameter返回字符串
8.jsp静态包含和动态包含的区别?
- 静态包含:使用jsp:include标签将一个JSP页面嵌入到另一个JSP页面中,并在编译时将嵌入的页面的代码合并到主页面中。这意味着在主页面被访问时,被包含的页面已经被执行了。因此,如果被包含的页面中包含有动态内容,它们也会在主页面中被执行。
- 动态包含:使用jsp:include标签将一个JSP页面嵌入到另一个JSP页面中,但在运行时才会执行被嵌入的页面。这意味着被包含的页面中包含的动态内容只有在主页面被访问时才会被执行,而不是在编译时就执行了。
因此,静态包含和动态包含的主要区别在于它们执行嵌入的页面的时间不同。静态包含在编译时执行被包含的页面,而动态包含在运行时才执行被包含的页面。一般来说,如果被包含的页面中包含有动态内容,应该使用动态包含,否则应该使用静态包含。
9.MVC的各个部分都有哪些技术来实现?如何实现?
MVC 是一种常用的软件设计模式,其包含三个核心部分:模型(Model)、视图(View)和控制器(Controller)。下面是它们各自常用的实现技术:
1.模型(Model):模型通常是应用程序的核心数据结构,它负责处理应用程序的业务逻辑和数据存储。常见的实现技术包括:
-
数据库:使用 SQL 数据库或 NoSQL 数据库来存储和管理数据,例如 MySQL、PostgreSQL、MongoDB 等。
-
ORM(对象关系映射):ORM 技术将数据库中的数据映射为对象,使得应用程序可以通过面向对象的方式来处理数据。常见的 ORM 技术包括 Hibernate、Entity Framework 等。
-
RESTful API:使用 RESTful API 来提供数据访问接口,使得客户端可以通过 HTTP 协议来访问和操作数据。
2.视图(View):视图通常是用户界面的展现部分,负责向用户展示数据和收集用户输入。常见的实现技术包括:
-
HTML/CSS/JavaScript:使用前端技术来实现网页界面,例如 HTML 用于定义页面结构,CSS 用于样式设计,JavaScript 用于实现交互功能。
-
模板引擎:使用模板引擎来生成动态 HTML 页面,例如 Handlebars、Thymeleaf 等。
3.控制器(Controller):控制器负责协调模型和视图之间的交互,处理用户请求并调用相应的模型和视图来处理。常见的实现技术包括:
- Servlet/JSP:使用 Servlet 和 JSP 技术来实现 Web 应用程序,其中 Servlet 负责处理请求,JSP 负责生成 HTML 页面。
- Spring MVC:Spring MVC 是一个基于 Servlet 的 MVC 框架,它提供了很多功能来简化开发工作,例如请求处理、数据绑定、异常处理等。
- ASP.NET MVC:ASP.NET MVC 是一个基于 .NET 平台的 MVC 框架,它提供了很多功能来简化开发工作,例如路由、过滤器、视图引擎等。
10.jsp有哪些内置对象?作用分别是什么?
在 JSP 中,有 9 个内置对象(也称为预定义变量或隐含对象),它们是:
- request:表示客户端发出的 HTTP 请求,可以用来获取客户端提交的表单数据或 URL 参数。
- response:表示服务器返回给客户端的 HTTP 响应,可以用来设置响应头、状态码、Cookie 等。
- session:表示客户端与服务器之间的会话,可以用来存储用户登录状态、购物车信息等。
- application:表示整个 Web 应用程序,可以用来共享数据、调用 Servlet 或其他 JSP 程序等。
- out:表示输出流,可以用来向客户端发送文本或 HTML 标签。
- page:表示当前 JSP 页面本身,可以用来获取 JSP 页面的属性和方法。
- pageContext:表示 JSP 页面的上下文,可以用来获取其他内置对象、请求属性、会话属性等。
- exception:表示页面中发生的异常,可以用来处理异常信息。
- config:表示当前 JSP 页面的配置信息,可以用来获取 JSP 配置参数和 Servlet 上下文初始化参数。
这些内置对象在 JSP 中非常有用,它们提供了许多常用的功能和方法,使得 JSP 开发更加方便和高效。
11.Http请求的get和post方法的区别。
- GET方法: GET方法用于从Web服务器获取数据。它通过在URL中添加参数来传递数据,这些参数以问号(?)分隔并用&符号分隔。由于GET请求是通过URL传递数据的,因此它受到URL长度限制的限制,可以传递的数据量比POST方法少。它还可以被缓存,因此多次使用相同的GET请求时,服务器可以直接返回缓存的数据,而无需重新生成它们。
- POST方法: POST方法用于向Web服务器提交数据。它通过HTTP正文传递数据,因此可以传递更多的数据,没有URL长度限制的限制。POST请求可以用于提交表单数据、上传文件和进行数据库操作等。由于POST请求是通过HTTP正文传递数据的,因此它不能被缓存,每次请求都需要重新生成数据。
因此,GET请求适用于需要从服务器获取数据的情况,而POST请求适用于需要向服务器提交数据的情况
12.tomcat容器是如何创建servlet类实例?用到了什么原理?
Tomcat是一个Java Servlet容器,它用于运行Java Web应用程序。当Tomcat启动时,它会加载Web应用程序的相关配置和类,并创建Servlet实例来处理Web请求。
Tomcat通过Java反射机制实现Servlet实例的创建。具体来说,当Tomcat收到一个HTTP请求时,它会根据请求的URL找到对应的Servlet,并创建一个新的Servlet实例来处理该请求。Tomcat使用Java类加载器加载Servlet类,并使用Java反射机制创建Servlet实例。在创建Servlet实例时,Tomcat会调用Servlet类的构造函数,并传递一个ServletConfig对象作为参数,该对象包含了Servlet的初始化参数和上下文信息。
需要注意的是,Tomcat是一个多线程的Web容器,它可以同时处理多个HTTP请求。因此,Tomcat会为每个HTTP请求创建一个新的线程,并在该线程中创建Servlet实例来处理请求。在多线程环境下,Tomcat通过线程池技术来管理Servlet实例,以避免创建过多的实例导致系统资源耗尽。
总之,Tomcat使用Java反射机制创建Servlet实例,通过线程池技术管理Servlet实例,以实现高效的Web请求处理。
13.JDBC访问数据库的基本步骤是什么?
-
加载数据库驱动程序:在使用JDBC之前,需要使用Class.forName()方法加载数据库驱动程序,例如:
Class.forName("com.mysql.jdbc.Driver"); -
获取数据库连接:使用DriverManager类的getConnection()方法获取数据库连接,需要提供数据库URL、用户名和密码等连接参数,例如:
String url = "jdbc:mysql://localhost:3306/test"; String username = "root"; String password = "password"; Connection conn = DriverManager.getConnection(url, username, password); -
创建Statement对象:使用Connection对象的createStatement()方法创建一个Statement对象,用于执行SQL语句,例如:
Statement stmt = conn.createStatement(); -
执行SQL语句:使用Statement对象的executeQuery()或executeUpdate()方法执行SQL语句,例如:
ResultSet rs = stmt.executeQuery("SELECT * FROM users"); int rows = stmt.executeUpdate("INSERT INTO users(name, age) VALUES('Tom', 20)"); -
处理结果集:如果SQL语句是SELECT语句,则需要使用ResultSet对象处理查询结果,例如:
while (rs.next()) { String name = rs.getString("name"); int age = rs.getInt("age"); System.out.println("Name: " + name + ", Age: " + age); } -
关闭数据库连接:使用Connection、Statement和ResultSet对象的close()方法关闭数据库连接,例如:
rs.close(); stmt.close(); conn.close();
以上就是JDBC访问数据库的基本步骤。需要注意的是,在实际应用中,为了提高性能和安全性,需要使用连接池、预编译SQL语句等技术来优化JDBC程序。
14.为什么要使用PreparedStatement?
- 提高性能:PreparedStatement是预编译的SQL语句,即在执行SQL语句之前,数据库已经将SQL语句编译成二进制代码,从而提高了执行效率。而使用Statement执行SQL语句时,每次都需要将SQL语句解析为二进制代码,再执行,效率较低。
- 避免SQL注入攻击:使用PreparedStatement可以避免SQL注入攻击。SQL注入攻击是指攻击者通过在用户输入中插入恶意SQL语句,从而达到攻击的目的。使用PreparedStatement时,数据库会对SQL语句的参数进行类型校验,从而避免了SQL注入攻击。
- 支持批量操作:使用PreparedStatement可以支持批量操作,即执行多个相同或不同的SQL语句。批量操作可以大大减少网络传输的数据量和数据库的IO操作,从而提高了执行效率。
- 提高代码可读性和可维护性:使用PreparedStatement可以将SQL语句和参数分离,从而使代码更加清晰、可读性更好。此外,PreparedStatement还可以重复使用,从而减少了代码量和维护难度。
综上所述,使用PreparedStatement比使用Statement更为推荐,因为它可以提高性能、安全性和可维护性。
15.数据库连接池的原理。为什么要使用连接池?
数据库连接池是一种管理数据库连接的技术,它可以在应用程序和数据库之间建立一个连接池,并预先创建一定数量的数据库连接,这些连接可以被应用程序重复利用。数据库连接池的原理如下:
- 初始化连接池:连接池在启动时会预先创建一定数量的数据库连接,这些连接存储在一个池中,等待应用程序请求连接。
- 获取连接:应用程序请求连接时,连接池会从池中取出一个空闲连接并返回给应用程序。如果没有空闲连接,连接池可以创建一个新的连接并返回给应用程序。
- 使用连接:应用程序使用连接访问数据库。如果连接在使用过程中发生错误,连接池会回收该连接并创建一个新的连接。
- 返还连接:应用程序使用完连接后,需要将连接返还给连接池。连接池会将该连接标记为空闲状态,等待下一个应用程序请求连接。
数据库连接池的好处有以下几个方面:
- 提高性能:连接池预先创建一定数量的数据库连接,并将这些连接存储在一个池中。这些连接可以被应用程序重复利用,从而避免了频繁地创建和关闭连接,提高了应用程序的性能。
- 减少资源消耗:数据库连接是一种资源消耗较大的资源,频繁地创建和关闭连接会造成一定的资源浪费。连接池可以重复利用连接,减少了资源的浪费。
- 控制连接数:连接池可以限制数据库连接的数量,从而避免了过多的连接占用数据库资源。
- 提高稳定性:连接池可以检测连接的健康状况,如果连接发生故障,连接池可以自动回收连接并创建一个新的连接。
综上所述,数据库连接池是一种管理数据库连接的技术,它可以提高应用程序的性能、减少资源消耗、控制连接数和提高稳定性,因此在实际应用中非常常见。
面试题 3.20 ~ 3.24日
1. execute,executeQuery,executeUpdate的区别是什么?
- execute() 方法可执行任意SQL语句,包括SELECT、INSERT、UPDATE、DELETE 等语句,但它不能返回查询结果或受影响的行数。如果执行的是SELECT语句,execute() 方法会返回一个布尔值,表示是否有结果集。需要通过调用 getResultSet() 方法获取结果集。
- executeQuery() 方法用于执行SELECT语句并返回结果集,它不能用于执行INSERT、UPDATE、DELETE等语句。如果执行的不是SELECT语句,则会抛出SQLException异常。
- executeUpdate() 方法用于执行INSERT、UPDATE、DELETE等语句并返回受影响的行数,如果执行的是SELECT语句,则会抛出SQLException异常。
因此,三者的主要区别在于它们执行的SQL语句类型和返回值类型。
2. JDBC ResultSet是什么?
JDBC(Java Database Connectivity)是Java语言访问关系型数据库的标准API,而 ResultSet 则是 JDBC API 中的一个接口,它表示从数据库中返回的结果集。
当使用 executeQuery() 方法执行SELECT语句时,会返回一个ResultSet对象,该对象包含了满足查询条件的所有行,每一行都是一个ResultSet对象中的一个记录,每个记录包含了多个字段,可以通过字段名或字段索引来获取。
ResultSet 对象提供了多种方法,可以通过这些方法来遍历、检索和操作结果集。例如,可以使用 next() 方法将游标移到结果集的下一行,使用 getString()、getInt() 等方法获取指定字段的值,使用 updateXXX() 方法更新结果集中的某个字段值等等。
需要注意的是,ResultSet 对象通常是基于流式查询结果构建的,因此在查询时会占用一定的资源。在使用完ResultSet对象后,必须使用close()方法显式关闭该对象,以释放资源
3.什么是 Servlet?
Servlet是Java EE Web应用程序中的一种Java类,它主要用于处理客户端请求并生成响应。Servlet 运行在支持Java Servlet规范的Web服务器上,如Tomcat、Jetty等。Servlet技术是构建Web应用程序的核心技术之一,常用于实现动态Web页面和Web服务。
Servlet使用Java编写,它可以接收来自客户端的请求(通常是HTTP请求),并对请求进行处理,生成相应的响应。Servlet可以访问请求中包含的参数和头信息,也可以向响应中添加头信息和内容,从而生成需要的输出。Servlet还可以通过Java API访问底层数据源,如数据库、文件系统等。
Servlet通常使用Java Servlet API来开发,这个API定义了Servlet开发所需的类和接口。Servlet API包含了很多核心类和接口,如ServletRequest、ServletResponse、Servlet、Filter等,通过这些类和接口,开发者可以轻松地处理HTTP请求和响应,实现复杂的业务逻辑和数据处理。
总之,Servlet是Java EE中用于处理Web请求的核心技术之一,它能够通过Java编写处理请求,并生成响应,可以被Web服务器加载、运行和管理。
4.doGet和doPost 方法有什么区别?
在 Servlet 中,doGet() 和 doPost() 方法都是用于处理 HTTP 请求的方法,它们之间的区别如下:
- doGet() 方法用于处理 HTTP GET 请求,而 doPost() 方法用于处理 HTTP POST 请求。
- doGet() 方法将请求参数追加在 URL 的末尾,并通过 HTTP 请求发送给服务器,而 doPost() 方法则将请求参数包含在 HTTP 请求体中,并通过 HTTP 请求发送给服务器。
- doGet() 方法可以通过URL在浏览器中直接访问,而 doPost() 方法通常不直接访问,而是在表单提交时使用。
因此,当需要从服务器获取数据时,通常使用 doGet() 方法,而当需要向服务器发送数据时,通常使用 doPost() 方法。另外,由于 doPost() 方法将参数包含在请求体中,因此它更安全,可以处理大量的数据,并避免了因为 URL 长度限制而导致的数据丢失的问题。
5.JSP 有哪些动作?分别是什么?
JSP(Java Server Pages)是一种基于Java技术的Web应用程序开发技术,它允许在HTML页面中嵌入Java代码和Java标签,以生成动态Web页面。JSP提供了多种动作,可以帮助开发人员处理特定的任务,如访问数据库、转发请求、设置Cookie等等。下面是JSP中常用的一些动作:
- include:用于将其他JSP或HTML页面包含到当前页面中。
- forward:用于将请求转发到其他资源,如Servlet或JSP。
- param:用于获取请求参数的值。
- setProperty:用于设置JavaBean对象的属性值。
- getProperty:用于获取JavaBean对象的属性值。
- useBean:用于创建或获取JavaBean对象。
- plugin:用于在JSP页面中嵌入Java applet或其他对象。
- jsp:include:类似于include动作,但只能包含JSP页面。
- jsp:forward:类似于forward动作,但只能转发到其他JSP页面。
- jsp:useBean:类似于useBean动作,但可以通过class属性指定JavaBean的类名。
- jsp:setProperty:类似于setProperty动作,但可以通过name属性指定JavaBean的名称。
- jsp:getProperty:类似于getProperty动作,但可以通过name属性指定JavaBean的名称。
这些JSP动作提供了丰富的功能,可以帮助开发人员快速、方便地构建动态Web应用程序。
6.JSP 常用的指令?
-
page指令:用于指定JSP页面的属性,如页面语言、缓存需求、错误页面等。page指令通常出现在JSP页面的第一行,具体语法如下:
<%@ page 属性名="属性值" %>
其中属性名可以是:
language
、contentType
、pageEncoding
、session
、isThreadSafe
、errorPage
、buffer
、autoFlush
等。 -
include指令:用于在JSP页面中包含其他JSP页面或HTML页面。include指令通常用于重用代码或页面结构。具体语法如下:
<%@ include file="文件名" %>
-
taglib指令:用于导入标签库,使得JSP页面可以使用标签库中定义的标签。具体语法如下:
<%@ taglib uri="标签库URI" prefix="前缀" %>
其中,uri
属性用于指定标签库的唯一资源标识符(URI),prefix
属性用于指定在JSP页面中引用标签库时使用的前缀。
这些指令可以使JSP页面的处理更加灵活和方便,提高了JSP开发的效率和可维护性。
7.页面间对象传递的方法?
request、session、application、cookie
8.JSP 中动态INCLUDE 与静态INCLUDE 的区别?
- 静态包含:使用jsp:include标签将一个JSP页面嵌入到另一个JSP页面中,并在编译时将嵌入的页面的代码合并到主页面中。这意味着在主页面被访问时,被包含的页面已经被执行了。因此,如果被包含的页面中包含有动态内容,它们也会在主页面中被执行。
- 动态包含:使用jsp:include标签将一个JSP页面嵌入到另一个JSP页面中,但在运行时才会执行被嵌入的页面。这意味着被包含的页面中包含的动态内容只有在主页面被访问时才会被执行,而不是在编译时就执行了。
因此,静态包含和动态包含的主要区别在于它们执行嵌入的页面的时间不同。静态包含在编译时执行被包含的页面,而动态包含在运行时才执行被包含的页面。一般来说,如果被包含的页面中包含有动态内容,应该使用动态包含,否则应该使用静态包含。
9.JSP 的四大范围?
JSP 中的四种作用域包括 page、request、session 和application,
具体来说:
-
page 代表与一个页面相关的对象和属性。
-
request 代表与Web 客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个 Web 组件;需要在页面显示的临时数据可以置于此作用域。
-
session 代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的 session 中。
-
application 代表与整个 Web 应用程序相关的对象和属性,它实质上是跨越整个 Web 应用程序,包括多个页面、请求和会话的一个全局作用域
10.BS与CS 的联系与区别?
1.硬件环境不同:
-
C/S一般建立在专用的网络上,小范围里的网络环境,局域网之间再通过专门服务器提供连接和数据交换服务.
-
B/S建立在广域网之上的,不必是专门的网络硬件环境,例与电话上网,租用设备.信息自己管理.有比C/S更强的适应范围,一般只要有操作系统和浏览器就行
2 . 对安全要求不同
-
C/S一般面向相对固定的用户群,对信息安全的控制能力很强.一般高度机密的信息系统采用C/S结构适宜.可以通过B/S发布部分可公开信息.
-
B/S建立在广域网之上,对安全的控制能力相对弱,可能面向不可知的用户。
3.对程序架构不同
- C/S程序可以更加注重流程,可以对权限多层次校验,对系统运行速度可以较少考虑.
- B/S对安全以及访问速度的多重的考虑,建立在需要更加优化的基础之上.比C/S有更高的要求B/S结构的程序架构是发展的趋势,从MS的.Net系列的BizTalk2000Exchange2000等,全面支持网络的构件搭建的系统.SUN和IBM推的JavaBean构件技术等,使B/S更加成熟.
4.软件重用不同
- C/S程序可以不可避免的整体性考虑,构件的重用性不如在B/S要求下的构件的重用性好.
- B/S对的多重结构,要求构件相对独立的功能.能够相对较好的重用.就入买来的餐桌可以再利用,而不是做在墙上的石头桌子
5.系统维护不同
-
C/S程序由于整体性,必须整体考察,处理出现的问题以及系统升级.升级难.可能是再做一个全新的系统
-
B/S构件组成,方面构件个别的更换,实现系统的无缝升级.系统维护开销减到最小.用户从网上自己下载安装就可以实现升级.
6.处理问题不同
-
C/S程序可以处理用户面固定,并且在相同区域,安全要求高需求,与操作系统相关.应该都是相同的系统
-
B/S建立在广域网上,面向不同的用户群,分散地域,这是C/S无法作到的.与操作系统平台关系最小.
7.用户接口不同
-
C/S多是建立的Window平台上,表现方法有限,对程序员普遍要求较高
-
B/S建立在浏览器上,有更加丰富和生动的表现方式与用户交流.并且大部分难度减低,减低开发成本.
8.信息流不同
-
C/S程序一般是典型的中央集权的机械式处理,交互性相对低
-
B/S信息流向可变化,B-BB-CB-G等信息、流向的变化,更像交易中心。
11.说出Servlet的生命周期,并说出Servlet和CGI的区别?
- Servlet被实例化:当服务器启动或在第一次请求Servlet时,Servlet容器(如Tomcat)会创建一个Servlet实例。
- 调用init()方法:一旦Servlet被实例化,容器就会调用它的init()方法。在这个方法中,Servlet可以执行一些初始化任务,例如读取配置文件和建立数据库连接等。
- 处理请求:每当有一个请求到达服务器时,Servlet容器就会将请求发送给适当的Servlet。
- 调用service()方法:一旦Servlet接收到请求,容器就会调用它的service()方法。在这个方法中,Servlet可以检查请求的类型(GET或POST)并根据需要执行相应的操作。
- 生成响应:一旦Servlet完成处理请求的过程,它会生成一个响应并将其发送回客户端。
- 调用destroy()方法:当服务器关闭或Servlet不再需要时,容器会调用Servlet的destroy()方法。在这个方法中,Servlet可以执行一些清理任务,例如释放资源和关闭数据库连接等。
Servlet和CGI的区别:
CGI(Common Gateway Interface)是一种用于创建动态Web内容的标准,它使用外部进程来处理请求并生成响应。相比之下,Servlet是基于Java的服务器端组件,它使用内部线程池来处理请求。
下面是Servlet和CGI之间的主要区别:
- 性能:Servlet比CGI更高效,因为它不需要启动和停止外部进程。相反,Servlet容器会维护一个线程池来处理请求,从而提高了性能。
- 安全性:由于CGI使用外部进程,因此存在安全漏洞的风险。相比之下,Servlet的安全性更高,因为它运行在受控的Java虚拟机环境中。
- 可移植性:Servlet是用Java编写的,因此可以在任何支持Java的平台上运行。相比之下,CGI需要在Web服务器上安装CGI解释器才能运行,这可能会限制其可移植性。
总之,Servlet比CGI更高效、更安全、更可移植。
12.如何防止表单重复提交?
- 后端处理:在服务器端处理表单提交时,可以使用一些技术来防止重复提交。例如,在处理表单提交前,可以生成一个唯一的令牌(Token),并将其存储在Session中。然后,在每次表单提交时,服务器会检查Session中是否存在该令牌。如果存在,则说明表单已经被提交过了,服务器会拒绝处理该请求。
- 前端处理:在客户端使用JavaScript可以防止表单重复提交。例如,在表单提交前,可以禁用提交按钮或将其隐藏,以防止用户重复点击提交按钮。或者在提交表单时,使用Ajax来发送表单数据,而不是通过传统的表单提交方式。
- PRG模式:Post-Redirect-Get(PRG)是一种常见的模式,它可以防止表单重复提交。在PRG模式中,当表单提交成功后,服务器会将用户重定向到另一个页面,而不是直接返回表单页面。这样,即使用户点击浏览器的“后退”按钮,也不会重复提交表单。
- Token机制:在表单中添加一个隐藏的Token字段,用于标识表单的唯一性。当表单提交时,服务器会验证Token的合法性,如果Token无效,则拒绝处理该请求。
无论采用哪种方法,都可以有效地防止表单重复提交。同时,开发者也可以结合多种方法使用,以提高防护效果。
13.request作用?
在Web应用程序中,request是一个重要的对象,它代表了一个HTTP请求。request对象包含了客户端发出的HTTP请求的所有信息,例如请求头、请求参数、请求体等。
下面是request对象的主要作用:
- 获取请求信息:request对象提供了很多方法,可以获取HTTP请求中的各种信息,例如请求URL、请求方法、请求头、请求参数、请求体等。
- 存储请求信息:request对象也可以存储一些请求相关的信息,例如请求处理过程中产生的一些状态信息,可以将其存储在request对象中,在后续处理中可以继续使用。
- 转发请求:在Web应用程序中,经常需要将请求转发给其他Servlet或JSP页面。request对象提供了一个forward()方法,可以将请求转发给其他组件。
- 共享数据:request对象也可以用于在Servlet之间共享数据。例如,一个Servlet可以将某些数据存储在request对象中,然后将请求转发给另一个Servlet,在另一个Servlet中可以通过request对象获取共享的数据。
- 处理会话:request对象可以用于处理会话,例如获取会话ID、设置会话属性等。
总之,request对象在Web应用程序中扮演着非常重要的角色,可以用于获取请求信息、存储状态信息、转发请求、共享数据等。开发人员需要充分利用request对象的功能,以提高Web应用程序的性能和可扩展性。
14.get请求中文乱码?
在HTTP GET请求中,中文参数在URL中以URL编码的形式进行传递,例如将“中文”转换成“%E4%B8%AD%E6%96%87”。当客户端发送HTTP GET请求时,浏览器会自动将中文参数进行URL编码,并将编码后的参数附加在URL后面。
如果在Servlet中直接使用request.getParameter()方法获取中文参数,则可能会出现中文乱码的问题。原因是,getParameter()方法默认使用ISO-8859-1字符集解码参数值,而不是UTF-8字符集。
为了解决中文乱码的问题,可以采取以下方法:
-
在客户端使用encodeURIComponent()方法对参数进行编码,然后发送到服务器端。在服务器端使用URLDecoder.decode()方法对参数进行解码。例如:
客户端代码:
var param = encodeURIComponent('中文'); location.href = 'http://localhost/servlet?param=' + param; 服务器端代码:
String param = request.getParameter("param"); param = URLDecoder.decode(param, "UTF-8"); -
在Servlet中手动设置请求参数的字符集为UTF-8,例如:
request.setCharacterEncoding("UTF-8"); String param = request.getParameter("param"); 这样,在调用getParameter()方法时,就会使用UTF-8字符集解码参数值,避免中文乱码的问题。
无论采用哪种方法,都可以有效地解决中文乱码的问题。同时,开发人员也应该在设计Web应用程序时,尽量避免在URL中传递中文参数,以提高程序的可维护性和可读性。
15.post请求中文乱码问题?
在HTTP POST请求中,中文参数在请求体中进行传递,而不是在URL中进行传递。如果在Servlet中直接使用request.getParameter()方法获取中文参数,则可能会出现中文乱码的问题。原因是,getParameter()方法默认使用ISO-8859-1字符集解码参数值,而不是UTF-8字符集。
为了解决POST请求中的中文乱码问题,可以采取以下方法:
-
在客户端的HTML表单中添加accept-charset="UTF-8"属性,例如:
<form action="servlet" method="post" accept-charset="UTF-8"> <input type="text" name="param" value="中文"> <input type="submit" value="提交"> </form> 这样,当客户端提交表单时,参数值会以UTF-8编码方式进行提交。
-
在Servlet中手动设置请求参数的字符集为UTF-8,例如:
request.setCharacterEncoding("UTF-8"); String param = request.getParameter("param"); 这样,在调用getParameter()方法时,就会使用UTF-8字符集解码参数值,避免中文乱码的问题。
无论采用哪种方法,都可以有效地解决POST请求中的中文乱码问题。同时,开发人员也应该在设计Web应用程序时,尽量使用POST请求来传递参数,避免在URL中传递中文参数,以提高程序的可维护性和可读性。
面试题 3.27 ~ 3.31日
1.hibernate 和 mybatis 的区别?
Hibernate是一种ORM(对象关系映射)框架,它将Java对象映射到关系型数据库中的数据表中,使开发人员可以使用面向对象的方式来操作数据库。它提供了一种简单的方式来查询、插入、更新和删除数据库记录。
MyBatis是一种持久层框架,它通过XML或注解的方式将Java对象映射到SQL语句中,使开发人员可以使用简单的方式来执行数据库操作。它提供了一种简单的方式来执行查询、插入、更新和删除操作,并且可以灵活地处理复杂的SQL语句。
因此,Hibernate更适合开发大型的、复杂的应用程序,而MyBatis则更适合开发小型的、简单的应用程序,因为它更注重于SQL的编写和执行,可以更好地处理复杂的SQL语句。
相同点:
- 都属于 ORM 框架
- 都是对 jdbc 的包装
- 都属于持久层的框架
不同点:
- hibernate 是面向对象的,mybatis 是面向 sql 的;
- hibernate 全自动的 orm,mybatis 是半自动的 orm;
- hibernate 查询映射实体对象必须全字段查询,mybatis 可以不用;
- hibernate 级联操作,mybatis 则没有;
- hibernate 编写 hql 查询数据库大大降低了对象和数据库的耦合性,mybatis 提供动态 sql, 需要手写 sql,与数据库之间的耦合度取决于程序员所写的 sql 的方法,所以 hibernate 的移植性要远大于 mybatis。
- hibernate 有方言夸数据库,mybatis 依赖于具体的数据库。
- hibernate 拥有完整的日志系统,mybatis 则相对比较欠缺。
2.MyBatis 的优点?
MyBatis的优点如下:
-
灵活性:MyBatis支持使用SQL语句,这意味着开发人员可以使用任何SQL语句来执行数据库操作,而不必受制于框架中的特定语法。
-
易于使用:MyBatis提供了简单易用的API,使得开发人员可以轻松地执行数据库操作,而不必学习复杂的ORM框架。
-
易于调试:MyBatis可以输出生成的SQL语句,使得开发人员可以轻松地调试和优化应用程序。
-
易于扩展:MyBatis提供了插件机制,使得开发人员可以自定义插件来扩展框架的功能。
-
性能优化:MyBatis可以使用缓存来提高应用程序的性能,同时也支持批量操作,可以减少与数据库的交互次数,从而提高性能。
-
与Spring集成:MyBatis可以与Spring框架集成,使得开发人员可以轻松地使用Spring的依赖注入和事务管理功能。
3.MyBatis 框架的缺点?
MyBatis框架的缺点如下:
-
SQL语句维护困难:MyBatis使用SQL语句来执行数据库操作,这意味着开发人员需要手动编写和维护SQL语句,这可能会导致代码冗长和维护困难。
-
对开发人员的要求较高:相比于Hibernate这样的ORM框架,MyBatis需要开发人员具备更多的数据库知识,能够编写高效的SQL语句,从而更好地利用框架的优势。
-
配置文件较为繁琐:MyBatis需要开发人员编写大量的XML配置文件,这可能会增加开发人员的工作量,同时也可能会导致配置文件的混乱和错误。
-
不适合复杂的关系映射:MyBatis在处理复杂的关系映射时可能会变得复杂和困难,因为它需要开发人员手动编写SQL语句来处理关系映射。
-
易受SQL注入攻击:由于MyBatis使用SQL语句来执行数据库操作,如果开发人员不小心编写了不安全的SQL语句,可能会导致SQL注入攻击的风险。
4.SpringMVC 工作流程?
SpringMVC的工作流程如下:
-
客户端发送请求到DispatcherServlet。
-
DispatcherServlet将请求传递给HandlerMapping,HandlerMapping根据请求的URL映射到对应的Controller。
-
Controller处理请求,并返回一个ModelAndView对象。
-
DispatcherServlet将ModelAndView对象传递给ViewResolver,ViewResolver根据视图名称解析出对应的视图。
-
DispatcherServlet将Model传递给视图,视图将Model渲染成HTML响应。
-
DispatcherServlet将HTML响应发送给客户端。
在这个过程中,还会涉及到拦截器、异常处理器等组件的调用,以及数据绑定、类型转换等操作。整个过程是由SpringMVC框架来控制和协调的。
5.MyBatis 框架使用的场合?
MyBatis框架适用于以下场合:
-
数据库操作比较复杂或需要执行复杂的SQL语句的场合。
-
数据库表结构比较复杂或需要进行高级映射的场合。
-
对数据库性能要求较高的场合,MyBatis可以使用缓存来提高性能。
-
需要灵活控制SQL语句的场合,MyBatis可以通过XML或注解来编写SQL语句,使得开发人员可以更灵活地控制SQL语句。
-
需要与Spring集成的场合,MyBatis可以与Spring框架集成,使得开发人员可以轻松地使用Spring的依赖注入和事务管理功能。
-
需要使用多数据源的场合,MyBatis可以通过配置多个SqlSessionFactory来实现多数据源的支持。
总之,MyBatis框架适用于需要灵活控制SQL语句、对数据库性能要求较高、需要与Spring集成、需要使用多数据源等场合。
6.SpringIOC 注入的几种方式?
SpringIOC支持以下几种注入方式:
-
构造函数注入(Constructor Injection):通过构造函数注入,Spring容器会在创建Bean实例时调用指定的构造函数,将依赖的对象作为参数传入。
-
属性注入(Setter Injection):通过属性注入,Spring容器会在创建Bean实例后,调用Bean的Setter方法,将依赖的对象注入到Bean的属性中。
-
接口注入(Interface Injection):通过接口注入,Spring容器会在创建Bean实例后,调用Bean实现的接口方法,将依赖的对象作为参数传入。
-
注解注入(Annotation Injection):通过注解注入,使用注解标记依赖的对象,Spring容器在创建Bean实例时,会自动扫描注解,并将依赖的对象注入到Bean中。
不同的注入方式适用于不同的场景,开发人员可以根据实际情况选择合适的注入方式。其中,构造函数注入和属性注入是最常用的注入方式。
7.拦截器与过滤器的区别?
1、拦截器是基于java的反射机制的,而过滤器是基于函数回调
2、拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
3、拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
4、拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
5、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
8.SpringIOC是什么?
Spring IOC(控制反转)是Spring框架的核心,它是一种设计模式,用于降低程序耦合度,提高代码的可重用性和可维护性。Spring IOC通过反转对象的创建和依赖关系的管理,实现了程序的松耦合,使得程序代码更加简洁、灵活和易于维护。Spring IOC包括两个核心概念:Bean和容器。Bean是Spring框架中的基本组件,是由Spring容器创建、管理和维护的对象;容器是Spring框架中的核心组件,负责管理Bean的生命周期和依赖关系。Spring IOC提供了多种注入方式,包括构造函数注入、属性注入、接口注入和注解注入等,开发人员可以根据实际情况选择合适的注入方式。在使用Spring IOC时,开发人员只需要定义好Bean的配置信息,由Spring容器来负责创建和管理对象,从而使得程序的开发和维护更加方便和高效。
SpringIOC负责创建对象,管理对象(通过依赖注入(DI),装配对象,配置对象,并且管理这些对象的整个生命周期。
9.AOP有哪些实现方式?
AOP(面向切面编程)是一种编程范式,用于在程序运行时动态地将代码切入到类的指定方法或者指定位置上,从而增加程序的功能和可重用性。AOP主要有以下几种实现方式:
-
基于代理的AOP:通过代理模式实现切面功能,将切面和目标对象封装在同一个代理对象中,代理对象在执行目标方法时,会先执行切面方法,再执行目标方法。
-
基于字节码操作的AOP:通过修改目标类的字节码来实现切面功能,需要使用特定的字节码操作库,如ASM、Javassist等。
-
基于注解的AOP:通过在目标方法上添加注解,再通过解析注解来实现切面功能,可以使用Spring AOP等框架提供的注解实现。
-
基于XML配置的AOP:通过在XML配置文件中定义切面和通知,再将切面和通知应用到目标对象上,实现切面功能。Spring AOP就是基于XML配置的AOP实现。
不同的实现方式各有优缺点,开发人员需要根据实际情况进行选择和使用。基于代理的AOP实现比较常用,它不需要修改目标类的字节码,也比较容易理解和使用;而基于字节码操作的AOP实现可以获得更高的性能,但是需要对字节码有一定的了解;基于注解的AOP实现比较简洁,但是对于复杂的切面需求,可能需要使用XML配置的AOP实现。
10.解释一下代理模式?
代理模式是一种结构型设计模式,它允许通过代理对象间接地访问一个对象,从而控制对该对象的访问。代理模式常用于增强原有对象的功能、隐藏原有对象的实现细节、控制对象的访问权限等场合。
代理模式包含三个角色:抽象主题角色、真实主题角色和代理主题角色。
抽象主题角色定义了真实主题角色和代理主题角色的共同接口,可以是抽象类或者接口。
真实主题角色是实际执行业务逻辑的对象,代理主题角色是真实主题角色的代理,它与真实主题角色具有相同的接口,可以完全代替真实主题角色执行相同的业务逻辑。代理主题角色通常会在执行真实主题角色的业务逻辑前或者后,执行一些额外的操作,比如记录日志、缓存结果、控制访问等。
代理模式可以分为静态代理和动态代理两种实现方式。
静态代理需要手动编写代理类,代理类与真实主题类实现相同的接口或者继承相同的父类,通过代理类来访问真实主题类。
动态代理则是在程序运行时动态地生成代理类,不需要手动编写代理类,可以通过Java反射机制来实现。动态代理通常使用Java提供的Proxy类或者第三方库,如CGLIB等。
代理模式可以在不修改原有对象的情况下,对其进行增强或者控制其访问权限,从而提高程序的灵活性、可扩展性和可维护性。
11.Mybatis是如何sql执行结果封装为目标对象?都有哪些映射形式?
MyBatis是一种基于Java的持久层框架,它提供了一种将SQL执行结果映射为目标对象的机制,这种机制称为对象关系映射(ORM)。
MyBatis的ORM机制可以通过以下两种映射形式来实现:
-
基于XML的映射:通过在XML配置文件中定义SQL语句和结果集的映射关系,再通过MyBatis提供的API将SQL执行结果映射为目标对象。XML配置文件中可以定义多个SQL语句和结果集的映射关系,通过namespace和id来唯一标识。
-
基于注解的映射:通过在目标对象的属性上添加注解,将属性与数据库表的列进行映射。当执行SQL语句时,MyBatis会自动将结果集中的列映射到目标对象的属性中,从而实现ORM。
MyBatis在执行SQL语句时,会根据SQL语句的执行结果和目标对象的类型来自动进行映射。如果SQL语句的执行结果是一个简单类型(如int、String等),则可以直接将结果赋值给目标对象;如果SQL语句的执行结果是一个复杂类型(如自定义的Java对象),则需要通过映射关系将结果集中的列映射到目标对象的属性中。
MyBatis提供了多种映射方式,包括属性映射、构造函数映射、枚举映射、关联映射等,开发人员可以根据实际情况选择合适的映射方式。在使用MyBatis时,开发人员需要根据实际情况定义好SQL语句和映射关系,从而实现数据的持久化。
12.Springbean的生命周期?
-
Spring容器根据bean定义创建bean实例。
-
Spring使用依赖注入(DI)将配置文件中的值或引用注入到bean实例中。
-
如果bean实现了BeanNameAware接口,Spring容器将bean的ID传递给setBeanName()方法。
-
如果bean实现了BeanFactoryAware接口,Spring容器将bean工厂实例传递给setBeanFactory()方法。
-
如果存在与bean关联的任何BeanPostProcessors(例如BeanValidationPostProcessor、AutowiredAnnotationBeanPostProcessor等),则调用postProcessBeforeInitialization()方法。
-
如果bean实现了InitializingBean接口,Spring容器将调用afterPropertiesSet()方法,如果在bean定义中指定了init-method,则Spring容器将调用指定的方法。
-
如果存在与bean关联的任何BeanPostProcessors,则调用postProcessAfterInitialization()方法。
-
如果bean实现了DisposableBean接口,Spring容器将调用destroy()方法,如果在bean定义中指定了destroy-method,则Spring容器将调用指定的方法。
需要注意的是,BeanPostProcessors和InitializingBean/DisposableBean接口提供了扩展Spring Bean生命周期的能力。开发人员可以实现这些接口,编写自己的BeanPostProcessors和初始化/销毁方法,以实现对Bean生命周期的定制化控制。
13.Spring框架中都用到了哪些设计模式?
Spring框架中用到的设计模式有很多,以下是一些常见的设计模式:
-
依赖注入(DI)和控制反转(IoC):这是Spring框架最核心的设计模式,它允许开发人员将对象之间的依赖关系从代码中抽离出来,由Spring容器负责管理和注入对象之间的依赖关系。
-
工厂模式:Spring框架中的BeanFactory和ApplicationContext接口都是工厂模式的应用,它们负责创建和管理对象的实例。
-
单例模式:Spring框架中默认情况下所有的bean都是单例的,即在整个应用程序中只有一个实例。
-
模板方法模式:Spring框架中的JdbcTemplate和HibernateTemplate等模板类都是模板方法模式的应用,它们封装了一些通用的操作,让开发人员可以专注于业务逻辑的实现。
-
观察者模式:Spring框架中的事件机制就是观察者模式的应用,它允许开发人员在应用程序中定义事件和监听器,并在事件发生时通知所有相关的监听器。
-
适配器模式:Spring框架中的适配器模式主要应用于Spring MVC中的HandlerAdapter,它允许开发人员编写自定义的控制器,并将它们适配到Spring MVC框架中。
-
代理模式:Spring框架中的AOP(面向切面编程)就是代理模式的应用,它允许开发人员在不修改原有代码的情况下,对方法进行增强或拦截。
-
装饰器模式:Spring框架中的Filter、Interceptor和Advice都是装饰器模式的应用,它们可以在目标方法执行前后添加一些额外的逻辑。
除了上述常见的设计模式,Spring框架中还用到了其他一些设计模式,如策略模式、迭代器模式、组合模式等。Spring框架的设计思想和实现方式都体现了面向对象设计原则和设计模式的应用。
14.Spring中的事件处理?
-
ApplicationContext是Spring的核心,它负责管理bean的生命周期、提供国际化、资源访问、AOP等功能。Spring还提供了一些内置事件,如ContextRefreshedEvent、ContextStartedEvent、ContextStoppedEvent、ContextClosedEvent、RequestHandleEvent等。
-
Spring事件处理是同步的,即所有的事件处理器都是在同一个线程中执行的,但是并不会阻塞该线程。如果事件处理器需要执行长时间的任务,可以使用异步任务或线程池来处理,以避免阻塞主线程。
-
监听上下文事件的方式可以通过实现ApplicationListener接口或使用@EventListener注解来实现。如果需要监听多个事件类型,可以使用@Order注解指定监听器的执行顺序,或使用SmartApplicationListener接口来实现更加灵活的监听器。
-
开发人员可以通过继承ApplicationEvent类来定义自己的事件类型,并通过ApplicationContext的publishEvent()方法来发布事件。同时,开发人员还需要定义自己的事件监听器,可以通过实现ApplicationListener接口或使用@EventListener注解来实现。自定义事件可以更好地解耦应用程序中的不同组件,使得代码更加灵活和可维护。在事件处理中,如果需要访问事件源对象或其他Spring组件,可以使用@Autowire注解来注入相关的组件依赖。
总之,Spring事件处理是一种基于观察者模式的实现,它可以将应用程序中的不同组件解耦,使得代码更加灵活和可维护。在使用时,需要注意事件处理的同步性和性能问题,以及如何使用监听器和自定义事件来实现特定的业务需求。
15.使用Sping框架的好处是什么?
使用Spring框架的好处如下:
-
提高开发效率:Spring框架提供了大量的现成的功能和组件,如IoC容器、AOP、事务管理、数据访问、安全性等,可以帮助开发人员快速地构建应用程序,提高开发效率。
-
降低开发成本:Spring框架是开源的,可以免费使用和修改,而且提供了许多常用的功能和组件,可以减少开发人员的工作量和开发成本。
-
提高代码质量:Spring框架提供了一些设计模式和最佳实践,如IoC、AOP、依赖注入等,可以帮助开发人员编写高质量、可维护、可测试的代码。
-
提高应用程序的可扩展性和灵活性:Spring框架使用IoC容器来管理对象之间的依赖关系,可以使应用程序更加灵活和可扩展,易于维护和升级。
-
与其他框架的集成:Spring框架可以与其他框架和技术集成,如Hibernate、MyBatis、Struts、JSF、JMS、RESTful等,可以使应用程序更加强大和灵活。
-
提高应用程序的安全性:Spring框架提供了一些安全性功能,如认证、授权、加密、过滤器等,可以保护应用程序免受恶意攻击和数据泄露等威胁。
综上所述,使用Spring框架可以提高开发效率、降低开发成本、提高代码质量、提高应用程序的可扩展性和灵活性、与其他框架的集成、提高应用程序的安全性等好处。因此,Spring框架是现代企业级Java应用程序开发的首选框架之一。
面试题 4.3~ 4.7日
1.解释Spring支持的几种bean的作用域?
Spring Framework 支持以下五种 Bean 作用域:
-
Singleton:单例模式,在整个 Spring IOC 容器中,使用 singleton 定义的 Bean 将只有一个实例。
-
Prototype:多例模式,每次通过容器中的 getBean 方法获取 prototype 定义的 Bean 时,都会产生一个新的 Bean 的实例。
-
Request:对于每次 HTTP 请求,使用 request 定义的 Bean 都会产生一个新的实例。只有在 Web 应用时候,该作用域才会有效。
-
Session:对于每次 HttpSession,使用 session 定义的 Bean 都将产生一个新的实例。
-
Global Session:每个全局的 HttpSession,使用 session 定义的 Bean 都将产生一个新的实例。只有在 Web 应用时候,该作用域才会有效。
不同的作用域适用于不同的场景,可以根据需要选择合适的作用域。例如,对于一些非常通用的 Bean,可以使用 Singleton 作用域,在整个应用程序中共享一个实例,以提高性能。而对于一些需要频繁创建和销毁的 Bean,可以使用 Prototype 作用域,每次获取时都会创建一个新的实例。
2.在Spring中如何注入一个java集合?
有使用xml和注解两种
在Spring中,我们可以使用以下几种方式来注入Java集合:
- 使用
@Autowired
和@Qualifier
注解
使用@Autowired
注解可以自动装配Spring容器中的组件,而@Qualifier
注解可以指定注入的组件名称。我们可以将其用于集合类型的属性上,例如:
@Component public class MyComponent { @Autowired @Qualifier("myList") private List<String> myList; // other methods... }
- 使用
@Resource
注解
@Resource
注解可以指定注入的组件名称或者类型。我们可以将其用于集合类型的属性上,例如:
@Component public class MyComponent { @Resource(name = "myList") private List<String> myList; // other methods... }
- 在XML配置文件中使用
<list>
标签
在XML配置文件中,我们可以使用<list>
标签来配置一个列表,并将其注入到组件中,例如:
<bean id="myComponent" class="com.example.MyComponent"> <property name="myList"> <list> <value>item1</value> <value>item2</value> <value>item3</value> </list> </property> </bean>
2.使用<set>
标签
<bean id="myBean" class="com.example.MyBean"> <property name="mySet"> <set> <value>item1</value> <value>item2</value> <value>item3</value> </set> </property> </bean>
3.在XML配置文件中使用<map>
标签
同样,在XML配置文件中,我们可以使用<map>
标签来配置一个映射,并将其注入到组件中,例如:
<bean id="myComponent" class="com.example.MyComponent"> <property name="myMap"> <map> <entry key="key1" value="value1" /> <entry key="key2" value="value2" /> <entry key="key3" value="value3" /> </map> </property> </bean>
4.使用<props>
标签
<bean id="myBean" class="com.example.MyBean"> <property name="myProps"> <props> <prop key="prop1">value1</prop> <prop key="prop2">value2</prop> <prop key="prop3">value3</prop> </props> </property> </bean>
以上是在Spring中注入Java集合的几种方式。根据具体的应用场景和需求,我们可以选择其中的一种或多种方式来实现。
3.什么是Springbean?
它们是构成用户应用程序主干的对象。
Bean由SpringIoC容器管理。
它们由SpringIoC容器实例化,配置,装配和管理。
Bean是基于用户提供给容器的配置元数据创建。
4.什么是spring自动装配?
Spring 自动装配是一种通过 Spring IoC 容器自动连接应用程序中的各个组件的机制。通过自动装配,Spring 能够自动发现应用程序中定义的 Bean,并将其自动连接到需要它的其他 Bean 中。
在 Spring 中,自动装配可以通过三种方式实现:byName、byType 和 constructor。其中,byName 方式会根据 Bean 的名称进行自动装配,byType 方式会根据 Bean 的类型进行自动装配,而 constructor 方式则会根据构造函数的参数类型进行自动装配。
Spring 的自动装配机制能够减少编写大量重复代码的工作量,提高应用程序的可维护性和可读性。但是,在实际应用中,由于自动装配会影响应用程序的灵活性和可测试性,因此需要谨慎使用。
总之,Spring 自动装配是一种通过 Spring IoC 容器自动连接应用程序中的各个组件的机制。通过使用自动装配,Spring 能够减少重复代码的编写,提高应用程序的可维护性和可读性,但需要注意其对应用程序的灵活性和可测试性的影响。、
Spring自动装配是一种机制,它允许Spring框架自动将需要的依赖项注入到一个类中,而无需显式地编写依赖注入的代码。这使得开发人员可以更快速地开发应用程序,因为他们不必担心手动创建和管理依赖关系。Spring自动装配可以通过几种不同的方式来实现,包括基于注解的自动装配、基于XML配置的自动装配和基于Java配置的自动装配。这些方式都可以根据应用程序的需求进行选择和使用。
、‘
5.自动装配有哪些方式?
- byName:根据 Bean 的名称进行自动装配。当容器中存在一个与属性名称匹配的 Bean 时,Spring 将会把该 Bean 注入到属性中。例如,一个名为 "customerDAO" 的 Bean 可以自动装配到属性名为 "customerDao" 的属性中。
- byType:根据 Bean 的类型进行自动装配。当容器中存在一个与属性类型匹配的 Bean 时,Spring 将会把该 Bean 注入到属性中。例如,如果一个类需要一个 DataSource 类型的 Bean,那么容器会自动找到一个类型为 DataSource 的 Bean 并注入到该属性中。
- constructor:根据构造函数的参数类型进行自动装配。当容器中存在一个与构造函数参数类型匹配的 Bean 时,Spring 将会把该 Bean 注入到构造函数中。例如,如果一个类的构造函数需要一个类型为 DataSource 的参数,那么容器会自动找到一个类型为 DataSource 的 Bean 并注入到该构造函数中。
6.自动装配有什么局限?
- 覆盖的可能性:在自动装配过程中,可能存在多个 Bean 可以注入到同一个属性中,此时需要注意是否需要覆盖。可以通过显式地指定依赖关系来覆盖自动装配。
- 基本元数据类型:Spring 自动装配只适用于 Bean 对象,无法对基本元数据类型(如原数据类型、字符串和类)进行自动装配。这些类型的属性需要使用显式依赖注入。
- 令人困惑的性质:自动装配可以带来便利,但也容易出现问题,因为它不太精确。使用明确的依赖注入可以更加清晰地表达 Bean 之间的依赖关系,从而减少混淆和错误。
1、覆盖的可能性-您始终可以使用
将覆盖自动装配。
2、基本元数据类型-简单属性(如原数据类型,字符串和类)无法自动装配。
3、令人困惑的性质-总是喜欢使用明确的装配,因为自动装配不太精确。
7.Spring的重要注解?
@Controller-用于SpringMVC项目中的控制器类。
@Service-用于服务类。
@RequestMapping-用于在控制器处理程序方法中配置URI映射。
@ResponseBody-用于发送Object作为响应,通常用于发送XML或JSON数据作为响应。
@PathVariable-用于将动态值从URI映射到处理程序方法参数。
@Autowired-用于在springbean中自动装配依赖项。
@Qualifier-使用@Autowired注解,以避免在存在多个bean类型实例时出现混淆。
@Scope-用于配置springbean的范围。
@Configuration,@ComponentScan和@Bean-用于基于java的配置。
@Aspect,@Before,@After,@Around,@Pointcut-用于切面编程(AOP)。
8.@Component,@Controller,@Repository,@Service有何区别?
@Service、@Repository、@Controller都是@Component注解的特化,也就是它们本质上都是@Component,都可以被组件扫描机制自动识别为bean并被IoC容器管理。
但是它们具有不同的语义用途,可以更加清晰地表明被注解类的职责和作用。
-
@Service注解通常用于标注业务逻辑组件,
-
@Repository注解通常用于标注数据访问组件,
-
@Controller注解通常用于标注Web请求处理组件。
-
@Component:这将java类标记为bean。
9.列举spring支持的事务管理类型?
Spring支持两种类型的事务管理:
- 编程式事务管理:在此过程中,通过编写代码来管理事务,手动开启、提交或回滚事务。这种方式提供了极大的灵活性,但也很容易出现错误,而且不易于维护。
- 声明式事务管理:在此方式中,事务管理与业务代码分离,仅使用注解或基于XML的配置来管理事务。这种方式通常更易于使用和维护,并且可以避免代码中的重复逻辑。可以使用以下方式实现声明式事务管理:
- 基于注解的声明式事务管理:使用 @Transactional 注解来管理事务。
- 基于XML的声明式事务管理:在XML配置文件中使用 [tx:advice](javascript:void(0)) 元素和 [aop:advisor](javascript:void(0)) 元素来管理事务。
10.Spring框架的事物管理有哪些优点?
Spring框架的事务管理具有以下优点:
- 简化编程 - Spring的事务管理抽象了底层的事务实现机制,使编程更加简单。开发人员只需要将业务逻辑封装在事务方法中,而不需要考虑底层的事务管理机制。
- 提高可重用性 - Spring的事务管理使得可以将事务逻辑和业务逻辑分离。这使得事务代码更加可重用,并且可以在不同的应用程序和不同的数据库中使用。
- 支持多种事务管理机制 - Spring的事务管理支持JDBC事务、Hibernate事务、JTA事务等多种事务管理机制,可以根据不同的应用程序和不同的数据源选择不同的事务管理机制。
- 提供声明式事务管理 - Spring的事务管理支持声明式事务管理,这使得可以在不修改现有代码的情况下,对事务管理进行配置和调整。使用声明式事务管理可以将事务管理与业务逻辑分离,使得业务逻辑更加清晰。
- 支持事务传播机制 - Spring的事务管理支持事务传播机制,可以根据需要控制事务的范围和行为。使用事务传播机制可以解决复杂的事务场景,并且提高了系统的可靠性和性能。
综上所述,Spring的事务管理具有简化编程、提高可重用性、支持多种事务管理机制、提供声明式事务管理和支持事务传播机制等优点。这些优点使得Spring的事务管理成为开发人员首选的事务管理解决方案之一。
11.SpringAOP(面向切面)编程的原理?
Spring AOP(面向切面)编程是一种基于代理模式的编程范式,它通过在运行时动态地将代码横向切割,从而实现了横切关注点的模块化。AOP 可以解决许多与业务无关的系统级问题,如事务管理、安全性、缓存、日志记录等。
Spring AOP 的核心原理是动态代理。在运行时,Spring AOP 会为目标对象创建一个代理对象,代理对象会拦截目标对象的方法调用,并在方法调用前后执行一些附加的逻辑。Spring AOP 支持两种代理方式:JDK 动态代理和 CGLIB 代理。
JDK 动态代理是基于接口的代理,它要求目标对象必须实现一个接口。JDK 动态代理通过反射机制在运行时创建代理对象,代理对象实现了目标对象的接口,并将方法调用转发给目标对象。JDK 动态代理只能代理实现了接口的目标对象。
CGLIB 代理是基于类的代理,它可以代理任何类,包括没有实现接口的类。CGLIB 代理通过继承目标对象创建代理对象,并覆盖目标对象的方法。CGLIB 代理在运行时生成字节码,因此比 JDK 动态代理慢一些,但是它可以代理任何类,包括 final 类型的类。
Spring AOP 还支持切点、通知和切面等概念。切点定义了哪些方法应该被代理,通知定义了在方法调用前、后或异常时执行的逻辑,切面则是将切点和通知组合起来的概念。Spring AOP 还支持多个切面的联合,可以将多个切面按照特定的顺序组合起来,形成一个完整的切面链。
Spring AOP (Aspect-Oriented Programming)是一种编程范式,用于在应用程序中解耦关注点。AOP通过在应用程序中跨越多个对象、方法和类来实现这一点。它的核心是切面(Aspect),切面是一个与业务逻辑无关的横切关注点,它可以被任何对象、方法和类使用。
Spring AOP的原理是通过在运行时动态地创建代理对象来实现切面。当使用Spring AOP时,Spring容器会为被代理对象创建一个代理对象,当代理对象上的方法被调用时,Spring AOP会根据一组规则(定义在切点上)来决定是否在方法执行前、执行后或执行时插入切面的代码。代理对象隐藏了切面的实现细节,使得被代理对象的方法看起来就像是直接被调用,但实际上会被切面拦截并执行相关的代码。
Spring AOP的实现基于Java的动态代理机制或者CGLIB库,它可以对Spring管理的任何Bean应用切面,无需修改源代码。它还支持在XML配置文件或使用注解来定义切点和切面,使得开发人员能够方便地应用AOP,从而提高应用程序的可维护性和可扩展性。
12.SpringMVC框架有什么用?
SpringMVC框架的主要作用如下:
- 帮助开发人员构建Web应用程序的MVC架构,实现代码的分层和模块化,提高代码的可重用性和可维护性。
- 提供了一种基于注解和XML配置的声明式编程方式,使得开发人员可以更加方便地管理控制器、视图和模型等组件。
- 支持RESTful Web服务,提供多种请求和响应类型的支0,如JSON、XML、HTML等。
- 内置了多种视图解析器和模板引擎,包括JSP、Thymeleaf、Freemarker等,使得开发人员可以根据自己的需求选择适合的视图技术。
- 提供了强大的数据绑定和验证机制,使得开发人员可以轻松地处理表单数据和进行数据验证。
- 支持拦截器机制,可以在请求的不同阶段进行拦截和处理,实现日志记录、安全验证、性能监控等功能。
总之,SpringMVC框架为开发人员提供了一种高效、灵活、可扩展和易于维护的Web应用程序开发框架,可以大大提高开发效率和代码质量。
13.Mybatis中#{}和${}的区别是什么?
#{}
是预编译处理,${}
是字符串替换。
Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来
赋值;
Mybatis在处理
高系统安全性。
14.Spring中@Autowire与@Resource的区别?
在Spring中,@Autowire和@Resource都是用来进行依赖注入的注解,但是它们有以下区别:
-
@Autowire是Spring提供的注解,而@Resource是JSR-250规范中定义的注解。
-
@Autowire默认按照类型进行注入,如果存在多个类型一致的Bean,则按照名称进行匹配。而@Resource默认按照名称进行注入,如果名称无法匹配,则按照类型进行匹配。
-
@Autowire可以用在构造函数、Setter方法、字段和方法上,而@Resource只能用在字段和Setter方法上。
-
@Autowire支持装配集合类型的Bean,如List、Map等,而@Resource不支持。
总的来说,@Autowire更加灵活,也更加常用,但是@Resource的使用也是非常方便的。在实际开发中,可以根据具体情况选择使用哪个注解。
15.什么是控制反转(IOC),什么是依赖注入(DI)?
IOC:就是对象之间的依赖关系由容器来创建,对象之间的关系本来是由我们开发者自己创
建和维护的,在我们使用Spring框架后,对象之间的关系由容器来创建和维护,将开发者
做的事让容器做,这就是控制反转。BeanFactory接口是SpringIoc容器的核心接口。
DI:我们在使用Spring容器的时候,容器通过调用set方法或者是构造器来建立对象之间的
依赖关系。
控制反转是目标,依赖注入是我们实现控制反转的一种手段。
面试题 4.10~ 4.14日
1.介绍一下WebApplicationContext?
WebApplicationContext是ApplicationContext的扩展。它具有Web应用程序所需的一些额
外功能。它与普通的ApplicationContext在解析主题和决定与哪个servlet关联的能力方面
有所不同。
WebApplicationContext是Spring框架中专门为Web应用程序而设计的一个ApplicationContext。它提供了一些额外的功能,如自动加载Web应用程序中的配置文件,管理Web应用程序中的Bean,以及与Web应用程序相关的环境信息等。
WebApplicationContext的主要作用是管理Web应用程序中的Bean,并提供这些Bean的依赖注入、AOP等功能。同时,它还提供了让Web应用程序访问Spring上下文的接口,以及在Web应用程序中使用Spring MVC等Web框架的支持。
在WebApplicationContext中,每个Servlet都有自己的ApplicationContext,这意味着每个Servlet都可以拥有自己的Bean定义和实例。这些Bean可以被Servlet直接访问和使用,也可以被其他Servlet共享使用。
总之,WebApplicationContext是一个专门为Web应用程序而设计的Spring上下文,它提供了一些额外的功能,使得Spring框架在Web应用程序中更加易用和灵活。
2.Spring的事务传播行为?
-
PROPAGATION_REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是默认的事务传播行为。
-
PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
-
PROPAGATION_MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常。
-
PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。一个新的事务将启动,而且如果有一个现有的事务在运行的话,则这个方法将在运行期被挂起,直到新的事务提交或者回滚才恢复执行。
-
PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
-
PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
-
PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。外层事务抛出异常回滚,那么内层事务必须回滚,反之内层事务并不影响外层事务。
3.SpringMVC的运行流程?
-
客户端发送请求到DispatcherServlet。
-
DispatcherServlet将请求传递给HandlerMapping,HandlerMapping根据请求的URL映射到对应的Controller。
-
Controller处理请求,并返回一个ModelAndView对象。
-
DispatcherServlet将ModelAndView对象传递给ViewResolver(视图解析器),ViewResolver根据视图名称解析出对应的视图。
-
DispatcherServlet将Model传递给视图,视图将Model渲染成HTML响应。
-
DispatcherServlet将HTML响应发送给客户端。
在这个过程中,还会涉及到拦截器、异常处理器等组件的调用,以及数据绑定、类型转换等操作。整个过程是由SpringMVC框架来控制和协调的。
4. 什么是数据库
数据库是指按照一定的数据模型,将大量数据集中存储起来,并提供数据管理、数据查询和数据处理等功能的数据存储系统。它可以为各种应用程序提供数据支持,如企业管理系统、电子商务平台、社交网络等。数据库能够提供数据的持久化存储、数据的并发控制、数据的备份和恢复、数据的安全性保障等功能,使得用户可以方便地访问和使用数据。常见的数据库软件包括Oracle、MySQL、SQL Server、PostgreSQL等。
5.主流数据库服务软件有哪些?开源且跨平台的数据库软件有哪些?
主流数据库服务软件包括:
-
Oracle Database:一款商业数据库软件,提供高可用性、高性能和安全性。
-
Microsoft SQL Server:一款商业数据库软件,提供高可用性、强大的数据分析和报告功能。
-
MySQL:一款开源数据库软件,提供高性能、可扩展性和灵活性。
-
PostgreSQL:一款开源数据库软件,提供高可靠性、安全性和可扩展性。
-
IBM DB2:一款商业数据库软件,提供高可用性、高性能和安全性。
开源且跨平台的数据库软件包括:
-
MySQL:一款开源数据库软件,支持多种操作系统和平台。
-
PostgreSQL:一款开源数据库软件,支持多种操作系统和平台。
-
MongoDB:一款开源的NoSQL数据库软件,支持多种操作系统和平台。
-
SQLite:一款轻量级的开源数据库软件,支持多种操作系统和平台。
-
Apache Cassandra:一款开源的分布式数据库软件,支持多种操作系统和平台。
6.MySQL的特点及应用
MySQL是一种开源的关系型数据库管理系统,具有以下特点:
-
开源免费:MySQL是开源软件,免费使用,无需支付任何版权费用。
-
跨平台性:MySQL可以在多个操作系统上运行,包括Windows、Linux、Unix等。
-
易于使用:MySQL提供了简单易用的命令行工具和图形化界面,使得用户可以轻松地管理和操作数据库。
-
高性能:MySQL具有高效的数据存储和检索能力,支持高并发访问,适合处理大量数据。
-
可扩展性:MySQL支持多种存储引擎,可以根据不同的需求选择不同的存储引擎,如InnoDB、MyISAM等。
-
数据安全:MySQL提供了多种安全特性,如访问控制、数据加密等,保证数据的安全性。
MySQL广泛应用于各种类型的应用程序,包括Web应用、企业应用、移动应用等。常见的应用场景包括:
-
数据存储:MySQL可以用于存储各种类型的数据,如用户信息、产品信息等。
-
数据分析:MySQL可以用于存储和分析大量的数据,如销售数据、用户行为数据等。
-
Web应用:MySQL可以用于支持各种类型的Web应用,如电子商务网站、社交网络等。
-
企业应用:MySQL可以用于支持企业级应用,如人力资源管理、客户关系管理等。
-
移动应用:MySQL可以用于支持移动应用,如移动游戏、移动电商等。
7.mysql服务相关参数有什么?
MySQL服务相关参数包括:
-
数据库端口号:默认为3306,可以通过修改my.cnf文件中的port参数来更改端口号。
-
数据库字符集:默认为utf8,可以通过修改my.cnf文件中的character_set_server参数来更改字符集。
-
最大连接数:默认为151,可以通过修改my.cnf文件中的max_connections参数来增加或减少最大连接数。
-
缓存大小:包括缓存池大小、缓存索引大小等,可以通过修改my.cnf文件中的相关参数来调整缓存大小。
-
日志文件大小和数量:包括错误日志、慢查询日志、二进制日志等,可以通过修改my.cnf文件中的相关参数来调整日志文件大小和数量。
-
数据库存储路径:默认为/var/lib/mysql,可以通过修改my.cnf文件中的datadir参数来更改数据库存储路径。
-
数据库用户和密码:默认为root用户,可以通过修改my.cnf文件中的相关参数来更改数据库用户和密码。
-
MySQL配置文件路径:默认为/etc/mysql/my.cnf,可以通过修改启动命令行参数来指定其他配置文件路径。
8.mysql操作指令和注意事项?
MySQL是一种关系型数据库管理系统,它使用SQL语言进行数据库操作。以下是一些常用的MySQL操作指令和注意事项:
- 连接MySQL服务器
使用以下命令连接MySQL服务器:
mysql -h 主机名 -u 用户名 -p
其中,主机名是MySQL服务器的主机名或IP地址,用户名是MySQL服务器的用户名,-p选项表示需要输入密码。
- 创建数据库
使用以下命令创建一个名为test的数据库:
CREATE DATABASE test;
- 使用数据库
使用以下命令选择test数据库:
USE test;
- 创建表
使用以下命令创建一个名为users的表:
CREATE TABLE users ( id INT(11) NOT NULL AUTO_INCREMENT, name VARCHAR(50) NOT NULL, email VARCHAR(50) NOT NULL, PRIMARY KEY (id) );
- 插入数据
使用以下命令向users表中插入数据:
INSERT INTO users (name, email) VALUES ('John', 'john@example.com');
- 查询数据
使用以下命令查询users表中的数据:
SELECT * FROM users;
- 更新数据
使用以下命令更新users表中的数据:
UPDATE users SET name='Alice' WHERE id=1;
- 删除数据
使用以下命令删除users表中的数据:
DELETE FROM users WHERE id=1;
- 导入数据
使用以下命令从文件中导入数据:
LOAD DATA INFILE 'data.txt' INTO TABLE users;
注意事项:
- MySQL命令必须以分号结尾。
- MySQL命令不区分大小写。
- 在MySQL中,所有对象(数据库、表、列等)都有一个名称,名称必须唯一且不超过64个字符。
- 在创建表时,必须为每个列指定数据类型。
- 在插入数据时,必须为每个非空列指定值。
- 在更新数据时,必须指定要更新的列和更新后的值。
- 在删除数据时,必须指定要删除的行。
- 在导入数据时,文件必须位于MySQL服务器上,并且MySQL用户必须具有文件读取权限。
9.mysql库管理命令都有什么?
这些命令是针对 MySQL 数据库的,常见的库管理命令包括:
-
SHOW DATABASES;:显示已有的库。
-
USE 库名;:切换库。
-
SELECT DATABASE();:显示当前所在的库。
-
CREATE DATABASE 库名;:创建新库。
-
SHOW TABLES;:显示已有的表。
-
DROP DATABASE 库名;:删除库。
还有其他的一些库管理命令,例如:
-
ALTER DATABASE:修改数据库的属性。
-
GRANT:授权。
-
REVOKE:取消授权。
-
BACKUP DATABASE:备份数据库。
-
RESTORE DATABASE:还原数据库。
-
OPTIMIZE DATABASE:优化数据库表。
-
CHECK DATABASE:检查数据库表。
10.常见的信息种类
•数值型:体重、身高、成绩、工资
•字符型:姓名、工作单位、通信住址
•枚举型:兴趣爱好、性别
•日期时间型:出生日期、注册时间
11.(数值型)关于整数型字段
整数型字段是一种常见的数值类型,在数据库中用于存储整数值。在使用整数型字段时,可以使用UNSIGNED修饰符来指定该字段只保存正数值。如果数值不够指定宽度时,数据库管理软件会在左侧使用空格进行补位,宽度仅用于显示,实际存储的大小由数据类型决定。使用关键字ZEROFILL时,数据库管理软件会使用0代替空格进行补位。如果数值超出了字段的范围,则数据库管理软件会报错。
12.(数值型)关于浮点型字段
定义格式:float(总宽度,小数位数)
当字段值与类型不匹配时,指带有数据库并整合了数据库管理软件的
计算机系统字段值作为0处理
数值超出范围时,指带有数据库并整合了数据库管理软件的计算机系
统仅保存最大/最小值
13.字符类型
-
定长:char(字符数)
- 最大长度255字符
- 不够指定字符数时在右边用空格补齐
- 字符数断超出时,指带有数据库并整合了数据库管理软件的计算机系统无法写入数据。
-
变长:varchar(字符数) 按数据实际大小分配存储空间
14.日期时间类型
-
日期时间,DATETIME
- 占用8个字节
- 范围:1000-01-0100:00:00.000000~9999-12-3123:59:59.999999
-
日期时间,TIMESTAMP
- 占用4个字节
- 范围:1970-01-0100:00:00.000000~2038-01-1903:14:07.999999
-
日期,DATE
- 占用4个字节
- 范围:0001-01-01~9999-12-31
-
年份,YEAR
- 占用1个字节
- 范围:1901~2155
-
时间,TIME
-
占用3个字节
-
格式:HH:MM:SS
-
15.时间函数
- now() 获取系统当前日期和时间
- year() 执行时动态获得系统日期时间
- sleep(N) 休眠N秒
- curdate() 获取当前的系统日期
- curtime() 获取当前的系统时刻
- month() 获取指定时间中的月份
- date() 获取指定时间中的日期
- time() 获取指定时间中的时刻
面试题 4.17~ 4.21日
1.枚举类型
- 从给定值集合中选择单个值,ENUM
- 定义格式:enum(值1,值2,值N)
- 从给定值集合中选择一个或多个值,SET
- 定义格式:set(值1,值2,值N)
2.约束条件
- Null允许为空,默认设置
- NOTNULL不允许为空
- Key索引类型
- Default设置默认值,缺省为NULL
3.修改表结构的基本用法
- ALTER TABLE表名执行动作;
- Add添加字段
- Modify修改字段类型
- Change修改字段名
- Drop删除字段
- Rename修改表名
4.索引是什么?
- 索引是对记录集的多个字段进行排序的方法。
- 类似于书的目录
- 索引类型包括:Btree、B+tree、hash
5.索引优缺点?
-
索引优点
- 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性
- 可以加快数据的检索速度
-
索引缺点
- 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,
- 降低了数据的维护速度
- 索引需要占物理空间
6.键值类型有几种,分别是什么?
- INDEX:普通索引
- UNIQUE:唯一索引
- FULLTEXT:全文索引
- PRIMARYKEY:主键
- FOREIGNKEY:外键
7.INDEX普通索引说明?
- 一个表中可以有多个INDEX字段
- 字段的值允许有重复,切可以赋NULL值
- 经常把做查询条件的字段设置为INDEX字段
- INDEX字段的KEY标志是MUL
8.primarykey主键注意事项
- 一个表中只能有一个primarykey字段
- 对应的字段值不允许有重复,且不允许赋NULL值
- 如果有多个字段都作为PRIMARYKEY,称为复合主键,必须一起创建。
- 主键字段的KEY标志是PRI
- 通常与AUTO_INCREMENT连用
- 经常把表中能够唯一标识记录的字段设置为主键字段
9.foreignkey外键什么是外键?
- 让当前表字段的值在另一个表中字段值的范围内选择。
- 使用外键的条件
- 表的存储引擎必须是innodb
- 字段类型要一致
- 被参照字段必须要是索引类型的一种(primarykey)
10.简述MySQL体系结构的组成,并描述每个组成部分的作用。
- 连接池:进程数限制、内存检查、缓存检查等。
- SQL接口:用户通过sql客户端发过来的命令,由sql接口接收,sql操作(DML数据操作语言:查询、修改、升级数据等;
- DDL数据定义语言:创建一个新的数据库、新的索引、删除一个用户等;
存储过程、视图触发器。 - 分析器:分析查询语句事务处理对象访问权限。
- 优化器:优化访问路径、生成执行树。
- 缓存和缓冲:保存sql查询结果。
- 存储引擎:用于管理存储的文件系统,将逻辑结构转换为物理结构的程序;不同的存储引擎有不同的功能和存储方式。
- 管理工具:备份,恢复,安全,移植,集群等,这些工具一般和文件系统
打交道,不需要和mysql-server打交道,它们对应的都是命令。
物理存储设备(文件系统)。
11.MySQL存储引擎
-
作为可插拔式的组件提供
- MySQL服务软件自带的功能程序,处理表的处理器
- 不同的存储引擎有不同的功能和数据存储方式
-
默认的存储引擎
-
MySQL5.0/5.1--->MyISAM
-
MySQL5.5/5.6--->InnoDB
-
12.Myisam存储引擎的主要特点
- 支持表级锁
- 不支持事务、事务回滚、外键
- 相关的表文件
- 表名.frm
- 表名.MYI
- 表名.MYD
13.InnoDB存储引擎主要特点
-
支持行级锁定
-
支持事务、事务回滚、支持外键
-
相关的表文件
-
xxx.frm、xxx.ibd
-
ibdata1
-
ib_logfile0
-
ib_logfile1
-
14.MySQL锁机制
-
锁粒度
-
表级锁:一次直接对整张表进行加锁。
-
行级锁:只锁定某一行。
-
页级锁:对整个页面(MySQL管理数据的基本存储单位)进行加锁。
-
-
锁类型
-
读锁(共享锁):支持并发读。
-
写锁(互斥锁、排它锁):是独占锁,上锁期间其他线程不能读表或写表。
-
15.数据库事务的事务特性(ACID)
- Atomic:原子性
- 事务的整个操作是一个整体,不可分割,要么全部成功,要么全部失败。
- Consistency:一致性
- 事务操作的前后,表中的记录没有变化。
- Isolation:隔离性
- 事务操作是相互隔离不受影响的。
- Durability:持久性
- 数据一旦提交,不可改变,永久改变表数据
本文作者:柒木木木
本文链接:https://www.cnblogs.com/qimu666/articles/17280732.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步