【最新】经典面试100问,附答案

本文由公众号「字节传说」整理,设计到的内容由java基础、数据库、SSM框架、redis、消息队列、spring boot、spring cloud、git及一些前端知识。整理时间为2019-11-19,首发于微信公众号「字节传说」,关注微信公众号「字节传说」,回复面试领取该pdf版资料。公众号二维码以下:html

byte.jpg

2019年java面试经典100问,进入BAT不是梦。若是该pdf帮助到您,请您传阅给您的小伙伴,一块儿复习,共同作一个offer收割机,文章目录以下:前端

1、java基础

一、面向对象的特征有哪些方面? 【基础】java

答:面向对象的特征主要有如下几个方面:mysql

1)抽象:抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解所有问题,而只是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。nginx

2)继承:继承是一种联结类的层次模型,而且容许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类能够从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类能够从它的基类那里继承方法和实例变量,而且类能够修改或增长新的方法使之更适合特殊的须要。git

3)封装:封装是把过程和数据包围起来,对数据的访问只能经过已定义的界面。面向对象计算始于这个基本概念,即现实世界能够被描绘成一系列彻底自治、封装的对象,这些对象经过一个受保护的接口访问其余对象。程序员

4)多态性:多态性是指容许不一样类的对象对同一消息做出响应。多态性包括参数化多态性和包含多态性。多态性语言具备灵活、抽象、行为共享、代码共享的优点,很好的解决了应用程序函数同名问题。面试

二、int 和Integer 有什么区别? 【基础】正则表达式

答:Java 提供两种不一样的类型:引用类型和原始类型(或内置类型);

int 是java 的原始数据类型,Integer 是java 为int 提供的封装类。

Java 为每一个原始类型提供了封装类:

原始类型: boolean,char,byte,short,int,long,float,double

封装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double引用类型和原始类型的行为彻底不一样,而且它们具备不一样的语义。引用类型和原始类型具备不一样的特征和用法,它们包括:大小和速度问题,这种类型以哪一种类型的数据结构存储,当引用类型和原始类型用做某个类的实例数据时所指定的缺省值。对象引用实例变量的缺省值为null,而原始类型实例变量的缺省值与它们的类型有关。

三、Math.round(11.5) 等于多少? Math.round(-11.5)等于多少? 【基础】

答:Math.round(11.5)==12 Math.round(-11.5)==-11 round 方法返回与参数最接近的长整数,参数加1/2 后求其floor。

四、编程题: 用最有效率的方法算出2 乘以8 等於几? 【基础】

答: 2 << 3。

五、数组有没有 length()方法?String 有没有 length()方法?【基础】

答:数组没有 length()方法,有 length 的属性。String 有 length()方法。JavaScript 中,得到字符串的长度是经过 length 属性获得的,这一点容易和 Java 混淆。

六、构造器(constructor)是否可被重写(override)?【基础】

答:构造器不能被继承,所以不能被重写,但能够被重载。

七、是否能够继承String 类? 【基础】

答:String 类是final 类,故不能够继承。

八、当一个对象被看成参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里究竟是值传递仍是引用传递? 【基础】

答:是值传递。Java 编程语言只有值传递参数。当一个对象实例做为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的内容能够在被调用的方法中改变,但对象的引用是永远不会改变的。

九、String 和StringBuffer 的区别?【基础】

答:JAVA 平台提供了两个类:String 和StringBuffer,它们能够储存和操做字符串,即包含多个字符的字符数据。这个String 类提供了数值不可改变的字符串。而这个StringBuffer 类提供的字符串进行修改。当你知道字符数据要改变的时候你就能够使用StringBuffer。典型地,你能够使用StringBuffers 来动态构造字符数据。

十、String, StringBuffer StringBuilder 的区别。【基础】

答:String 的长度是不可变的;StringBuffer 的长度是可变的,若是你对字符串中的内容常常进行操做,特别是内容要修改时,那么使用StringBuffer.若是最后须要String,那么使用StringBuffer 的toString()方法,线程安全;StringBuilder 是从JDK 5 开始,为StringBuffer 该类补充了一个单个线程使用的等价类;一般应该优先使用StringBuilder 类,由于它支持全部相同的操做,但因为它不执行同步,因此速度更快,线程不安全。

十一、重载(Overload)和重写(Override)的区别。重载的方法可否根据返回类型进行区分?【基础】

答:方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,然后者实现的是运行时的多态性。重载发生在一个类中,同名的方法若是有不一样的参数列表(参数类型不一样、参数个数不一样或者两者都不一样)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求。

十二、描述一下 JVM 加载 class 文件的原理机制?【中等】

答:JVM 中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java 中的类加载器是一个重要的 Java 运行时系统组件,它负责在运行时查找和装入类文件中的类。

因为 Java 的跨平台性,通过编译的 Java 源程序并非一个可执行程序,而是一个或多个类文件。当 Java 程序须要使用某个类时,JVM 会确保这个类已经被加载、链接(验证、准备和解析)和初始化。类的加载是指把类的.class 文件中的数据读入到内存中,一般是建立一个字节数组读入.class 文件,而后产生与所加载类对应的 Class 对象。加载完成后,Class 对象还不完整,因此此时的类还不可用。当类被加载后就进入链接阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认的初始值)和解析(将符号引用替换为直接引用)三个步骤。最后 JVM 对类进行初始化,包括:

1)若是类存在直接的父类而且这个类尚未被初始化,那么就先初始化父类;

2)若是类中存在初始化语句,就依次执行这些初始化语句。

从 Java 2(JDK 1.2)开始,类加载过程采起了双亲委托机制(PDM)。PDM 更好的保证了 Java 平台的安全性,在该机制中,JVM 自带的 Bootstrap 是根加载器,其余的加载器都有且仅有一个父类加载器。类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加载。

1三、interface能够有方法的实现吗?【中等】

答:jdk1.8之后有方法的实现,用default修饰。

1四、是否能够从一个static 方法内部发出对非static 方法的调用?【基础】

答:不能够,若是其中包含对象的method(),不能保证对象初始化。

1五、GC 是什么? 为何要有GC? 【基础】

答:GC 是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会致使程序或系统的不稳定甚至崩溃,Java 提供的GC 功能能够自动监测对象是否超过做用域从而达到自动回收内存的目的,Java 语言没有提供释放已分配内存的显示操做方法。Java 程序员不用担忧内存管理,由于垃圾收集器会自动进行管理。要请求垃圾收集,能够调用下面的方法之一:System.gc() 或Runtime.getRuntime().gc()

1六、垃圾回收器的基本原理是什么?垃圾回收器能够立刻回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?【基础】

答:对于GC 来讲,当程序员建立对象时,GC 就开始监控这个对象的地址、大小以及使用状况。一般,GC 采用有向图的方式记录和管理堆(heap)中的全部对象。经过这种方式肯定哪些对象是"可达的",哪些对象是"不可达的"。当GC 肯定一些对象为"不可达"时,GC 就有责任回收这些内存空间。能够。程序员能够手动执行System.gc(),通知GC 运行,可是Java 语言规范并不保证GC 必定会执行。

