2019-2年面试总结


Spring事务传播行为

required: 如果存在事务则加入,不存在则新建事务(默认)

supports: 如果存在事务则加入,不存在以非事务的方式执行

mandatory: 如果存在事务则加入,如果不存在则抛出异常

nested: 新建一个事务,如果当前存在事务则加入嵌套执行

requires_new: 总是新建一个事务,如果当前存在事务则挂起当前事务

not_supported: 总是非事务的方式执行,如果存在事务则挂起当前事务

never: 以非事务的方式执行,如果存在事务,则抛出异常

数据库事务隔离级别

Serializable(串行化): 最高级别,可避免脏读、不可重复读、幻读
Repeatable read(可重复读): 可避免脏读、不可重复读的发生(mysql默认)
Read committed(读已提交): 可避免脏读的发生(Oracle默认)
Read uncommitted(读未提交): 最低级别,任何情况都无法避免

事务带来的问题

脏读: 指一个事务处理过程中读取了另一个事务未提交的数据。比如,当一个事务正在多次修改某个数据,而当这个事务对数据的修改还未提交时,这时一个并发的事务来访问该数据,就会造成数据的脏读。

不可重复读: 对于数据库中的某个数据,一个事务范围内多次查询返回了不同的值。例如,事务 T1 在读取某一数据,而事务 T2 立马修改了这个数据并且提交事务,当事务T1再次读取该数据就得到了不同的结果,即发生了不可重复读。

幻读: 指在一个事务读的过程中,另外一个事务可能插入了新数据记录,影响了该事务读的结果。例如,事务 T1 对一个表中所有的行的某个数据项执行了从“1”修改为“2”的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。这时,操作事务 T1 的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。

区别: *脏读关注的是事务读取了另一个事务未提交的数据;不可重复读关注的是同一事务中对同一个数据项多次读取的结果互不相同;幻读更侧重于数据记录的插入/删除问题。更进一步地说,不可重复读关注的是数据的更新带来的问题,幻读关注的是数据的增删带来的问题。

SpringMVC执行流程

  1. 用户向服务器发送请求,请求被SpringMVC的前端控制器DispatcherServlet拦截

  2. DispatcherServlet对请求URL进行解析,调用HandlerMapping获得该Handler配置的所有相关对象,包括Handler对象以及Handler对象对应的拦截器,这些对象被封装到一个HandlerExecutionchain当中返回

  3. DispatcherServlet根据获得的Handler(Controller),选择一个合适的HandlerAdapter。一个HandlerAdapter会被用于处理多种(一类)Handler,并调用Handler实际处理请求的方法。

  4. 在调用Handler实际处理请求的方法之前,HandlerAdapter首先会结合用户配置对请求消息进行转换(序列化),然后通过DataBinder将请求中的模型数据绑定到Handler对应的处理方法的参数中。

  5. Handler调用业务逻辑组件完成对请求的处理后,向DispatcherServlet返回一个ModelAndView对象,ModelAndView对象中应该包含视图名或者视图和模型。

  6. DispatcherServlet调用视图解析器ViewResolver结合Model来渲染视图

7.DispatcherServlet将视图渲染结果返回给客户端

SpringMVC请求处理流程概括: 当SpringMVC收到请求时,前端控制器DispatcherServlet会根据URL调用HandlerMapping将请求分发给具有一系列拦截器和业务控制器handle的HandlerExecutionChain对象,然后该请求将依次通过该执行链的各个拦截器并最终到达业务控制器Controller。在业务控制器Controller处理该请求前,HandlerAdapter会对请求消息作进一步转换和解析并绑定到业务控制器Controller的具体请求处理方法上,然后该方法根据结合请求参数调用一系列业务逻辑组件去处理请求,并将包含模型数据和具体视图的处理结果交给视图解析器ViewResolver进行渲染,最终DispatcherServlet将视图渲染结果返回客户端。

OSI七层结构

应用层: 确定进程之间通信的性质以满足用户需要以及提供网络与用户应用

表示层: 主要解决用户信息的语法表示问题,比如解密加密

会话层: 提供包括访问验证和会话管理在内的建立和维护应用之间的通信的机制,如服务器验证用户登录便是由会话层完成的

传输层: 实现网络不同主机上用户进程之间的数据通信,可靠与不可靠的传输,传输层的错误检测,流量监控等

网络层: 提供逻辑地址(IP) 选路,数据从源端到目的端

数据链路层: 将上层数据封装成帧,用MAC地址访问媒介,错误检测与修正

物流层: 设备之间比特流的传输,物流接口,电气特性等

四次挥手为什么要等两秒再关闭

  1. 为了保证客户端发送的最后一个ACK报文能够到达服务器
  2. 防止存活在网络里的老TCP报文与新TCP报文冲突,需等待老TCP报文从网络消失

redis为什么这么快

  1. 数据直接存储在内存中,避免了与磁盘的IO
  2. 单线程,避免了不必要的上下文切换和条件竞争
  3. 使用底层模型不同,redis直接自己构建了VM机制
  4. redis中的数据结构都是专门进行设计的,类似hash
  5. 使用多路I/O复用模型,非阻塞IO

分布式锁的实现

基于乐观锁: 利用主键唯一的特性,如果有多个请求同时提交到数据库会保证只有一个操作可以成功 基于表字段版本号做分布式锁

基于悲观锁: 在查询语句后加for update 数据库会在查询过程中给数据表加排它锁(mysql Innodb只有通过索引进行检索时才会使用行级锁,否则使用表级锁)

基于redis: 利用setnx(key,value)的原子性(SET if Not Exists),如果key不存在,则设置当前key成功,返回1;如果当前key已存在,则返回0. 使用expire()设置过期时间,使用delete删除key

基于zookeeper: 在/lock节点下创建一个有序临时节点,判断创建的节点序号是否最小,如果是则获取锁成功,不是则取锁失败,然后watch序号比本身小的前一个节点,等待 watch 事件到来后,再次判断是否序号最小。

Servlet生命周期

初始化: web容器加载servlet,调用init()方法

处理请求: 当请求到达时,运行其service()方法.service()自动派遣运行与请求相对应的doGet或doPost方法

销毁: 服务结束,web容器会调用servlet的distory()方法销毁servlet


文章作者: kangshifu
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 kangshifu !
  目录