天天看点

Java常见面试题一、Java基础二、容器三、多线程三、Java Web

一、Java基础

1、jdk和jre的区别

JDK(Java Development Kit)JDK是Java开发工具包,是Sun Microsystems针对Java开发员的产品。

Java Runtime Environment(JRE)是运行基于Java语言编写的程序所不可缺少的运行环境。也是通过它,Java的开发者才得以将自己开发的程序发布到用户手中,让用户使用。

2、 == 和equals 的区别

== 比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是指相同一个对象。比较的是真正意义上的指针操作。

equals用来比较的是两个对象的内容是否相等,由于所有的类都是继承自java.lang.Object类的,所以适用于所有对象,如果没有对该方法进行覆盖的话,调用的仍然是Object类中的方法,而Object中的equals方法返回的却是==的判断

3、两个对象的hashcode() 相同,则equals 则一定为true吗?

4、final在Java中的作用

1、final修饰类中的属性或者变量。无论属性是基本类型还是引用类型,final所起的作用都是变量里面存放的“值”不能变

2、final修饰类中的方法作用:可以被继承,但继承后不能被重写

3、final修饰类 作用:类不可以被继承

5、java中的Math.round(-1.5)等于多少?

-1(四舍五入)

6、String属于基础的数据类型吗?

基本数据类型包括byte、int、char、long、float、double、boolean和short。

引用数据类型包括:类,数组,接口等(简单来说就是除了基本数据类型之外的所有类型)所以String 是引用数据类型

7、Java操作字符串的类有哪些,他们之间什么区别

StringBuilder   StringBuffer  String

首先说运行速度,或者说是执行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer > String

String最慢的原因:String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的。

再来说线程安全在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的

8、String str = "str1" 与 String str = new String("str1")区别? 

String str1 = “str1”:

1、 在栈中创建str1的引用。

2、 去常量池中查看是否有相同Unicode编码的字符串常量。如果有将str1指向该常量,如果没有则创建一个内容为”str1”的字符串常量,将str1的引用指向该常量。

3、 如果str1进行了赋值str1= “123”,则栈中的str1的引用指向新的内容为“123”的字符串常量。

4、 String str1 = “str1”; String str2 = “str1”;str2的引用指向常量池中已经存在的内容为“str1”的常量,不会重新创建新的常量,str1和str2的引用指向同一个常量。

String str1 = new String(“str1”):

1、 在常量池中创建内容为“str1”的对象,在堆中创建内容为“str1”的对象。

2、 String str1 = new String(“str1”); String str2 = new String(“str1”);str2不会指向之前创建的对象,而是重新创建一个对象。

9、如何让将字符串反转?

实现方法很多,比较简单的方法 ,调用StringBuffer中的reverse方法

10、String 类的常用方法有哪些?

求字符串长度  length()

求字符串某一位置字符  charAt(int index)

提取子串  substring(int beginIndex)

字符串中单个字符查找   indexOf

字符串中字符的大小写转换  toLowerCase()  toUpperCase()

trim()   statWith(String prefix) 等等

11、抽象类必须要有抽象方法吗?

抽象类可以不包含抽象方法,

包含抽象方法的类一定是抽象类。

12、抽象类和普通类有什么区别?

1.抽象类不能被实例化。

2.抽象类可以有构造函数,被继承时子类必须继承父类一个构造方法,抽象方法不能被声明为静态。

3.抽象方法只需申明,而无需实现,抽象类中可以允许普通方法有主体

4.含有抽象方法的类必须申明为抽象类

5.抽象的子类必须实现抽象类中所有抽象方法,否则这个子类也是抽象类

13、抽象类能用final修饰吗?

抽象类需要被继承才能使用,而被final修饰的类无法被继承,所以abstract和final是不能共存的

14、接口和抽象类有什么区别?

1、抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。

2、抽象类要被子类继承,接口要被类实现。

3、接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现

4、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。

5、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。

6、抽象方法只能申明,不能实现,接口是设计的结果 ,抽象类是重构的结果

7、抽象类里可以没有抽象方法

8、如果一个类里有抽象方法,那么这个类只能是抽象类

9、抽象方法要被实现,所以不能是静态的,也不能是私有的。

10、接口可继承接口,并可多继承接口,但类只能单根继承。

15、Java中的io流分为几种?

16、BIO,NIO,AIO有什么区别?

  • Java BIO : 同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。
  • Java NIO : 同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。
  • Java AIO(NIO.2) : 异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理,