1七、一个“.java”源文件中是否能够包含多个类(不是内部类)?有什么限制?【基础】

答:能够;必须只有一个类名与文件名相同。

1八、Java 中的 final 关键字有哪些用法?【基础】

答:(1)修饰类:表示该类不能被继承;(2)修饰方法:表示方法不能被重写;(3)修饰变量:表示变量只能一次赋值之后值不能被修改(常量)。

1九、编码转换:怎样将GB2312 编码的字符串转换为ISO-8859-1 编码的字符串?【基础】

答:示例代码以下:

String s1 = "你好";

String s2 = new String(s1.getBytes("GB2312"), "ISO-8859-1");

20、error 和exception 有什么区别? 【基础】

答:error 表示系统级的错误和程序没必要处理的异常,是恢复不是不可能但很困难的状况下的一种严重问题;好比内存溢出,不可能期望程序能处理这样的状况;exception 表示须要捕捉或者须要程序进行处理的异常,是一种设计或实现问题;也就是说,它表示若是程序运行正常,从不会发生的状况。

2一、try{}里有一个return语句,那么紧跟在这个try后的finally{}里的代码会不会被执行,何时被执行,在return前仍是后?【基础】

答:会执行,在方法返回调用者前执行。

注意:在finally中改变返回值的作法是很差的,由于若是存在finally代码块,try中的return语句不会立马返回调用者,而是记录下返回值待finally代码块执行完毕以后再向调用者返回其值,而后若是在finally中修改了返回值,就会返回修改后的值。显然,在finally中返回或者修改返回值会对程序形成很大的困扰,C#中直接用编译错误的方式来阻止程序员干这种龌龊的事情,Java中也能够经过提高编译器的语法检查级别来产生警告或错误,Eclipse中能够在如图所示的地方进行设置,强烈建议将此项设置为编译错误。

2二、List,Set,Map 是否继承自Collection 接口?【基础】

答:List,Set 是;Map 不是。

2三、说出ArrayList,Vector, LinkedList 的存储性能和特性?【基础】

答:ArrayList 和Vector 都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增长和插入元素,它们都容许直接按序号索引元素,可是插入元素要涉及数组元素移动等内存操做,因此索引数据快而插入数据慢,Vector 因为使用了synchronized 方法(线程安全),一般性能上较ArrayList 差,而LinkedList 使用双向链表实现存储,按序号索引数据须要进行前向或后向遍历,可是插入数据时只须要记录本项的先后项便可,因此插入速度较快。

2四、HashMap 和Hashtable 的区别? 【基础】

答:两者都实现了Map 接口,是将唯一键映射到特定的值上;主要区别在于:

1)HashMap 没有排序,容许一个null 键和多个null 值,而Hashtable 不容许;

2)HashMap 把Hashtable 的contains 方法去掉了,改为containsvalue 和containsKey,由于contains 方法容易让人引发误解;

3)Hashtable 继承自Dictionary 类,HashMap 是Java1.2 引进的Map 接口的实现;

4)Hashtable 的方法是Synchronize 的,而HashMap 不是,在多个线程访问Hashtable 时,不须要本身为它的方法实现同步,而HashMap 就必须为之提供外同步。Hashtable 和HashMap 采用的hash/rehash 算法大体同样,因此性能不会有很大的差别。

2五、Arraylist 与Vector 区别?【基础】

答:就ArrayList 与Vector 主要从二方面来讲:

1)同步性:Vector 是线程安全的(同步),而ArrayList 是线程序不安全的;

2)数据增加:当须要增加时,Vector 默认增加一倍,而ArrayList 倒是一半。

2六、List、Map、Set 三个接口,存取元素时,各有什么特色?【基础】

答:List 以特定次序来持有元素,可有重复元素。Set 没法拥有重复元素,内部排序。Map 保存key-value 值,value 可多值。

2七、sleep() 和wait() 有什么区别? 【基础】

答:sleep 是线程类(Thread)的方法,致使此线程暂停执行指定时间,给执行机会给其余线程,可是监控状态依然保持,到时后会自动恢复。调用sleep 不会释放对象锁。wait 是Object 类的方法,对此对象调用wait 方法致使本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify 方法(或notifyAll)后本线程才进入对象锁定池准备得到对象锁进入运行状态。

2八、当一个线程进入一个对象的一个synchronized 方法后,其它线程是否可进入此对象的其它方法? 【基础】

答:其它线程只能访问该对象的其它非同步方法,同步方法则不能进入。

2九、多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么? 【基础】

答:多线程有两种实现方法,分别是继承Thread 类与实现Runnable 接口,同步的实现方面有两种,分别是synchronized,wait 与notify。

30、当一个线程进入一个对象的 synchronized 方法 A 以后,其它线程是否可进入此对象的 synchronized 方法 B?【中等】

答:不能。其它线程只能访问该对象的非同步方法,同步方法则不能进入。由于非静态方法上的 synchronized 修饰符要求执行方法时要得到对象的锁,若是已经进入 A 方法说明对象锁已经被取走,那么试图进入 B 方法的线程就只能在等锁池(注意不是等待池哦)中等待对象的锁

3一、简述synchronized 和java.util.concurrent.locks.Lock 的异同?【中等】

答:主要相同点:Lock 能完成synchronized 所实现的全部功能;主要不一样点:Lock 有比synchronized 更精确的线程语义和更好的性能。synchronized 会自动释放锁,而Lock 必定要求程序员手工释放,而且必须在finally 从句中释放。

3二、编写多线程程序有几种实现方式?【中等】

答:Java 5 之前实现多线程有两种实现方法:一种是继承 Thread 类;另外一种是实现 Runnable 接口。两种方式都要经过重写 run()方法来定义线程的行为,推荐使用后者,由于 Java 中的继承是单继承,一个类有一个父类,若是继承了 Thread 类就没法再继承其余类了,显然使用 Runnable 接口更为灵活。

补充:Java 5 之后建立线程还有第三种方式:实现 Callable 接口,该接口中的 call 方法能够在线程执行结束时产生一个返回值,代码以下所示:

import java.util.ArrayList;

import java.util.List;
import java.util.concurrent.Callable;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import java.util.concurrent.Future;


class MyTask implements Callable<Integer> {

    private int upperBounds;

    public MyTask(int upperBounds) {
    
        this.upperBounds = upperBounds;
    }

    @Override

    public Integer call() throws Exception {
      int sum = 0;

        for(int i = 1; i <= upperBounds; i++) {

            sum += i;
        }

    return sum;

    }

}

class Test {

    public static void main(String[] args) throws Exception { 
    List<Future<Integer>> list = new ArrayList<>(); 
    ExecutorService service = Executors.newFixedThreadPool(10);

    for(int i = 0; i < 10; i++) {

        list.add(service.submit(new MyTask((int) (Math.random() * 100))));
    }

    int sum = 0;

    for(Future<Integer> future : list) {

        //while(!future.isDone()) ; 
        sum += future.get();

    }

    System.out.println(sum);

    }
}

