1.Error和Exception区别是什么
Error 是错误类,通常为虚拟机相关错误,如系统崩溃,内存溢出等,编译器不会对这类错误进行检测。
Exception是异常类,是可以在Java程序中进行捕获并处理的,遇到异常时应对其进行处理,使应用程序可以继续正常运行。
2.运行时异常和一般异常区别
区别在于是否强制要求调用者必须处理此异常。
- 运行时异常是指 RuntimeException 类及其子类,表示 JVM 在运行期间可能出现的异常,Java 编译器不会检查运行时异常。
- 受检异常是指 Exception 中除 RuntimeException 及其子类之外的异常,Java 编译器会检查受检异常。
3.throw和throws的区别是什么
- throw 关键字用在方法内部,用来抛出可能会发生的异常,后面跟的是异常对象名。
- throws 关键字用在方法声明上,用来声明该方法可能抛出的异常列表,后面跟的是异常类名,可以抛出多个异常类名。
二、多线程
1.并行和并发有什么区别?
并行:多个处理器同时处理多个不同的任务,这是物理上的同时发生。
并发:一个处理器可以同时处理多个任务,这是逻辑上的同时发生。
简单理解:并行就是三个人同时吃三个苹果,并发就是一个人同时吃三个苹果。
2.进程与线程的区别
- 进程:进程是操作系统资源分配的基本单位。每个进程都有自己独立的一块内存空间。一个进程可以有多个线程。
- 线程:线程是处理器任务调度和执行的基本单位。一个进程至少有多个线程,多个线程间可共享一块内存空间及其数据。
3.守护线程和用户线程有什么区别?
- 用户线程:运行在前台,执行用户具体的任务,如 main() 方法所在的线程是主线程,也是用户线程。
- 守护线程:运行在后台,为其他前台线程服务。一旦所有用户线程都结束运行,守护线程会随 JVM 一起结束工作。
4.什么是线程死锁?
- 用户线程:运行在前台,执行用户具体的任务,如 main() 方法所在的线程是主线程,也是用户线程。
- 守护线程:运行在后台,为其他前台线程服务。一旦所有用户线程都结束运行,守护线程会随 JVM 一起结束工作。
4.什么是线程死锁?
线程死锁是指多个线程在执行过程中,由于竞争资源而造成的一种阻塞的现象。多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放,由于线程被无限期地阻塞,因此程序不可能正常终止。
5.形成死锁的四个必要条件是什么
(1)互斥条件:线程对于所分配到的资源具有排它性,即一个资源只能被一个线程占用,直到被该线程释放资源。
(2)请求与保持条件:一个线程因请求被占用资源而发生阻塞时,对已获得的资源保持不放。
(3)不可剥夺条件:线程已获得的资源在末使用完之前不能被其他线程强行剥夺,只有自己使用完毕后才释 放资源。
(4)循环等待条件:当发生死锁时,所等待的线程必定会形成一个环路,造成永久阻塞。
6.创建线程的三种方式
(1)继承Thread类,重写run方法。然后创建子类对象,调用start()方法开启线程。
(2)实现Runnable接口,重写run方法。创建Runnable子类对象,将其传递给Thread类的构造器,调用start()方法开启线程。
(3)实现Callable接口,重写call方法。创建Callable子类对象,将其传递给FutureTask的构造器,再将FutureTask对象作为参数传递给Thread类的构造器,调用start()方法开启线程。
7.线程的run()和start()有什么区别
start()方法的作用是开启新线程,让被启动的线程执行run()中的任务代码。
直接调用run()并没有开启线程,执行run()的只有main()方法一条线程。而调用start()方法会在栈内 存中开辟出一个新的线程栈区,新的线程和main线程并行执行。
8.线程的五种状态
(1)新建状态(new):新建了一个线程对象。
(2)可运行状态(runnable):线程对象创建后,当调用线程对象的start()方法,该线程处于就绪状态
(3)运行状态(running):可运行状态的线程获得了CPU的执行权,就会执行程序代码。
(4)阻塞状态(block):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态。
(5)死亡状态(dead):线程run()、main()方法执行结束或异常退出,该线程结束生命周期,死亡的线程 不可再次复生。
9.请说出与线程同步以及线程调度相关的方法
wait():使一个线程处于等待状态,并且释放所持有的对象的锁。 sleep():使一个正在运行的线程处于睡眠状态,不会释放锁,调用此方法要处理InterruptedException
异常。
notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由 JVM 确定唤醒哪个线程。
notityAll():唤醒所有处于等待状态的线程,该方法并不是将对象的锁给所有线程,而是让它们竞争,只有获得锁的线程才能进入就绪状态。
10.sleep()和wait()有什么区别
sleep()是Thread类的静态方法,wait()是Object类的方法。sleep()不释放锁,wait()释放锁。
sleep()方法执行完成后,线程会自动苏醒。wait()方法被调用后,线程不会自动苏醒,需要别的线 程调用同一个对象上的notify()或者notifyAll() 方法来唤醒线程。
11.Thread类中的yield()方法有什么作用
yield()方法的作用是使当前线程从运行状态变为就绪状态。当前线程到了就绪状态,不会立马变成运行状态,这要看CPU的调度。
12.如何停止一个正在运行的线程
在java中有以下3种方法可以终止正在运行的线程:
使用退出标志,让线程正常退出,也就是当run方法执行完后,线程自然终止。 使用stop() 方法强行终止,但是不推荐这个方法,因为stop() 是过期作废的方法。使用interrupt() 方法来中断线程。
13.notify()和notifyAll()有什么区别
notifyAll() 会唤醒所有的线程,而 notify() 只会唤醒一个线程。
notifyAll() 调用后,会将全部线程由等待池移到锁池,然后参与锁的竞争,竞争成功则继续执行,如果不成功则留在锁池等待锁被释放后再次参与竞争。而notify()只会唤醒一个线程,具体唤醒哪一个线程由虚拟机控制。
14.如何在两个线程间共享数据
在两个线程间共享变量即可实现共享数据。一般来说,共享变量要求变量本身是线程安全的,然后在线 程内使用的时候,如果有对共享变量的复合操作,那么也得保证复合操作的线程安全性。
15.同步方法和同步代码块,该如何选择
同步代码块是更好的选择,因为它不会锁住整个对象。同步方法会锁住整个对象,哪怕这个类中有多个 不相关联的代码块,这通常会导致他们停止执行,并需要等待获得这个对象上的锁。
同步代码块更要符合开放调用的原则,只在需要锁住的代码块锁住相应的对象,这样从侧面来说也可以 避免死锁。
请记住一条原则:同步的范围越小越好。
16.什么是线程同步和线程互斥
当一个线程对共享的数据进行操作时,应使之成为一个”原子操作“,即在没有完成相关操作之前,不允 许其他线程打断它,否则,就会破坏数据的完整性,必然会得到错误的处理结果,这就是线程的同步。
线程互斥是指对于共享的系统资源,在各单个线程访问时的排它性。当有若干个线程都要使用某一共享 资源时,任何时刻最多只允许一个线程去使用,其它要使用该资源的线程必须等待,直到占用资源者释 放该资源,这就是线程的互斥。
线程互斥可以看成是一种特殊的线程同步。
17.谈谈你对线程优先级的理解
每一个线程都是有优先级的,一般来说,高优先级的线程在运行时会具有优先权,但这依赖于线程调度 的实现,这个实现是和操作系统相关的。我们可以定义线程的优先级,但是这并不能保证高优先级的线 程会在低优先级的线程前执行。Java 的线程优先级调度会委托给操作系统去处理,所以与具体的操作系统优先级有关,如非特别需要,一般无需设置线程优先级。
18.synchronized和Lock有什么区别
synchronized可以给类、方法、代码块加锁,而lock只能给代码块加锁。
synchronized不需要手动加锁和释放锁,使用简单,发生异常会自动释放锁,不会造成死锁。而Lock需 要手动加锁和释放锁,如果使用不当,没有unLock()去释放锁就会造成死锁。通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。
1、说一下JVM的主要组成部分及其作用
JVM包含两个子系统和两个组件,两个子系统分别是Class loader(类装载)、Execution engine(执行引擎)。两个组件分别是Runtime data area(运行时数据区)、Native Interface(本地接口)。
首先通过 JVM 编译器把 Java 代码编译成 class文件,类加载器再把 class 文件加载到内存中,将其放在运行时数据区的方法区内,因为字节码文件只是 JVM 的一套指令集规范,并不能直接交给底层操作系统去执行,因此需要特定的命令解析器交给执行引擎区,将字节码翻译成底层系统指令,再交由 CPU 去执行,而这个过程中需要调用其他语言的本地库接口来实现整个程序的功能。
2、说一下JVM运行时数据区
Java 虚拟机在执行 Java 程序的过程中会把它所管理的内存区域划分为若干个不同的数据区域,Java 虚拟机规范的区域分为 5 个部分:程序计数器、Java 虚拟机栈、本地方法栈、Java 堆、方法区
3、栈内存和堆内存有什么区别
栈内存用于存放基本数据类型的变量、对象的引用和方法调用。堆内存用于存放数组、对象和成员 变量。
栈内存更新速度要比堆内存快,因为局部变量的声明周期很短。
栈内存中存放的变量生命周期一旦结束就会被释放,而堆内存中存放的实体会被垃圾回收机制不定 时的回收。
4、什么是深拷贝和浅拷贝
深拷贝是增加了一个指针并且申请了一块新的内存地址,使这个增加的指针指向这个新的内存地址。 浅拷贝只是增加了一个指针来指向已存在的内存地址。
5、Java会存在内存泄漏吗?请简单描述
内存泄漏是指不再被使用的对象或者变量一直被占据在内存中。理论上来说,Java语言有GC垃圾回收机制,不再被使用的对象,会被GC自动回收掉,自动从内存中清除。但是,即使这样,Java也还是存在着内存泄漏的情况。
Java导致内存泄露的原因很明确:长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄 露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收,这 就是Java中内存泄露的发生场景。
6、请你谈谈内存泄漏和内存溢出的区别
内存泄漏:是指不再被使用的对象或者变量一直被占据在内存中。内存溢出:是指程序申请内存时,没有足够的内存供申请者使用。 7、简述Java垃圾回收机制
在 Java 中,程序员是不需要显示的去释放一个对象的内存的,而是由虚拟机自行执行。在JVM中,有一个垃圾回收线程,它是低优先级的,在正常情况下是不会执行的,只有在虚拟机空闲或者当前堆内存不 足时,才会触发执行,扫描那些没有被任何引用的对象,并将它们添加到要回收的集合中,进行回收。
8、垃圾回收器的基本原理是什么
对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理堆中的所有对象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可 达的"。当GC确定一些对象为"不可达"时,GC就有责任回收这些内存空间。
9、有什么办法主动通知虚拟机进行垃圾回收
Java程序员可以手动调用System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。
10、怎么判断一个对象是否可以被回收
垃圾收集器在做垃圾回收的时候,首先需要判断的就是哪些内存是需要被回收的,哪些对象是存活的, 哪些对象是不可用的。一般有两种方法来判断:引用计数器法、可达性分析算法。
11、在Java中,对象什么时候可以被垃圾回收
当对象对当前的应用程序变得不可触及的时候,这个对象就可以被回收了。垃圾回收不会发生在永久 代,如果永久代满了或者超过了临界值,会触发完全垃圾回收(Full GC)。如果你仔细查看垃圾收集器的输出信息,就会发现永久代也是被回收的。
12、说一下JVM有哪些垃圾回收算法
标记清除算法:标记无用对象,然后进行清除回收。
复制算法:将内存划分两个大小相等的区域,当一块用完后将活着的对象复制到另一块上,然后再 把已使用的内存空间一次清理。
标记整理算法:标记无用对象,让所有存活的对象都向一端移动,然后直接清除掉端边界以外的内 存。
分代算法:根据对象存活周期的不同将内存划分为几块,一般是新生代和老年代,新生代基本采用 复制算法,而老年代采用标记整理算法。
13、JVM一次完整的GC流程是怎样的?对象如何晋升到老年代
Java堆 = 老年代 + 新生代,大小比例为1:2,如下新生代 = Eden + S0 + S1(S0和S1成为幸存者区)
对象的内存分配通常是在 Java 堆上进行分配的,对象主要分配在新生代的伊甸园区。
当Eden区满了,Java虚拟机会触发一次Minor GC,以收集新生代的垃圾,存活下来的对象,则会转移到Survior区。
大对象直接进入老年代。
如果对象在Eden出生,并经过第一次Minor GC后仍然存活,并且被Survivor容纳的话,就将其年龄设为1,每熬过一次Minor GC,年龄+1,若年龄超过一定限制(15),则被晋升到老年代,则长期存活的对象进入老年代。
老年代满了,无法容纳更多的对象,Minor GC之后经常会进行Full GC,Full GC清理整个内存堆, 包括新生代和老年代。
Major GC发生在老年代,清理老年区,经常会伴随至少一次Minor GC,比Minor GC慢10倍以上。
14、描述一下JVM加载class文件的原理机制
Java中的所有类,都必须由类加载器装载到 JVM 中才能运行。类加载器本身也是一个类,而它的工作就是把class文件从硬盘读取到内存中。在写程序的时候,我们几乎不需要关心类的加载,因为这些都是隐式装载的,除非我们有特殊的用法,比如反射,就需要显式的加载所需要的类。
类装载方式,有两种:
隐式装载, 程序在运行过程中当碰到通过new等方式生成对象时,隐式调用类装载器加载对应的类到 JVM 中。
显式装载, 通过Class.forName()等方法,显式加载需要的类。
Java的类加载是动态的,它并不会一次性将所有类全部加载后再运行,而是保证程序运行的基础类先完全加载到 JVM 中,至于其他类,则在需要的时候才加载,这当然也是为了节省内存开销。
15、什么是类加载器,类加载器有哪些
类加载器:是指可以通过类的全权限定名获取该类的二进制字节流的代码块的一个类。类加载器本身也 是一个类,主要有以下四种类加载器:
启动类加载器 (bootstrap class loader):用来加载 Java 核心类库,无法被Java程序直接引用。扩展类加载器 (extensions class loader):它用来加载 Java 的扩展库。
应用加载器 (application class loader):用来加载classpath中指定的jar包及目录中的类。自定义类加载器 (custom class loader),根据自身需要自定义的类加载器。
16、说一下类装载的执行过程
类装载分为以下 5 个步骤:
① 加载:根据查找路径找到相应的 class 文件然后导入。
② 验证:检查加载的 class 文件的正确性。
③ 准备:给类中的静态变量分配内存空间。
④ 解析:虚拟机将常量池中的符号引用替换成直接引用的过程。
⑤ 初始化:对静态变量和静态代码块执行初始化工作。
17、什么是双亲委派模型
双亲委派模型:当一个类加载器收到了类加载的请求,它不会自己去加载这个类,而是将这个请求委派 给父类加载器,由父类加载器去加载,如果父类不能加载,反馈给子类,才由子类去完成类的加载。每 一层的类加载器都是如此。
18、说一下硬、软、弱、虚引用的区别
Java提供了四种级别的应用类型:强引用、软引用、弱引用及虚引用:
强引用:相当于Object obj=new Object() 这种引用就是强引用,即使OOM也不会被垃圾回收器进行回收。
软引用:如果将要发生了OOM,则会将对象自动回收。弱引用:只要发生了gc() 就会进行回收弱引用的对象。
虚引用:主要用来跟踪对象被垃圾回收的活动。虚引用必须和引用队列关联使用。
MySQL面试题
1、数据库三大范式是什么
第一范式:每个列都不可以再拆分。
第二范式:在第一范式的基础上,消除部分依赖。第三范式:在第二范式的基础上,消除传递依赖。
2、存储引擎InnoDB与MyISAM区别
InnoDB引擎提供了对数据库事务的支持,还提供了行级锁和外键的约束。MyIASM引擎不提供事务的支持,也不支持行级锁和外键。
InnoDB索引是聚簇索引,MyISAM索引是非聚簇索引。
InnoDB的主键索引的叶子节点存储着行数据,因此主键索引非常高效。MyISAM索引的叶子节点存储的是行数据地址,需要再寻址一次才能得到数据。
3、什么是索引
索引是一种特殊的文件,文件中包含着对数据表里所有记录的引用指针。
数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据,索引 的实现通常使用B树或者B+树。
4、索引有哪些优缺点
优点:索引可以大大加快数据的检索速度。缺点:创建索引和维护索引要耗费时间,索引需要占物理空 间。
5、索引有哪几种类型
主键索引:数据列不允许重复,不允许为NULL,一个表只能有一个主键索引。
唯一索引:数据列不允许重复,允许为NULL值,一个表允许多个列创建唯一索引。普通索引:基本的索引类型,没有唯一性的限制,允许为NULL值。
全文索引:是目前搜索引擎使用的一种关键技术。
6、索引的基本原理
索引可以大大加快数据的检索速度。如果没有索引,一般来说执行查询时需要遍历整张表。索引的原理 很简单,就是把无序的数据变成有序的数据。
把创建了索引的列的内容进行排序对排序结果生成倒排表
在倒排表内容上拼上数据地址链
在查询的时候,先拿到倒排表内容,再取出数据地址链,从而拿到具体数据
7、什么是数据库事务
数据库事务是一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作 单位。
8、请你介绍一下事务的四大特性ACID
原子性 (atomicity):确保这些数据库操作要么全部执行,要么全部不执行。一致性 (consistency):事务执行前后,数据保持一致。
隔离性 (isolation):并发访问数据库时,一个事务不被其他事务所干扰。
持久性 (durability):一个事务被提交之后,它对数据库中数据的改变是持久的。
9、什么是脏读?幻读?不可重复读
脏读:是指一个事务读取到其他事务没有提交的数据。
不可重复读:是指一个事务内多次根据同一查询条件查询出来的同一行记录的值不一致。 幻读:是指一个事务内多次根据同一条件查询出来的记录行数不一致。
10、数据库的四种隔离级别
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
| READ UNCOMMITED (读未提交) | 允许 | 允许 | 允许 |
| READ COMMITED (读已经提交) | 不允许 | 允许 | 允许 |
| REPEATABLE READ (可重复读) | 不允许 | 不允许 | 允许 |
| SERIALIZABLE (串行化) | 不允许 | 不允许 | 不允许 |
11、SQL语句主要分为哪几类
DDL (数据定义语言):用于定义和管理数据对象,如数据库、数据表等。常用命令有CREATE、DROP、ALTER
DML (数据操作语言):用于操作数据库对象中的所包含的数据。常用命令有INSERT、UPDATE、DELETE DQL (数据查询语言):用于查询数据库的数据。常用命令有 SELECT
DCL (数据控制语言):用于管理数据库的语言,包括管理权限等。常用命令有 COMMIT、ROLLBACK、CRANT
12、SQL约束有哪几种
主键约束:用于控制字段内容不能重复,一个表只允许有一个主键约束。 唯一约束:用于控制字段内容不能重复,一个表可以允许有多个唯一约束。非空约束:用于控制字段的内容一定不能为NULL值。
外键约束:用于在两个表之间建立关系,需要指定引用主表的哪一列。
13、数据库设计,表之间的关系有几种
⼀对⼀:可以在任意一方添加唯一外键指向另一方的主键。
⼀对多:在多的一方建立外键,指向一的一方的主键。
多对多:需要借助第三张中间表来实现。中间表至少包含两个字段,这两个字段作为中间表的外键,分 别指向那两张表的主键。
14、MySQL的常用函数有哪些
| 常用函数 | 作用 |
| AVG | 求平均值 |
| COUNT | 统计数量 |
| MAX | 求最大值 |
| MIN | 求最小值 |
| SUM | 求和 |
| ROUND | 四舍五入函数 |
| CONCAT | 字符串连接函数 |
15、DELETE、TRUNCATE与DROP的区别
DELETE属于DML语言,而DROP和TRUNCATE属于DDL语言。
DELETE在删除时事务可以回滚,TRUNCATE和DROP删除时事务不能回滚。
DELETE和TRUNCATE在删除数据表时,表结构还在。而DROP在删除时会将表数据、索引、权限全 部删除。
DELETE删除速度稍慢,TRUNCATE删除速度较快,DROP删除速度最快。
16、写出JDBC操作数据库的几个步骤
① 注册驱动
② 获取数据连接对象 Connection conn = DriverManager.getConnection(url, username, password);
③ 获取Statement语句对象
④ 执行sql语句 ResultSet rs = stmt.executeQuery(sql)
⑤ 处理结果集
⑥ 关闭资源
17、JDBC中的Statement和PreparedStatement的区别
Statement一般用于执行固定的没有参数的SQL。PreparedStatement 一般用于执行带有?参数预编译的
SQL语句。
PreparedStatement支持占位符?传参,相对于Statement更加灵活。PreparedStatement可以有效防止SQL注入,相对于Statement更加安全。 18、JDBC中大数据量的分页解决方法
利用sql语句的内容。
进行分页,这样每次查询出的结果集中就只包含某页的数据
19、说说数据库连接池工作原理和实现方案
工作原理:Web服务器启动时会建立一定数量的池连接,并一直维持不少于此数目的池连接。客户端程 序需要连接时,池驱动程序会返回一个未使用的池连接并将其标记为忙。如果当前没有空闲连接,池驱 动程序就新建一定数量的连接,新建连接的数量有配置参数决定。当使用的池连接调用完成后,池驱动 程序将此连接标记为空闲,其他调用就可以使用这个连接。当连接数量达到连接池最大值时候,池驱动
程序将不再创建新连接,只能等连接空闲以后重用已有的连接。
实现方案:返回的数据库连接对象其实是对原始Connection的代理,代理Connection的close()方法,当 调用close()方法时,不是真正关闭连接,而是把它代理的Connection对象放回到连接池中,等待下一次 重复利用。
JavaWeb面试题
1、什么是Servlet
Servlet是用Java编写的服务器端程序,主要功能在于交互式地浏览和生成数据,生成动态Web内容。Servlet其实就是一个接口,定义了Java类能被浏览器访问到或Tomcat识别的规则。
2、说一下Servlet的生命周期方法
Servlet生命周期定义了一个Servlet如何被加载、初始化,以及它怎样接收请求、响应请求,提供服务。 init()方法:只会执行一次,在服务器装入Servlet时执行的,可以配置服务器启动时设置一些东西。
service()方法:会执行多次,它是用来处理请求进行响应的方法。当用户请求一个HttpServlet对象,该 对象的Service()方法就要调用。
destroy()方法:只会执行一次,在服务器关闭且卸载Servlet时执行该方法。
3、请你谈谈Servlet的执行原理
当服务器接收到浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径:
首先,查找web.xml文件,是否有对相应的
Tomcat会将其字节码文件加载进内存,创建其对象并调用service()方法。
4、GET和POST请求的区别
GET的请求参数是通过url传递,而POST请求参数是存放在请求体中。GET请求传递的参数是有长度限制的,而POST没有长度限制。
GET相对于POST不太安全,因为参数直接暴露在url中,所以不能用来传递敏感信息。
5、转发和重定向的区别
转发: request.getRequestDispatcher("xxx.jsp").forward(request, response);
重定向: response.sendRedirect(request.getContextPath()+"/xxx.jsp");
| 转发 | 重定向 |
| 转发地址栏不发生改变 | 重定向地址栏会发生改变 |
| 转发只能访问当前服务器下的资源 | 重定向可以访问其他服务器下的资源 |
| 转发是一次请求,可以通过request域对象共享数据 | 重定向是两次请求,不能通过request域共享数据 |
6、什么时候使用转发?什么时候使用重定向
当前后两个页面有数据传递时,使用转发。例如查询了某些数据需要在页面中显示。 当前后两个页面没有数据传递时,使用重定向。例如进行了更新操作跳转到其他页面。 7、如何解决Servlet线程不安全的问题
Servlet是非线程安全的,多线程并发的读写会导致数据不同步的问题。 解决办法是,尽量不要定义成员变量,而是要把变量分别定义在doGet()和doPost()方法内。虽然使用synchronized同步代码块可以解决 问题,但是会造成线程的等待,不是很科学的办法。
8、JSP和Servlet的区别和联系
JSP的本质上还是Servlet类。Servlet和JSP最主要的不同点在于,Servlet的应用逻辑是在Java文件中,并 且完全从表示层中的HTML里分离开来。而JSP是Java和HTML可以组合成一个扩展名为.jsp的文件,也就 是说JSP偏重于视图,Servlet偏重于业务逻辑。
9、JSP的九大内置对象及其作用
| 变量名 | 真实类型 | 作用 |
| pageContext | PageContext | (域对象)当前页面共享数据,还可以获取其他八个内置对象 |
| request | HttpServletRequest | (域对象)一次请求访问的多个资源 |
| session | HttpSession | (域对象)一次会话的多个请求间共享数据 |
| application | ServletContext | (域对象)所有用户间共享数据 |
| response | HttpServletResponse | 响应对象 |
| page | Object | 当前页面的对象this |
| out | JspWriter | 输出对象,将数据输出到页面上 |
| config | ServletConfig | Servlet的配置对象 |
| exception | Throwable | 异常对象 |
10、JSP的常用指令有哪些
page指令:定义页面的一些属性。include指令:引入一个静态的JSP页面。taglib指令:引入一个标签库。
11、cookie和session的区别
cookie数据存放在客户端上,安全性较差。session数据存放在服务器端,安全性相对较高。
cookie数据的存储有限制,单个cookie保存的数据不能超过4K,一个站点内最多保存20个cookie。而session无此限制。
session一定时间内保存在服务器上,当访问增多,占用服务器性能,考虑到服务器性能方面,应当使用cookie。
cookie的应用场景:记住密码功能、保存上一次用户登录等。session应用场景:保存一个登录用户信 息、购物车信息等。
12、请你详细描述一下MVC设计模型
基于Java的web应用系统一般都采用MVC设计模型,即用模型 - 视图 - 控制器分离设计,这是目前web应用服务系统的主流设置方向。
Model:模型,用于处理业务逻辑的模块。
View:视图,负责页面显示,将Model的处理结果显示给用户,主要实现数据到页面的转换过程。Controller:控制器,负责处理请求和响应数据的,将Model的处理结果进行响应给页面。