BIO、NIO、AIO适用场景分析:

  • BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。
  • NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。
  • AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持

17、Files的常用方法有哪些?

(一)访问文件名或路径

1)String getName()  返回File对象所表示的文件名或文件路径

2)String getPath()    返回File对象所对应的相对路径名。

3)File getAbsoluteFile() 返回File对象的绝对路径文件

4)String getAbsolutePath() 返回File对象所对应的绝对路径名

5)String getParent() 返回File对象所对应目录的父目录

6) boolean renameTo(File dest) 重命名File对象的文件或目录

(二)文件检测

1boolean exists()   判断File对象的文件或目录是否存在

2)bool canWrite()     判断File对象是否可写

3)boolean canRead()判断File对象是否可读

4)boolean isDirectory() 判断File对象是否是目录

5)boolean isFile() 判断File对象是否是文件

6)boolean  isAbsolute() 判断File对象是否采用绝对路径

(三)文件信息

1)long length() ; File对象对应文件的长度

2)long lastNodified()   File对象最后修改的时间

(四)文件操作

1)boolean createNewFile() ;      检查文件是否存在,当文件不存在时创建一个新的文件

2) boolean delete()             删除File对象所对应的文件或目录 

(五)目录操作

1)boolean mkdir()       创建一个File对象所对应的路径

2)String[] list()         列出File对象所有的子文件名和路径名

3)File[] listFile()     列出File对象的所有子文件或路径

4)static File[] listRoots()   列出系统所有的根路径

二、容器

1、Java容器有哪些?

|Collection 

|  ├List 

|  │-├LinkedList 

|  │-├ArrayList 

|  │-└Vector 

|  │ └Stack 

|  ├Set 

|  │├HashSet 

|  │├TreeSet 

|  │└LinkedSet 

|Map 

  ├Hashtable 

  ├HashMap 

  └WeakHashMap

2、Collection 和 Collections 区别?

1、java.util.Collection 是一个集合接口(集合类的一个顶级接口)。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式,其直接继承接口有List与Set。

2、Collections则是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。

3、List  Set  Map 之间的区别?

list   --其中的值允许重复,因为其为有序的数据结构 ,允许空值

set --其中的值不允许重复,无序的数据结构 

map--成对的数据结构,健值必须具有唯一性(键不能同,否则值替换)

4、Hashmap  Hashtable 区别?

HashMap中键值 允许为空 并且是非同步的

Hashtable中键值 不允许为空 是同步的

继承不同,但都实现了Map接口

5、Hashmap  Treemap  ?

HashMap:基于哈希表实现。

TreeMap:基于红黑树实现。

HashMap通常比TreeMap快一点(树和哈希表的数据结构使然),建议多使用HashMap,在需要排序的Map时候才用TreeMap。

6、Hashmap 的实现原理?

7、Hashset 的实现原理?

8、ArraryList 和 LinkedList 的区别?

1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 

2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。 

3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。

9、如何让实现数组和 list 之间的转换?

1.数组转换成List集合  采用java中集合自带的asList()方法就可以完成转换了

String[] array = new String[] {"zhu", "wen", "tao"};
    // String数组转List集合
    List<String> mlist = Arrays.asList(array);
           
2.List集合转换成数组  采用集合的toArray()方法直接把List集合转换成数组,
           
String[] array = mlist.toArray(new String[0]);
           

10、ArraryList 和 Vector 区别?

这两个类都实现了List接口(List接口继承了Collection接口),他们都是有序集合,即存储在这两个集合中的元素的位置都是有顺序的, 

这是HashSet之类的集合的最大不同处,HashSet之类的集合不可以按索引号去检索其中的元素,也不允许有重复的元素(本来题目问的与hashset没有任何关系, 

1)同步性:

Vector是线程安全的,也就是说是它的方法之间是线程同步的,而ArrayList是线程序不安全的,它的方法之间是线程不同步的。如果只有一个线程会访问到集合,那最好是使用ArrayList,因为它不考虑线程安全,效率会高些;如果有多个线程会访问到集合,那最好是使用Vector,因为不需要我们自己再去考虑和编写线程安全的代码。 

(2)数据增长: 