3三、Java 中如何实现序列化,有什么意义?【中等】

答:序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。能够对流化后的对象进行读写操做,也可将流化后的对象传输于网络之间。序列化是为了解决对象流读写操做时可能引起的问题(若是不进行序列化可能会存在数据乱序的问题)。要实现序列化,须要让一个类实现 Serializable 接口,该接口是一个标识性接口,标注该类对象是可被序列化的,而后使用一个输出流来构造一个对象输出流并经过 writeObject(Object)方法就能够将实现对象写出(即保存其状态);若是须要反序列化则能够用一个输入流创建对象输入流,而后经过 readObject 方法从流中读取对象。

2、数据库

3四、阐述 JDBC 操做数据库的步骤。【基础】

答:下面的代码以链接本机的 Oracle 数据库为例,演示 JDBC 操做数据库的步骤。

//加载驱动。
Class.forName("oracle.jdbc.driver.OracleDriver");

//建立链接。
Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "tiger");

//建立语句。
PreparedStatement ps = con.prepareStatement("select * from emp where sal between ? and ?"); ps.setInt(1, 1000);

ps.setInt(2, 3000);

//执行语句。
ResultSet rs = ps.executeQuery();

//处理结果。
while(rs.next()) {
    System.out.println(rs.getInt("empno") + " - " + rs.getString("ename"));
}

//关闭资源。
finally {
    if(con != null) {
        try {
            con.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

提示:关闭外部资源的顺序应该和打开的顺序相反,也就是说先关闭 ResultSet、再关闭Statement、在关闭 Connection。上面的代码只关闭了 Connection(链接),虽然一般状况下在关闭链接时,链接上建立的语句和打开的游标也会关闭,但不能保证老是如此,所以应该按照刚才说的顺序分别关闭。此外,第一步加载驱动在 JDBC 4.0 中是能够省略的(自动从类路径中加载驱动),可是咱们建议保留。

3五、使用 JDBC 操做数据库时,如何提高读取数据的性能?如何提高更新数据的性能?【中等】

答:要提高读取数据的性能,能够指定经过结果集(ResultSet)对象的 setFetchSize()方法指定每次抓取的记录数(典型的空间换时间策略);要提高更新数据的性能能够使用 PreparedStatement 语句构建批处理,将若干 SQL 语句置于一个批处理中执行。

3六、在进行数据库编程时,链接池有什么做用?【基础】

答:因为建立链接和释放链接都有很大的开销(尤为是数据库服务器不在本地时,每次创建链接都须要进行 TCP 的三次握手,释放链接须要进行 TCP 四次握手,形成的开销是不可忽视的),为了提高系统访问数据库的性能,能够事先建立若干链接置于链接池中,须要时直接从链接池获取,使用结束时归还链接池而没必要关闭链接,从而避免频繁建立和释放链接所形成的开销,这是典型的用空间换取时间的策略(浪费了空间存储链接,但节省了建立和释放链接的时间)。池化技术在 Java 开发中是很常见的,在使用线程时建立线程池的道理与此相同。基于 Java 的开源数据库链接池主要有:C3P0、Proxool、DBCP、BoneCP、Druid 等。

3七、事务的ACID是指什么?【基础】

答:

  • 原子性(Atomic):事务中各项操做,要么全作要么全不作,任何一项操做的失败都会致使整个事务的失败;

  • 一致性(Consistent):事务结束后系统状态是一致的;

  • 隔离性(Isolated):并发执行的事务彼此没法看到对方的中间状态;
  • 持久性(Durable):事务完成后所作的改动都会被持久化,即便发生灾难性的失败。经过日志和同步备份能够在故障发生后重建数据。

3八、谈谈脏读、幻读和不可重复读?【中等】

脏读(Dirty Read):A 事务读取 B 事务还没有提交的数据并在此基础上操做,而 B 事务执行回滚,那么 A 读取到的数据就是脏数据。

时间转帐事务 A 取款事务 B
T1 开始事务
T2 开始事务
T3 查询帐户余额为 1000 元
T4 取出 500 元余额修改成 500
T5 查询帐户余额为 500 元(脏读)
T6 撤销事务余额恢复为 1000 元
T7 汇入 100 元把余额修改成 600 元
T8 提交事务

不可重复读(Unrepeatable Read):事务 A 从新读取前面读取过的数据,发现该数据已经被另外一个已提交的事务 B 修改过了。

时间转帐事务 A 取款事务 B
T1 开始事务
T2 开始事务
T3 查询帐户余额为 1000 元
T4 查询帐户余额为 1000 元
T5 取出 100 元修改余额为 900 元
T6 提交事务
T7 查询帐户余额为 900 元(不可重复读)

幻读(Phantom Read):事务 A 从新执行一个查询,返回一系列符合查询条件的行,发现其中插入了被事务 B 提交的行。

时间统计金额事务 A 转帐事务 B
T1 开始事务
T2 开始事务
T3 统计总存款为 10000 元
T4 新增一个存款帐户存入 100 元
T5 提交事务
T6 再次统计总存款为 10100 元(幻读)

第 1 类丢失更新:事务 A 撤销时,把已经提交的事务 B 的更新数据覆盖了。

时间取款事务 A 转帐事务 B

时间取款事务 A 转帐事务 B
T1 开始事务
T2 开始事务
T3 查询帐户余额为 1000 元
T4 查询帐户余额为 1000 元
T5 汇入 100 元修改余额为 1100 元
T6 提交事务
T7 取出 100 元将余额修改成 900 元
T8 撤销事务
T9 余额恢复为 1000 元(丢失更新)
第 2 类丢失更新:事务 A 覆盖事务 B 已经提交的数据,形成事务 B 所作的操做丢失。
时间转帐事务 A 取款事务 B
T1 开始事务
T2 开始事务
T3 查询帐户余额为 1000 元
T4 查询帐户余额为 1000 元
T5 取出 100 元将余额修改成 900 元
T6 提交事务
T7 汇入 100 元将余额修改成 1100 元
T8 提交事务
T9 查询帐户余额为 1100 元(丢失更新)

数据并发访问所产生的问题,在有些场景下多是容许的,可是有些场景下可能就是致命的,数据库一般会经过锁机制来解决数据并发访问问题,按锁定对象不一样能够分为表级锁和行级锁;按并发事务锁定关系能够分为共享锁和独占锁,具体的内容你们能够自行查阅资料进行了解。直接使用锁是很是麻烦的,为此数据库为用户提供了自动锁机制,只要用户指定会话的事务隔离级别,数据库就会经过分析 SQL 语句而后为事务访问的资源加上合适的锁,此外,数据库还会维护这些锁经过各类手段提升系统的性能,这些对用户来讲都是透明的(就是说你不用理解,事实上我确实也不知道)。

ANSI/ISO SQL 92 标准定义了4 个等级的事务隔离级别,以下表所示:

隔离级别 脏读 不可重复读幻读 第一类丢失更新第二类丢失更新
READ UNCOMMITED 容许 容许 容许 不容许 容许
READ COMMITTED 不容许 容许 容许 不容许 容许
REPEATABLE READ 不容许 不容许 容许 不容许 不容许
SERIALIZABLE 不容许 不容许 不容许 不容许 不容许

须要说明的是,事务隔离级别和数据访问的并发性是对立的,事务隔离级别越高并发性就越差。因此要根据具体的应用来肯定合适的事务隔离级别,这个世界没有万能的原则。

3九、JDBC中如何进行事务处理?【中等】

答:Connection 提供了事务处理的方法,经过调用setAutoCommit(false)能够设置手动提交事务;当事务完成后用 commit()显式提交事务;若是在事务处理过程当中发生异常则经过 rollback()进行事务回滚。除此以外,从 JDBC 3.0 中还引入了 Savepoint(保存点)的概念,容许经过代码设置保存点并让事务回滚到指定的保存点。

40、得到一个类的类对象有哪些方式?【基础】

答:

  • 方法 1:类型.class,例如:String.class

  • 方法 2:对象.getClass(),例如:"hello".getClass()

  • 方法 3:Class.forName(),例如:Class.forName("java.lang.String")

4一、JSP 有哪些内置对象?做用分别是什么?【基础】

答:JSP 有 9 个内置对象:

  • request:封装客户端的请求,其中包含来自 GET 或 POST 请求的参数;

  • response:封装服务器对客户端的响应;

  • pageContext:经过该对象能够获取其余对象;

  • session:封装用户会话的对象;

  • application:封装服务器运行环境的对象;

  • out:输出服务器响应的输出流对象;

  • config:Web 应用的配置对象;

  • page:JSP 页面自己(至关于 Java 程序中的 this);

  • exception:封装页面抛出异常的对象。

4二、get 和 post 请求的区别?【基础】

答:①get 请求用来从服务器上得到资源,而 post 是用来向服务器提交数据;

②get 将表单中数据按照 name=value 的形式,添加到 action 所指向的 URL 后面,而且二者使用"?"链接,而各个变量之间使用"&"链接;post 是将表单中的数据放在 HTTP 协议的请求头或消息体中,传递到 action 所指向 URL;

③get 传输的数据要受到 URL 长度限制(1024 字节);而 post 能够传输大量的数据,上传文件一般要使用 post 方式;

④使用 get 时参数会显示在地址栏上,若是这些数据不是敏感数据,那么能够使用 get;对于敏感数据仍是应用使用 post;

⑤get 使用 MIME 类型 application/x-www-form-urlencoded 的 URL 编码(也叫百分号编码)

文本的格式传递参数,保证被传送的参数由遵循规范的文本组成,例如一个空格的编码是"%20"。

4三、讲解 JSP 中的四种做用域。【基础】

答:JSP 中的四种做用域包括 page、request、session 和 application,具体来讲:

  • page 表明与一个页面相关的对象和属性。

  • request 表明与 Web 客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个 Web 组件;须要在页面显示的临时数据能够置于此做用域。

  • session 表明与某个用户与服务器创建的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户本身的 session 中。

  • application 表明与整个 Web 应用程序相关的对象和属性,它实质上是跨越整个 Web 应用程序,包括多个页面、请求和会话的一个全局做用域。

3、SSM框架

4四、MyBatis 中使用#和$书写占位符有什么区别?【中等】

答:#将传入的数据都当成一个字符串,会对传入的数据自动加上引号;$将传入的数据直接显示生成在 SQL 中。注意:使用$占位符可能会致使 SQL 注射攻击,能用#的地方就不要使用$,写 order by 子句的时候应该用$而不是#。

4五、解释一下 MyBatis 中命名空间(namespace)的做用。【中等】

答:在大型项目中,可能存在大量的 SQL 语句,这时候为每一个 SQL 语句起一个惟一的标识(ID)就变得并不容易了。为了解决这个问题,在 MyBatis 中,能够为每一个映射文件起一个惟一的命名空间,这样定义在这个映射文件中的每一个 SQL 语句就成了定义在这个命名空间中的一个 ID。只要咱们可以保证每一个命名空间中这个 ID 是惟一的,即便在不一样映射文件中的语句 ID 相同,也不会再产生冲突了。

4六、什么是 IoC 和 DI?DI 是如何实现的?【中等】

答:IoC 叫控制反转,是 Inversion of Control 的缩写,DI(Dependency Injection)叫依赖注入,是对 IoC 更简单的诠释。控制反转是把传统上由程序代码直接操控的对象的调用权交给容器,经过容器来实现对象组件的装配和管理。所谓的"控制反转"就是对组件对象控制权的转移,从程序代码自己转移到了外部容器,由容器来建立对象并管理对象之间的依赖关系。IoC 体现了好莱坞原则 - "Don’t call me, we will call you"。依赖注入的基本原则是应用组件不该该负责查找资源或者其余依赖的协做对象。配置对象的工做应该由容器负责,查找资源的逻辑应该从应用组件的代码中抽取出来,交给容器来完成。DI 是对 IoC 更准确的描述,即组件之间的依赖关系由容器在运行期决定,形象的来讲,即由容器动态的将某种依赖关系注入到组件之中。

4七、解释一下什么叫 AOP(面向切面编程)?【基础】

答:AOP(Aspect-Oriented Programming)指一种程序设计范型,该范型以一种称为切面(aspect)的语言构造为基础,切面是一种新的模块化机制,用来描述分散在对象、类或方法中的横切关注点(crosscutting concern)。

4八、你是如何理解"横切关注"这个概念的?【中等】

答:"横切关注"是会影响到整个应用程序的关注功能,它跟正常的业务逻辑是正交的,没有必然的联系,可是几乎全部的业务逻辑都会涉及到这些关注功能。一般,事务、日志、安全性等关注就是应用中的横切关注功能。

4九、你如何理解 AOP 中的链接点(Joinpoint)、切点(Pointcut)、加强(Advice)、引介(Introduction)、织入(Weaving)、切面(Aspect)这些概念?【基础】

答:a. 链接点(Joinpoint):程序执行的某个特定位置(如:某个方法调用前、调用后,方法抛出异常后)。一个类或一段程序代码拥有一些具备边界性质的特定点,这些代码中的特定点就是链接点。Spring 仅支持方法的链接点。

b. 切点(Pointcut):若是链接点至关于数据中的记录,那么切点至关于查询条件,一个切点能够匹配多个链接点。Spring AOP 的规则解析引擎负责解析切点所设定的查询条件,找到对应的链接点。

c. 加强(Advice):加强是织入到目标类链接点上的一段程序代码。Spring 提供的加强接口都是带方位名的,如:BeforeAdvice、AfterReturningAdvice、ThrowsAdvice 等。不少资料上将加强译为“通知”,这明显是个词不达意的翻译,让不少程序员困惑了许久。

说明: Advice 在国内的不少书面资料中都被翻译成"通知",可是很显然这个翻译没法表达其本质,有少许的读物上将这个词翻译为"加强",这个翻译是对 Advice 较为准确的诠释,咱们经过 AOP 将横切关注功能加到原有的业务逻辑上,这就是对原有业务逻辑的一种加强,这种加强能够是前置加强、后置加强、返回后加强、抛异常时加强和包围型加强。

d. 引介(Introduction):引介是一种特殊的加强,它为类添加一些属性和方法。这样,即便一个业务类本来没有实现某个接口,经过引介功能,能够动态的未该业务类添加接口的实现逻辑,让业务类成为这个接口的实现类。

e. 织入(Weaving):织入是将加强添加到目标类具体链接点上的过程,AOP 有三种织入方式:①编译期织入:须要特殊的 Java 编译期(例如 AspectJ 的 ajc);②装载期织入:要求使用特殊的类加载器,在装载类的时候对类进行加强;③运行时织入:在运行时为目标类生成代理实现加强。Spring 采用了动态代理的方式实现了运行时织入,而 AspectJ 采用了编译期织入和装载期织入的方式。

f. 切面(Aspect):切面是由切点和加强(引介)组成的,它包括了对横切关注功能的定义,也包括了对链接点的定义。

50、Spring 支持的事务管理类型有哪些?你在项目中使用哪一种方式?【中等】

答:Spring 支持编程式事务管理和声明式事务管理。许多 Spring 框架的用户选择声明式事务管理,由于这种方式和应用程序的关联较少,所以更加符合轻量级容器的概念。声明式事务管理要优于编程式事务管理,尽管在灵活性方面它弱于编程式事务管理,由于编程式事务容许你经过代码控制业务。

5一、Spring MVC的工做原理是怎样的?【基础】

答:SpringMVC工做原理图以下:

① 客户端的全部请求都交给前端控制器 DispatcherServlet 来处理,它会负责调用系统的其余模块来真正处理用户的请求。

② DispatcherServlet 收到请求后,将根据请求的信息(包括 URL、HTTP 协议方法、请求头、请求参数、Cookie 等)以及 HandlerMapping 的配置找处处理该请求的 Handler(任何一个对象均可以做为请求的 Handler)。

③在这个地方 Spring 会经过 HandlerAdapter 对该处理器进行封装。

④ HandlerAdapter 是一个适配器,它用统一的接口对各类 Handler 中的方法进行调用。

⑤ Handler 完成对用户请求的处理后,会返回一个 ModelAndView 对象给 DispatcherServlet, ModelAndView 顾名思义,包含了数据模型以及相应的视图的信息。

⑥ ModelAndView 的视图是逻辑视图,DispatcherServlet 还要借助 ViewResolver 完成从逻辑视图到真实视图对象的解析工做。

⑦ 当获得真正的视图对象后,DispatcherServlet 会利用视图对象对模型数据进行渲染。

⑧ 客户端获得响应,多是一个普通的 HTML 页面,也能够是 XML 或 JSON 字符串,还能够是一张图片或者一个 PDF 文件。

5二、什么是 XSS 攻击?【困难】

答: XSS(Cross Site Script,跨站脚本攻击)是向网页中注入恶意脚本在用户浏览网页时在用户浏览器中执行恶意脚本的攻击方式。跨站脚本攻击分有两种形式:反射型攻击(诱使用户点击一个嵌入恶意脚本的连接以达到攻击的目标,目前有不少攻击者利用论坛、微博发布含有恶意脚本的 URL 就属于这种方式)和持久型攻击(将恶意脚本提交到被攻击网站的数据库中,用户浏览网页时,恶意脚本从数据库中被加载到页面执行,QQ 邮箱的早期版本就曾经被利用做为持久型跨站脚本攻击的平台)。XSS 虽然不是什么新鲜玩意,可是攻击的手法却不断翻新,防范 XSS 主要有两方面:消毒(对危险字符进行转义)和 HttpOnly (防范 XSS 攻击者窃取 Cookie 数据)。

5三、SQL 注入攻击?【困难】

答: SQL 注入攻击是注入攻击最多见的形式(此外还有 OS 注入攻击(Struts 2 的高危漏洞就是经过 OGNL 实施 OS 注入攻击致使的)),当服务器使用请求参数构造 SQL 语句时,恶意的 SQL 被嵌入到 SQL 中交给数据库执行。SQL 注入攻击须要攻击者对数据库结构有所了解才能进行,攻击者想要得到表结构有多种方式:(1)若是使用开源系统搭建网站,数据库结构也是公开的(目前有不少现成的系统能够直接搭建论坛,电商网站,虽然方便快 捷可是风险是必需要认真评估的);(2)错误回显(若是将服务器的错误信息直接显示在页面上,攻击者能够经过非法参数引起页面错误从而经过错误信息了解数据库结构,Web应用应当设置友好的错误页,一方面符合最小惊讶原则,一方面屏蔽掉可能给系统带来危险的错误回显信息);(3)盲注。防范 SQL 注入攻击也能够采用消毒的方式,经过正则表达式对请求参数进行验证,此外,参数绑定也是很好的手段,这样恶意的 SQL 会被当作 SQL 的参数而不是命令被执行,JDBC 中的 PreparedStatement 就是支持参数绑定的语句对象,从性能和安全性上都明显优于 Statement。

5四、什么是CSRF攻击?【困难】

答: CSRF 攻击(Cross Site Request Forgery,跨站请求伪造)是攻击者经过跨站请求,以合法的用户身份进行非法操做(如转帐或发帖等)。CSRF 的原理是利用浏览器的 Cookie 或服务器的 Session,盗取用户身份,其原理以下图所示。防范 CSRF 的主要手段是识别请求者的身份,主要有如下几种方式:

(1)在表单中添加令牌(token);

(2)验证码;

(3)检查请求头中的 Referer。

令牌和验证都具备一次消费性的特征,所以在原理上一致的,可是验证码是一种糟糕的用户体验,不是必要的状况下不要轻易使用验证码,目前不少网站的作法是若是在短期内屡次提交一个表单未得到成功后才要求提供验证码,这样会得到较好的用户体验。

4、redis

5五、使用redis有哪些好处?【基础】

答:

  • 速度快,由于数据存在内存中,相似于HashMap,HashMap的优点就是查找和操做的时间复杂度都是O(1)

  • 支持丰富数据类型,支持string,list,set,sorted set,hash

  • 支持事务,操做都是原子性,所谓的原子性就是对数据的更改要么所有执行,要么所有不执行

  • 丰富的特性:可用于缓存,消息,按key设置过时时间,过时后将会自动删除

5六、Redis有哪些数据结构?【基础】

答:字符串String、字典Hash、列表List、集合Set、有序集合SortedSet。

5七、若是有大量的key须要设置同一时间过时,通常须要注意什么?【中等】

答:若是大量的key过时时间设置的过于集中,到过时的那个时间点,redis可能会出现短暂的卡顿现象。通常须要在时间上加一个随机值,使得过时时间分散一些。

5八、为何Redis须要把全部数据放到内存中?【中等】

答:Redis为了达到最快的读写速度将数据都读到内存中,并经过异步的方式将数据写入磁盘。因此redis具备快速和数据持久化的特征。若是不将数据放在内存中,磁盘I/O速度为严重影响redis的性能。在内存愈来愈便宜的今天,redis将会愈来愈受欢迎。 若是设置了最大使用的内存,则数据已有记录数达到内存限值后不能继续插入新值。

5九、Redis提供了哪几种持久化方式?【中等】

答:

  1. RDB持久化方式可以在指定的时间间隔能对你的数据进行快照存储。
  2. AOF持久化方式记录每次对服务器写的操做,当服务器重启的时候会从新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操做到文件末尾。Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大。
  3. 若是你只但愿你的数据在服务器运行的时候存在,你也能够不使用任何持久化方式。
  4. 你也能够同时开启两种持久化方式, 在这种状况下, 当redis重启的时候会优先载入AOF文件来恢复原始的数据,由于在一般状况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。
  5. 最重要的事情是了解RDB和AOF持久化方式的不一样,让咱们以RDB持久化方式开始。

60、如何选择合适的持久化方式?【中等】

答:通常来讲, 若是想达到足以媲美PostgreSQL的数据安全性, 你应该同时使用两种持久化功能。若是你很是关心你的数据, 但仍然能够承受数分钟之内的数据丢失,那么你能够只使用RDB持久化。

有不少用户都只使用AOF持久化,但并不推荐这种方式:由于定时生成RDB快照(snapshot)很是便于进行数据库备份, 而且 RDB 恢复数据集的速度也要比AOF恢复的速度要快,除此以外, 使用RDB还能够避免以前提到的AOF程序的bug。

6一、redis支持的java客户端你用过哪一个?【基础】

答: Jedis,Jedis是Redis的Java实现的客户端,其API提供了比较全面的Redis命令的支持。

6二、Redis集群的主从复制模型是怎样的?【困难】

答:为了使在部分节点失败或者大部分节点没法通讯的状况下集群仍然可用,因此集群使用了主从复制模型,每一个节点都会有N-1个复制品。

6三、Redis集群之间是如何复制的?【中等】

答:异步复制。

6四、怎么测试Redis的连通性?【基础】

ping。

5、消息队列

6五、为何要用消息队列?【中等】

解耦、异步、削峰

  • A系统调用B系统、C系统,传统的调用是直接调用,可是当B系统说我不须要你提供数据了,这时候A须要改代码,C系统说我不须要某个字段了,这时候A也要改代码,若是又多了一个D系统,A又要写代码。为了实现解耦,引入消息队列,A将产生的数据丢到消息队列中,哪一个系统须要 哪一个系统就去取;
  • A系统调用B系统,B系统因为某个须要调用第三方接口超时,致使A系统响应速度慢,而B系统的好坏又不会影响业务逻辑,因此能够改成A异步调用B,A将消息丢到消息队列中,B系统订阅消息,实现A的快速响应;
  • 当大量流量请求到系统A时,因为数据库的处理能力有限,形成数据库链接异常。使用消息队列,大量请求先丢到消息队列中,系统A使用按批拉数据的方式,批量处理数据,生产中,高峰期短暂的消息积压是容许的。

6六、使用消息队列有什么缺点【中等】

  • 系统复杂性增长:加了消息队列,须要保证消息不会重复消费,须要保证消息的可靠性,须要保证消息队列的高可用
  • 系统的可用性下降:若是消息队列挂了,那么系统也会受到影响

6七、为何选用RocketMQ;RocketMQ和ActiveMQ的区别【困难】

RocketMQ模型简单、接口易用,在阿里大规模使用,社区活跃,单机吞吐量10万级,可用性很是高,消息理论上不会丢失;

  • ActiveMQ严格遵循JMS规范,可持久化到内存、文件、数据库,可用性高主要是主从,多语言支持,消失丢失率低;
  • RocketMQ持久化到磁盘文件,可用性很是高,支持分布式,只支持Java,消息理论上不会丢失;

6八、RocketMQ是怎么保证系统高可用的?【困难】

  • 多Master部署,防止单点故障;
  • 主从结构,消息冗余,防止消息丢失;

6九、消息中间件集群崩溃,如何保证百万生产数据不丢失?【中等】
答: 把消息持久化写入到磁盘上去 。

6、spring boot

70、Spring Boot 的核心配置文件有哪几个?它们的区别是什么?【中等】

Spring Boot 的核心配置文件是 application 和 bootstrap 配置文件。

application 配置文件这个容易理解,主要用于 Spring Boot 项目的自动化配置。

bootstrap 配置文件有如下几个应用场景:

  • 使用 Spring Cloud Config 配置中心时,这时须要在 bootstrap 配置文件中添加链接到配置中心的配置属性来加载外部配置中心的配置信息;

  • 一些固定的不能被覆盖的属性;

  • 一些加密/解密的场景;

7一、Spring Boot 的配置文件有哪几种格式?它们有什么区别?【中等】

.properties 和 .yml,它们的区别主要是书写格式不一样。

1).properties

app.user.name = javastack

2).yml

app:
  user:
    name: javastack

另外,.yml 格式不支持 @PropertySource 注解导入配置。

7二、Spring Boot 的核心注解是哪一个?它主要由哪几个注解组成的?【基础】

启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了如下 3 个注解:

  • @SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。

  • @EnableAutoConfiguration:打开自动配置的功能,也能够关闭某个自动配置的选项,如关闭数据源自动配置功能:@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })。

  • @ComponentScan:Spring组件扫描。