ArrayList与Vector都有一个初始的容量大小,当存储进它们里面的元素的个数超过了容量时,就需要增加ArrayList与Vector的存储空间,每次要增加存储空间时,不是只增加一个存储单元,而是增加多个存储单元,每次增加的存储单元的个数在内存空间利用与程序效率之间要取得一定的平衡。Vector默认增长为原来两倍,而ArrayList的增长策略在文档中没有明确规定(从源代码看到的是增长为原来的1.5倍)。ArrayList与Vector都可以设置初始的空间大小,Vector还可以设置增长的空间大小,而ArrayList没有提供设置增长空间的方法。 

总结:即Vector增长原来的一倍,ArrayList增加原来的0.5倍。

11、Array 和 ArrayList 区别?

(1)ArrayList是Array的复杂版本

ArrayList内部封装了一个Object类型的数组,从一般的意义来说,它和数组没有本质的差别,甚至于ArrayList的许多方法,如Index、IndexOf、Contains、Sort等都是在内部数组的基础上直接调用Array的对应方法。

(2)存储的数据类型

ArrayList可以存储异构对象,而Array只能存储相同数据类型的数据。

(3)长度的可变

Array的长度实际上是不可变的,二维变长数组实际上的长度也是固定的,可变的只是其中元素的长度。而ArrayList的长度既可以指定(即使指定了长度,也会自动2倍扩容)也可以不指定,是变长的。

(4)存取和增删元素

对于一般的引用类型来说,这部分的影响不是很大,但是对于值类型来说,往ArrayList里面添加和修改元素,都会引起装箱和拆箱的操作,频繁的操作可能会影响一部分效率。另外,ArrayList是动态数组,它不包括通过Key或者Value快速访问的算法,所以实际上调用IndexOf、Contains等方法是执行的简单的循环来查找元素,所以频繁的调用此类方法并不比你自己写循环并且稍作优化来的快,如果有这方面的要求,建议使用Hashtable或SortedList等键值对的集合。

12、queue 中的 poll() 和 ewmove() 区别?

poll()方法和remove()方法都是从队列中取出一个元素,但是poll()在获取失败的时候会返回空,remove()方法在获取数据失败的时候抛出异常

13、哪些集合类是线程安全的?

线程安全类

在集合框架中,有些类是线程安全的,这些都是jdk1.1中的出现的。在jdk1.2之后,就出现许许多多非线程安全的类。 下面是这些线程安全的同步的类:

vector:就比arraylist多了个同步化机制(线程安全),因为效率较低,现在已经不太建议使用。在web应用中,特别是前台页面,往往效率(页面响应速度)是优先考虑的。

statck:堆栈类,先进后出

hashtable:就比hashmap多了个线程安全

enumeration:枚举,相当于迭代器

除了这些之外,其他的都是非线程安全的类和接口。

14、迭代器 iterator 是什么?

15、iterator 怎么使用,有什么特点?

16、怎么确保一个集合不能被修改?

三、多线程

1、并行和并发的区别

简而言之就是并发是多个事件在同一时间段执行,而并行是多个事件在同一时间点执行。

2、线程和进程的区别

进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些

3、守护线程是什么?

1、守护线程,专门用于服务其他的线程,如果其他的线程(即用户自定义线程)都执行完毕,连main线程也执行完毕,那么jvm就会退出(即停止运行)——此时,连jvm都停止运行了,守护线程当然也就停止执行了。

2、再换一种说法,如果有用户自定义线程存在的话,jvm就不会退出——此时,守护线程也不能退出,也就是它还要运行,干嘛呢,就是为了执行垃圾回收的任务啊

4、创建线程有几种方式?

通过实现Runnable接口来创建Thread线程

通过实现Callable接口来创建Thread线程

通过继承Thread类来创建一个线程

使用Executor框架来创建线程池

5、runnable 和 callable 的区别

Runnable没有返回值;Callable可以返回执行结果,是个泛型,和Future、FutureTask配合可以用来获取异步执行的结果

Callable接口的call()方法允许抛出异常;Runnable的run()方法异常只能在内部消化,不能往上继续抛

6、线程有哪些状态

新建状态、先创建出来的线程

就绪状态、调用线程的 start 方法

运行状态、当线程获得 cpu 时间时

阻塞状态、调用 sleep 方法、等待锁的时候

死亡状态、run方法正常退出而自然死亡;一个未捕获的异常终止了run方法而使线程猝死

7、sllep()  和  wait()  区别

sleep()方法正在执行的线程主动让出CPU(然后CPU就可以去执行其他任务),在sleep指定时间后CPU再回到该线程继续往下执行(注意:sleep方法只让出了CPU,而并不会释放同步资源锁!!!);