7三、开启 Spring Boot 特性有哪几种方式?【基础】

1)继承spring-boot-starter-parent项目

2)导入spring-boot-dependencies项目依赖

7四、Spring Boot 须要独立的容器运行吗?【基础】

能够不须要,内置了 Tomcat/ Jetty 等容器。
7五、如何在 Spring Boot 启动的时候运行一些特定的代码?【中等】

Spring Boot Runner启动器,能够实现接口 ApplicationRunner 或者 CommandLineRunner,这两个接口实现方式同样,它们都只提供了一个 run 方法。

7六、Spring Boot 有哪几种读取配置的方式?【中等】

Spring Boot 能够经过 @PropertySource,@Value,@Environment, @ConfigurationProperties 来绑定变量。

实例:

单个注入:@Value("${book.author}"),

映射一个类:@ConfigurationProperties(prefix="author",locations={"classpath:author.properties"})经过prefix指定前缀,经过locations指定位置
7七、Spring Boot 如何定义多套不一样环境配置?【中等】

提供多套配置文件,按照application-xxx.properties格式创建文件,并在application.properties中指定。如:

application.properties
 
application-dev.properties
 
application-test.properties
 
application-prod.properties

7八、SpringBoot中的定时任务如何实现?【中等】

经过配置注解@EnableScheduline来开启对计划任务的支持,而后再要执行的任务上加注解@Scheduled。

7九、咱们如何链接一个像 MYSQL 或者 orcale 同样的外部数据库?【中等】

让咱们以 MySQL 为例来思考这个问题:

第一步 - 把 mysql 链接器的依赖项添加至 pom.xml

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

第二步 - 配置你的 MySQL 数据库链接

配置 application.properties

spring.datasource.url=jdbc:mysql://localhost:3306/todo_example
spring.datasource.username=todouser
spring.datasource.password=YOUR_PASSWORD

第三步 - 从新启动,你就准备好了!

7、spring cloud

80、什么是微服务【中等】

  • 之前的模式是 全部的代码在同一个工程中 部署在同一个服务器中 同一个项目的不一样模块不一样功能互相抢占资源

  • 微服务 将工程根据不一样的业务规则拆分红微服务 微服务部署在不一样的机器上 服务之间进行相互调用

  • Java微服务的框架有 dubbo(只能用来作微服务),spring cloud(提供了服务的发现,断路器等)

8一、微服务之间是如何独立通信的spring Cloud和 Dubbo有哪些区別?【困难】

答:

  • springcloud服务注册中心是Spring Cloud Netflix Eureka

    dubbo的注册中心通常是zookeeper

  • dubbo只是相似Netflix的一个子集只有注册中心,其余springcloud组件没有

  • springcloud的调用方式是REST API

    dubbo的调用方式是RPC

    RPC服务提供方与调用方接口依赖方式太强

    咱们为每一个微服务定义了各自的service抽象接口

    并经过持续集成发布到私有仓库中

    调用方应用对微服务提供的抽象接口存在强依赖关系

    REST方式的服务依赖要比RPC方式的依赖更为灵活

  • Dubbo的文档能够说在国内开源框架中算是一流的,很是全,而且讲解的也很是深刻,国内开发者来讲,阅读起来更加容易上手