wait()方法则是指当前线程让自己暂时退让出同步资源锁,以便其他正在等待该资源的线程得到该资源进而运行,只有调用了notify()方法,之前调用wait()的线程才会解除wait状态,可以去参与竞争同步资源锁,进而得到执行。

8、notify() 和 notifyall() 区别?

9、run() 和 start() 的区别

start() :

它的作用是启动一个新线程。

通过start()方法来启动的新线程,处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行相应线程的run()方法,这里方法run()称为线程体,它包含了要执行的这个线程的内容,run方法运行结束,此线程随即终止。start()不能被重复调用。用start方法来启动线程,真正实现了多线程运行,即无需等待某个线程的run方法体代码执行完毕就直接继续执行下面的代码。这里无需等待run方法执行完毕,即可继续执行下面的代码,即进行了线程切换。

run() :

run()就和普通的成员方法一样,可以被重复调用。

如果直接调用run方法,并不会启动新线程!程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到多线程的目的。

总结:调用start方法方可启动线程,而run方法只是thread的一个普通方法调用,还是在主线程里执行。

10、创建线程池有哪几种方式?

package com.thread;
 
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
 
/*  
 * Java通过Executors提供四种线程池,分别为:
 * newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
 * newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
 * newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
 * newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。	
 */
public class ThreadPool {
 
	public static void main(String[] args) {
		// 线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
		// 这里如果去除sleep,则你会发现在这个循环中创建了新的线程,因为前一个任务没有执行完,所以创建新线程执行下一个任务。
		ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
		for (int i = 0; i < 10; i++) {
			final int index = i;
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			newCachedThreadPool.execute(new Runnable() {
				public void run() {
					System.out.println(Thread.currentThread().getName() + "----" + index);
				}
			});
		}
		// ---------------------------------------------------------------------------------------------------
		// 创建一个定长的线程池,也是根据需要去调用线程,比如线程定为100个,而循环只有10个,那么也只会用到前10个进程。
		ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(100);
		for (int i = 0; i < 10; i++) {
			final int index = i;
			newFixedThreadPool.execute(new Runnable() {
				public void run() {
					// Thread.sleep(1000);
					System.out.println(Thread.currentThread().getName() + "----" + index);
				}
			});
		}
		// ---------------------------------------------------------------------------------------------------
		// 创建一个定长线程池,支持定时及周期性任务执行。
		ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(5);
		for (int i = 0; i < 10; i++) {
			newScheduledThreadPool.schedule(new Runnable() {
				public void run() {
					System.out.println(Thread.currentThread().getName() + "----delay 3 seconds");
				}
			}, 3, TimeUnit.SECONDS);
		}
		// ---------------------------------------------------------------------------------------------------
		// 按顺序来执行线程任务 但是不同于单线程,这个线程池只是只能存在一个线程,这个线程死后另外一个线程会补上。
		ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
		for (int i = 0; i < 10; i++) {
			final int index = i;
			newSingleThreadExecutor.execute(new Runnable() {
				public void run() {
					System.out.println(Thread.currentThread().getName() + "----" + index);
				}
			});
		}
	}
}
           

11、线程池都有哪些状态?

12、线程池中 submit()和 execute()方法有什么区别?

13、在 java 程序中怎么保证多线程的运行安全?

14、多线程锁的升级原理是什么?

15、什么是死锁?

死锁是指多个进程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。例如,在某一个计算机系统中只有一台打印机和一台输入 设备,进程P1正占用输入设备,同时又提出使用打印机的请求,但此时打印机正被进程P2 所占用,而P2在未释放打印机之前,又提出请求使用正被P1占用着的输入设备。这样两个进程相互无休止地等待下去,均无法继续执行,此时两个进程陷入死锁状态

16、怎么防止死锁?

17、ThreadLocal 是什么?有哪些使用场景?

18、说一下 synchronized 底层实现原理?

19、synchronized 和 volatile 的区别是什么?

20、synchronized 和 Lock 有什么区别?

1.首先synchronized是java内置关键字,在jvm层面,Lock是个java类;

2.synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁;

3.synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程中发生异常会释放锁),Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁;

4.用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2线程等待。如果线程1阻塞,线程2则会一直等待下去,而Lock锁就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就结束了;

5.synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可判断、可公平(两者皆可)

6.Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题

21、synchronized 和 ReentrantLock 区别是什么?

22、 说一下 atomic 的原理?

三、Java Web

1、jsp 和 servlet 有什么区别?

1.jsp经编译后就变成了Servlet.(JSP的本质就是Servlet,JVM只能识别java的类,不能识别JSP的代码,Web容器将JSP的代码编译成JVM能够识别的java类)

2.jsp更擅长表现于页面显示,servlet更擅长于逻辑控制.

3.Servlet中没有内置对象,Jsp中的内置对象都是必须通过HttpServletRequest对象,HttpServletResponse对象以及HttpServlet对象得到.

Jsp是Servlet的一种简化,使用Jsp只需要完成程序员需要输出到客户端的内容,Jsp中的Java脚本如何镶嵌到一个类中,由Jsp容器完成。而Servlet则是个完整的Java类,这个类的Service方法用于生成对客户端的响应。

联系: JSP是Servlet技术的扩展,本质上就是Servlet的简易方式。JSP编译后是“类servlet”。Servlet和JSP最主要的不同点在于,Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件。JSP侧重于视图,Servlet主要用于控制逻辑

2、 jsp 有哪些内置对象?作用分别是什么?

Page,pageContext,request,response,session,application,out,config,exception

3、 说一下 jsp 的 4 种作用域?

这四大作用域,其实就是其九大内置对象中的四个,为什么说他们也是JSP的四大作用域呢?因为这四个对象都能存储数据

page作用域:代表变量只能在当前页面上生效

request:代表变量能在一次请求中生效,一次请求可能包含一个页面,也可能包含多个页面,比如页面A请求转发到页面B

session:代表变量能在一次会话中生效,基本上就是能在web项目下都有效,session的使用也跟cookie有很大的关系。一般来说,只要浏览器不关闭,cookie就会一直生效,cookie生效,session的使用就不会受到影响。

application:代表变量能一个应用下(多个会话),在服务器下的多个项目之间都能够使用。比如baidu、wenku等共享帐号。

4、request.setAttribute()  和  request.setParameter()

首先,没有setParameter方法,只有getParameter,所以一般只区分getAttribute和getParameter的区别。

getAttribute表示从request范围取得设置的属性,必须要先setAttribute设置属性,才能通过getAttribute来取得,设置与取得的为Object对象类型

getParameter表示接收参数,参数为页面提交的参数,包括:表单提交的参数、url重写(就是xxx?id=1中的id)传的参数等,因此这个并没有设置参数的方法(没有setParameter),而且接收参数返回的不是Object,而是String类型

5、session 和 cookie 有什么区别?

1、cookie数据存放在客户的浏览器上,session数据放在服务器上。

2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗

   考虑到安全应当使用session。

3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能

   考虑到减轻服务器性能方面,应当使用COOKIE。

4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

6、说一下 session 的工作原理?

在用户1和用户2登录的时候,我们的服务器在他们登录成功后,在session表中为他们每个用户分配了一个sessionid并且存下了一个对应的信息。当用户第二次访问该服务器的时候,会将sessionid在request请求中携带者发送过去。这时我们的服务器就可以根据sessionid确定用户存储的数据,然后进行使用。

当session超过一定时间(一般为30分钟)没有被访问时,服务器就会认为这个session对应的客户端已经停止活动,然后将这个session删除。用以节省空间。

当用户关闭浏览器时,sessionId的信息会丢失,虽然服务器session还在,依然无法访问到session中的数据。

7、如果客户端禁止 cookie 能实现 session 还能用吗?

http请求是无状态的。。假如你是浏览器,我是服务器,那么类似你知道我的电话号码,可以给我打电话,但是我不知道你的电话号码,我想和你说话只能等你跟我打。。

那么问题来了,如果你想让我相信你就是昨天给我打电话的那个人必须借助一个新的东西,比如你给我打电话的时候我给你一串数字,你下次打给我告诉我这串数字我就知道你是谁了,这串数字在我这里存的就叫session(可以简单这么理解),你自己也存了一份,那份叫cookie。你以后给我打电话顺便把这个cookie给我就可以了。这个就是session和cookie的原理。

所以了,假如你要禁用cookie,通过cookie把那串数字给我就不行了。那你也可以把这串数字放在url后面给我,或者放到form表单里给我,那也是可以的。

8、spring mvc 和 struts 的区别是什么?

9、 如何避免 sql 注入?

10、什么是 XSS 攻击,如何避免?

11、什么是 CSRF 攻击,如何避免?

参考:

版权声明:本文为CSDN博主「weixin_42832953」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/weixin_42832953/article/details/89818274

继续阅读