8二、springcloud如何实现服务的注册和发现【中等】

  • 服务在发布时 指定对应的服务名(服务名包括了IP地址和端口) 将服务注册到注册中心(eureka或者zookeeper)

  • 这一过程是springcloud自动实现 只须要在main方法添加@EnableDisscoveryClient 同一个服务修改端口就能够启动多个实例

  • 调用方法:传递服务名称经过注册中心获取全部的可用实例 经过负载均衡策略调用(ribbon和feign)对应的服务

8三、Ribbon和Feign的区别【中等】

Ribbon和Feign都是用于调用其余服务的,不过方式不一样。

1.启动类使用的注解不一样,Ribbon用的是@RibbonClient,Feign用的是@EnableFeignClients。

2.服务的指定位置不一样,Ribbon是在@RibbonClient注解上声明,Feign则是在定义抽象方法的接口中使用@FeignClient声明。

3.调用方式不一样,Ribbon须要本身构建http请求,模拟http请求而后使用RestTemplate发送给其余服务,步骤至关繁琐。

Feign则是在Ribbon的基础上进行了一次改进,采用接口的方式,将须要调用的其余服务的方法定义成抽象方法便可,不须要本身构建http请求。不过要注意的是抽象方法的注解、方法签名要和提供服务的方法彻底一致。

8四、springcloud断路器的做用【中等】

当一个服务调用另外一个服务因为网络缘由或者自身缘由出现问题时 调用者就会等待被调用者的响应 当更多的服务请求到这些资源时。致使更多的请求等待 这样就会发生连锁效应(雪崩效应) 断路器就是解决这一问题

8五、springcloud如何实现服务的注册和发现【中等】

答:服务在发布时 指定对应的服务名,服务名包括了IP地址和端口,将服务注册到注册中心eureka或者zookeeper,这一过程是springcloud自动实现,只须要在main方法添加 @ EnableDisscoveryClient,同一个服务修改端口就能够启动多个实例。

8六、springcloud中的组件有那些?【中等】

答:独挑大梁,独自启动不须要依赖其它组件

1)Eureka,服务注册中心,特性有失效剔除、服务保护

2)Dashboard,Hystrix仪表盘,监控集群模式和单点模式,其中集群模式须要收集器Turbine配合

3)Zuul,API服务网关,功能有路由分发和过滤

4)Config,分布式配置中心,支持本地仓库、SVN、Git、Jar包内配置等模式

润物无声,融合在每一个微服务中、依赖其它组件并为其提供服务

1)Ribbon,客户端负载均衡,特性有区域亲和,重试机制

2)Hystrix,客户端容错保护,特性有服务降级、服务熔断、请求缓存、请求合并、依赖隔离

3)Feign,声明式服务调用本质上就是Ribbon+Hystrix

4)Stream,消息驱动,有Sink、Source、Processor三种通道,特性有订阅发布、消费组、消息分区

5)Bus,消息总线,配合Config仓库修改的一种Stream实现,

6)Sleuth,分布式服务追踪,须要搞清楚TraceID和SpanID以及抽样,如何与ELK整合

8、其余

8七、cookie和session的区别【基础】

一、Cookies是一种可以让网站服务器把少许数据储存到客户端的硬盘或内存,或是从客户端的硬盘读取数据的一种技术。Cookies是当你浏览某网站时,由Web服务器置于你硬盘上的一个很是小的文本文件,它能够记录你的用户ID、密码、浏览过的网页、停留的时间等信息。session: 当用户请求来自应用程序的 Web 页时,若是该用户尚未会话,则 Web 服务器将自动建立一个 Session 对象。当会话过时或被放弃后,服务器将终止该会话。cookie机制:采用的是在客户端保持状态的方案,而session机制采用的是在服务端保持状态的方案。同时咱们看到因为服务器端保持状态的方案在客户端也须要保存一个标识,因此session机制可能须要借助cookie机制来达到保存标识的目的。

二、Session是服务器用来跟踪用户的一种手段,每一个Session都有一个惟一标识:session ID。当服务器建立了Session时,给客户端发送的响应报文包含了Set-cookie字段,其中有一个名为sid的键值对,这个键值Session ID。客户端收到后就把Cookie保存浏览器,而且以后发送的请求报表都包含SessionID。HTTP就是经过Session和Cookie这两个发送一块儿合做来实现跟踪用户状态,Session用于服务端,Cookie用于客户端

8八、一次完整的http请求过程【中等】

域名解析 --> 发起TCP的3次握手 --> 创建TCP链接后发起http请求 --> 服务器响应http请求,浏览器获得html代码 --> 浏览器解析html代码,并请求html代码中的资源(如js、css、图片等) --> 浏览器对页面进行渲染呈现给用户。

8九、讲一下长链接【困难】

1、基于http协议的长链接

在HTTP1.0和HTTP1.1协议中都有对长链接的支持。其中HTTP1.0须要在request中增长”Connection: keep-alive“ header才可以支持,而HTTP1.1默认支持.

http1.0请求与服务端的交互过程:

  1. 客户端发出带有包含一个header:”Connection: keep-alive“的请求

  2. 服务端接收到这个请求后,根据http1.0和”Connection: keep-alive“判断出这是一个长链接,就会在response的header中也增长”Connection: keep-alive“,同是不会关闭已创建的tcp链接.

  3. 客户端收到服务端的response后,发现其中包含”Connection: keep-alive“,就认为是一个长链接,不关闭这个链接。并用该链接再发送request.转到a)。

2、发心跳包。每隔几秒就发一个数据包过去

90、TCP如何保证可靠传输?【困难】

  1. 三次握手。

  2. 将数据截断为合理的长度。应用数据被分割成 TCP 认为最适合发送的数据块(按字节编号,合理分片)

  3. 超时重发。当 TCP 发出一个段后,它启动一个定时器,若是不能及时收到一个确认就重发

  4. 对于收到的请求,给出确认响应

  5. 校验出包有错,丢弃报文段,不给出响应

  6. 对失序数据进行从新排序,而后才交给应用层

  7. 对于重复数据 , 可以丢弃重复数据

  8. 流量控制。TCP 链接的每一方都有固定大小的缓冲空间。TCP 的接收端只容许另外一端发送接收端缓冲区所能接纳的数据。这将防止较快主机导致较慢主机的缓冲区溢出。

  9. 拥塞控制。当网络拥塞时,减小数据的发送。

9一、URI和URL的区别【中等】

URI,是uniform resource identifier,统一资源标识符,用来惟一的标识一个资源。Web上可用的每种资源如HTML文档、图像、视频片断、程序等都是一个来URI来定位的

URI通常由三部组成:

  1. 访问资源的命名机制

  2. 存放资源的主机名

  3. 资源自身的名称,由路径表示,着重强调于资源。

URL是uniform resource locator,统一资源定位器,它是一种具体的URI,即URL能够用来标识一个资源,并且还指明了如何locate这个资源。URL是Internet上用来描述信息资源的字符串,主要用在各类WWW客户程序和服务器程序上,特别是著名的Mosaic。采用URL能够用一种统一的格式来描述各类信息资源,包括文件、服务器的地址和目录等。

URL通常由三部组成:

  1. 协议(或称为服务方式)

  2. 存有该资源的主机IP地址(有时也包括端口号)

  3. 主机资源的具体地址。如目录和文件名等

9二、http和https的区别?【中等】

  1. https协议须要到CA申请证书,通常免费证书不多,须要交费。

  2. http是超文本传输协议,信息是明文传输;https 则是具备安全性的ssl加密传输协 议。

  3. http和https使用的是彻底不一样的链接方式,用的端口也不同,前者是80,后者是443。

  4. http的链接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

  5. http默认使用80端口,https默认使用443端口

9三、docker经常使用命令【中等】

1.docker images // 查看镜像
2.docker run 镜像名称   // 生成一个正在运行的容器实例
3.docker stop 容器名称   // 中止容器
4.docker rm 容器名称  // 删除容器
5.docker start 容器名称  // 启动容器
6.docker restart 容器名称  //重启容器
7.docker rmi 镜像名称  // 删除镜像
8.docker exec -it 容器名称 /bin/bash  // 进入容器
9.docker ps  // 显示正在运行的全部容器
10.docker ps -a  // 显示全部容器(包括已经中止的)
11.docker pull 镜像名称:版本号  // 拉取镜像

9四、什么是Docker镜像?【中等】

Docker镜像是Docker容器的源代码。换句话说,Docker镜像用于建立容器。使用build命令建立映像,而且在使用run启动时它们将生成容器。镜像存储在Docker注册表http://registry.hub.docker.com中,由于它们可能变得很是大,镜像被设计为由其余镜像层组成,容许在经过网络传输镜像时发送最少许的数据。

9五、什么是Docker容器?【中等】

Docker容器包括应用程序及其全部依赖项,但与其余容器共享内核,做为主机操做系统上用户空间中的独立进程运行。Docker容器不依赖于任何特定的基础架构:它们能够在任何计算机,任何基础架构和任何云中运行。

9六、什么是Docker Hub?【中等】

Docker hub是一个基于云的注册表服务,容许您连接到代码存储库,构建镜像并测试它们,存储手动推送的镜像以及指向Docker云的连接,以便您能够将镜像部署到主机。它为整个开发流程中的容器镜像发现,分发和变动管理,用户和团队协做以及工做流自动化提供了集中资源。

9七、什么是 Git 复刻(fork)?复刻(fork)、分支(branch)和克隆(clone)之间有什么区别?【中等】

  • 复刻(fork)

是对存储仓库(repository)进行的远程的、服务器端的拷贝,从源头上就有所区别。复刻实际上不是 Git 的范畴。它更像是个政治/社会概念。

  • 克隆(clone)

不是复刻,克隆是个对某个远程仓库的本地拷贝。克隆时,其实是拷贝整个源存储仓库,包括全部历史记录和分支。

  • 分支(branch)

是一种机制,用于处理单一存储仓库中的变动,并最终目的是用于与其余部分代码合并。

9八、“git pull”和“git fetch”之间有什么区别?【中等】

简单来讲,git pull 是 git fetch + git merge。 当你使用 pull,Git 会试着自动为你完成工做。它是上下文(工做环境)敏感的,因此 Git 会把全部拉取的提交合并到你当前处理的分支中。

pull 则是 自动合并提交而没有让你复查的过程。若是你没有细心管理你的分支,你可能会频繁遇到冲突。

当你 fetch,Git 会收集目标分支中的全部不存在的提交,并将这些提交存储到本地仓库中。但Git 不会把这些提交合并到当前分支中。这种处理逻辑在当你须要保持仓库更新,在更新文件时又但愿处理可能中断的事情时,这将很是实用。而将提交合并到主分支中,则该使用 merge。

9九、使用Ajax的优缺点分别是什么?【中等】

优势

  • 交互性更好。来自服务器的新内容能够动态更改,无需从新加载整个页面。
  • 减小与服务器的链接,由于脚本和样式只须要被请求一次。
  • 状态能够维护在一个页面上。JavaScript 变量和 DOM 状态将获得保持,由于主容器页面未被从新加载。
  • 基本上包括大部分 SPA 的优势。

缺点

  • 动态网页很难收藏。
  • 若是 JavaScript 已在浏览器中被禁用,则不起做用。
  • 有些网络爬虫不执行 JavaScript,也不会看到 JavaScript 加载的内容。
  • 基本上包括大部分 SPA 的缺点。

100、跨域问题,谁限制的跨域,怎么解决【困难】

  1. 浏览器的同源策略致使了跨域
  2. 用于隔离潜在恶意文件的重要安全机制
  3. jsonp ,容许 script 加载第三方资源
  4. nginx 反向代理(nginx 服务内部配置 Access-Control-Allow-Origin *)
  5. cors 先后端协做设置请求头部,Access-Control-Allow-Origin 等头部信息
  6. iframe 嵌套通信,postmessage