文档章节

后端开发面试题

Jansens
 Jansens
发布于 2016/10/26 10:48
字数 4229
阅读 40
收藏 4

1. Spring MVC 如何接受并处理一个请求的?

首先我们会在web.xml中注册一个DispatcherServlet,并令这个servlet接收所有的请求,项目启动后Spring会扫描配置文件,根据配置加载和实例化类,其中扫描到的带有@Controller或者@RestController注解的类则是请求要映射到的类,Spring MVC扫描里面所有和请求映射有关的注解, 如@RequestMapping@ResponseBody@RequestParam等。当接收到一个请求时,它会根据请求的url映射到对应的controler,并根据返回值判断是渲染jsp页面还是返回普通文本,亦或是返回json。

2. AOP实现原理。

AOP是通过动态代理来实现的,有两种常用的技术,一是JDK的动态代理,二是CGLIB,而无论是前者还是后者,都是生成动态生成类的字节码来实现的。JDK的动态代理只能处理接口实现的方法,而CGLIB则没有这个限制。因为字节码是动态生成的,所以可以在生成的字节码当中,在目标方法前后插入定义好的方法的调用。

3. 注解是怎么用的?为什么要使用注解?

当在一个类、方法或者字段上标上注解后,可以通过obj.getClass().isAnnotationPresent(..)来判断一个目标是否被特定的注解标识,通过obj.getClass().getAnnotation(..)来获取标志是注解,以此获得注解上的信息。使用注解可以帮助我们在项目的编译期或运行时给类、方法或对象添加一个额外的信息,给编程增加了很大的灵活性。比如用@Override来标志这是重写父类的方法,那么编译器就可以在编译期检查该方法是否真的是重写父类的方法,将错误扼杀在编译器。

4. 线程有几种状态?生命周期是怎样的?

线程有五种状态:创建就绪运行阻塞死亡。 
调用start方法时,线程就会进入就绪状态。 
在线程得到cpu时间片时进入运行状态。 
线程调用yield方法可以让出cpu时间回到就绪状态。 
线程运行时可能由于IO、调用sleepwaitjoin方法或者无法获得同步锁等原因进入阻塞状态。 
当线程获得到等待的资源资源或者引起阻塞的条件得到满足时(调用notifynotifyAll),会从阻塞状态进入就绪状态。 
当线程的run方法执行结束或者调用interrupt方法时,线程就进入死亡状态。

5. Java中如何实现同步。

Java实现同步的方法有:

  1. 使用synchronized关键字为方法或代码块加锁。

  2. 使用volatile修饰变量,但是volatile不保证原子性

  3. 使用ReentrantLock或者ReentrantReadWriteLock, 这种方法比synchronized更灵活。

  4. 使用Semaphore,允许最多n个线程同时访问资源。

6. HashMapHashtable的区别。

  1. HashMap线程不安全的,Hashtable是线程安全的。

  2. HashMap的key和value接受null,Hashtable不接受。

  3. HashMap继承自AbstractMapHashtable继承自Directory

7. JVM是否了解?

这里我回答了最近正在看《深入理解Java虚拟机》一书,本想着这方面的问题能答上一些的,没想到面试官直接说
那看样子还不是很了解,就不问这块的问题了= =.. 心塞 
但是我估摸着大概如果问的话会问:

7.1. JVM的内存模型。

JVM的内存一共分为5个部分:

  1. 程序计数器: 里面存放着线程执行的指令。

  2. 方法区: 存放类的信息,如:类名、方法、成员变量等,也存放着常量池。

  3. 虚拟机栈: 存放着局部变量表、操作数栈、方法出口信息等方法执行所需信息。

  4. 本地方法栈: 存放程序调用native方法的信息。

  5. : 这五个部分中最大的,对象的内存分配都是在堆内存中。

7.2. 常用的虚拟机参数。

  1. -Xmx: 指定最大堆内存

  2. -Xms: 指定初始化堆内存大小。

  3. -Xmn: 指定年轻代内存初始内存大小,同时也是最大内存大小。

  4. -XX:NewSize: 指定年轻代内存大小。

  5. -XX:NewRatio: 指定年轻代和老年代的内存比例。

  6. -XX:MaxHeapSize: 指定程序最大内存。

  7. -XX:+PrintGC: 打印GC日志。

  8. -XX:+PrintGCDetails: 打印详细的GC日志。

  9. -Xloggc: 打印GC日志保存位置。

7.3. 垃圾回收算法。

  1. 引用计数算法:

该算法对每一个对象都有一个引用计数,没增加一次引用就+1,减少一次引用-1,在回收时将引用计数为0的对象清理掉。这种算法简单,但是无法解决循环引用的问题(比如: A引用B, B也引用A,但是A和B都没有被其它任何对象引用)。

  1. 标记-清除算法:

该算法分为两个阶段, 第一阶段遍历找出所有需要被回收的对象,并做上标记,第二阶段对清理所有被标记的对象,这种算法效率比较低,并且会产生较多的内存碎片。

  1. 标记-整理算法:

该算法的第一阶段和标记-清除算法是一样的,而第二阶段它不是直接清理掉垃圾对象,而且将存活的对象往同一侧移动,移动完成后清理掉另一侧所有的对象。这种算法不会产生内存碎片,但是效率低下。

  1. 复制算法:

该算法将内存分为两个区域,进行垃圾回收时,就将还活着的对象复制到另一块内存区域中,然后再将整片内存区域清空。这种算法简单快速,而且不会产生内存碎片,但是因为将内存分成两块,所以可用的内存会少很多。

  1. 分代收集算法:

将内存细分为多个区域,不同区域GC的频率,并对不同的区域采用适当的收集算法。如JVM将内存分为年轻代和老年代,普通对象最开始分配在年轻代(大对象会直接分配到老年代),同一个对象在经过几次GC后还存活着,就认为这个对象的生命周期会比较长,将其移入老年代,GC主要发生在年轻代。

7.4 类加载机制。

Java中主要有Bootstrap类加载器ExtClassLoaderAppClassLoader,其中Bootstrap类加载器主要加载JAVA_HOME/lib目录下的类库,ExtClassLoader加载JAVA_HOME/lib/ext目录下的类库,AppClassLoader加载classpath指向目录下的类库。

Java的类加载器使用双亲委派模型,除了顶层的Bootstrap类加载器外,其余的类加载器都有父类加载器,当一个类加载器要加载一个类时,它不会直接去加载,而是委托父类加载器尝试加载,父类加载器如果无法完成,则继续委托其父类加载器加载,如果在期间有某一个类加载器发现已经加载过这个类,则会将已经加载的类返回,子类不再加载。若所有的类加载器都未加载过这个类,那么最开始尝试加载的加载器才会去加载这个类。使用这样的加载机制的好处是: 对于同一个类,如:java.lang.String,能保证整个程序中都是使用的这一个类,否则如果用户在自己的项目中也写了一个java.lang.String类,那么项目中将存在两个String类,一个是java提供的String类,一个是用户自定义的String类,不仅使项目变得混乱,而且不安全。

8. MyBatis和Hibernate各有什么优缺点?

我个人因为只简单接触过而没有实际应用过Hibernate,所以没能从比较好的角度来回答这个问题。

Hibernate的优点是它是一个完全的ORM框架,使用Hibernate可以做到不用手写SQL,而且无须关心使用何种数据库,可移植性较好,当需要更变数据库时需要做的修改很少甚至为0。其缺点是需要根据数据库的设计在实体进行又一次的配置,且帮程序员做了太多事,如果需要进行调优的话需要对Hibernate有比较深的了解。 
MyBatis的优缺点差不多和Hibernate相反,我们需要手写SQL语句和配置结果集和实体类的映射,即使是简单的单表操作也需要写SQL(可以通过拦截器来实现CommonMapper,或者可以使用生成器来生成代码),因此MyBatis要进行SQL调优也简单直接。其次是MyBatis二级缓存功能较弱,是针对namespace的。

9. MySQL平时是怎么分析效率和进行SQL优化的?

较常使用的方法是explain SQL查看执行计划,根据查询计划可以知道是否使用了索引,是否进行来全表扫描以及查询的顺序,依此我们可以建立适当的索引和连接查询调优。 
还有一个是开启慢查询记录执行时间长的SQL语句。

  1. 通常会在WHEREJOIN ONORDER BY使用到字段上加上索引。

  2. 避免查询时判断NULL,否则可能会导致全表扫描。

  3. 避免使用OR来连接查询条件,否则可能导致全表扫描,可以改用UNIONUNION ALL

  4. 避免LIKE查询,否则可能导致全表扫描。

  5. 不使用SELECT *,只查询必须的字段,避免加载无用数据。

  6. 能用UNION ALL的时候就不用UNIONUNION过滤重复数据要耗费更多的cpu资源。

10. MySQL除了InnoDB还有哪些引擎,有什么区别?

因为平时都是用的InnoDB,对其它引擎的了解甚少,所以这个问题没答上= =,这里直接贴一个链接好了。 
相关链接: MySQL存储引擎介绍

11. 如何动态改变页面上的元素?

  1. 使用$(..).css({..})来改变元素的样式。

  2. 使用$(..).attr(..)改变元素的属性。

  3. 使用$(..).html(..)改变元素的html内容。

  4. 使用$(..).text(..)改变元素的文本内容。

  5. 使用$(..).remove(..)删除元素。

  6. 使用$(..).append(..)添加元素。

12. 分页的实现。

如果是使用JSP等后端模板的话,一般会将需要分页的JSP代码抽成一个单独的JSP文件,并在页面中动态计算分页按钮的展示方式,在母页中includeJSP文件,然后在前端点击分页按钮时,通过AJAX请求下一页的内容,服务器端将渲染后的HTML返回给前端,前端通过$(..).html()等方式替换展示内容。 
如果是在前后端分离的项目中,一般会使用一些前端的框架,如: React.jsVue.js等,每次只向后台请求分页的数据,一般数据交互格式使用JSON,并替换已有的数据,触发页面内容的改变。

13. 解释一下RESTful,平时是怎么用的

RESTful是无状态的,采用URL+HTTP请求方法来描述资源行为。 
一般在前后端分离的项目中,后端会提供REST接口给前端,其HTTP请求方法一般为:

  1. GET : 获取资源。

  2. POST: 更新资源。

  3. PUT: 创建资源。

  4. DELETE: 删除资源。

其次,RESTful由于是无状态的,一般会采用JWTOAuth的方式来认证一个用户,Token是保存在前端的,为了安全性一般会配合HTTPS使用。

14. 有没有抓过包?GET和POST格式是怎么样的?

HTTP请求分为三部分: 请求行请求头请求体
请求行: 第一行是METHOD URL protocal,如GET http://abc.com HTTP/1.1。 
请求头: 从第二行开始,每一行的内容都是一个请求头参数值,直到遇到一个空行为止。 
请求体: 请求头和请求体中间隔着一行空行作为分界,请求体包含着本次请求携带的内容。 
GET方式的请求没有请求体,其是将参数追加到URL后面,URL?后面的内容为请求参数。 
POST方式则三部分都有,且POST的请求头应当包含Content-Type来指明请求体中内容的类型。

15. 如果是上传文件的话又是怎样的?后端如何处理?

上传文件的话会设置Content-Typemultipart/form-data,并指定boundary的值来标识请求体中内容的分界,而在请求体中,不同的内容(如:文件A和文件B)之间使用boundary的值来标识分界,并且请求体中每部分内容都会有Content-DispositionContent-Type来指明这部分内容的类型和信息。

后端的话使用ServletFileUpload来解析请求,获得FileItemList,遍历Item,然后通过Item获得输入流,从输入流中读取上传文件的数据,再构建FileOutputStream输出到磁盘中保存。
如果使用Spring MVC,则可以在接收请求的方法中接收CommonsMultipartFile,并使用transferTo方法保存到磁盘中。

16. AJAX实现原理。

这个也没答上来,平时都是使用jQuery封装的AJAX或者其他AJAX框架。

AJAX是利用浏览器的AJAX引擎来实现的异步请求,通过XMLHttpRequest对象来发送请求,由AJAX引擎向服务器发送和接收响应,再回调给用户处理,达到不阻塞用户界面和无刷新的目的。 
资料来源: AJAX工作原理及其优缺点

17. Linux下怎么查找一个文件?

如果是查找二进制文件,可以使用whereis。 
如果是查找命令,可以使用which。 
如果是其他文件,可以使用find命令(其实什么都可以找), -name指定搜索的名称或者匹配串, -maxdepth指定搜索的深度。 
也可以使用locate命令查找,但是最新变动的文件可能会找不到,因为该命令实际上是搜索数据库,该数据库每天自动更新,可以手动执行updatedb更新。

18. Linux怎么查找一个进程?

使用ps命令可以查看进程状态,ps -ef查看所有进程,配合grep命令可以进行筛选, 如查看tomcat进程的命令是: ps -ef | grep tomcat

19. Linux下只知道文件所在目录和内容,如何查找文件?

这题没也没答上= =

使用grep命令可以实现: 
grep -rn /path/to/target/dir -e "pattern" 
-r: 递归 
-n: 显示行数 
-w: 完全匹配 
例子: grep -rn. -e "ERROR" 
输出: ./面试:143:输出: ./面试:144:上面的命令搜索当前目录及其子目录中的文件,并输出含有ERROR内容的行 
详细答案及来源:How to find all files containing specific text on Linux?

20. Redis你用它来做什么?

Redis在我接触过的项目中主要做了两件事:

  1. 缓存

  2. 存储需要计算的信息

Redis也可以用来做消息订阅队列等。

21. Redis如果运行过程中崩溃了怎么办。

这个问题我估摸着面试官想问的是Redis的数据保障的方法,不然崩溃了除了重启还能怎么办?

Redis有提供数据持久化的功能,一种是快照,一种是AOF。 
快照是在某一个时间点将所有数据写入到磁盘中,AOF是将被执行的命令复制到硬盘中,快照的文件体积要比AOF的文件体积小。前者在恢复时速度比后者快,但是因为是间隔持久化,所以会有一定量的数据丢失。后者因为是实时写入的,所以数据的完整性比较好,如果丢失的话一般也就丢失一秒的数据。

其次需要做主从复制,这样一份数据可以保存在多台服务器上,且可以避免Redis崩溃到重启完成这段时间内无法提供正常服务,同时从服务器可以分担主服务器的读压力。

22. Redis集群。

没配置过所以没答上= =

相关连接: Redis集群教程

23. 剩下的问题都是偏向个人的,没有什么通用性的回答,大概问了我:

  1. 前一家公司实习的时候主要做什么?

  2. 讲一下做过的项目?

  3. 项目中有没有遇到什么难点?怎么解决的?

  4. 有没有做过什么有亮点的东西? 其中在问题3根据我的回答,继续将情况复杂化让我给出解决方案,一步一步问。

© 著作权归作者所有

Jansens
粉丝 9
博文 53
码字总数 128340
作品 0
闸北
高级程序员
私信 提问
Android-Java面试

2016 年末,腾讯,百度,华为,搜狗和滴滴面试题汇总 2016 年未,腾讯,百度,华为,搜狗和滴滴面试题汇总 各大公司 Java 后端开发面试题总结 各大公司 Java 后端开发面试题总结 刚出炉的一线...

掘金官方
2018/01/02
0
0
全新 Dubbo Admin 安装(开发版-Dubbo OPS)

这是正在研发的Dubbo Admin,这一版Dubbo Admin名称改成了Dubbo OPS,目前功能简陋,不建议使用(2018/11月)。架构上使用了前后端分离。前端使用Vue实现,后端使用Spring Boot实现。在安装之...

关注公众号_搜云库_每天更新
2018/11/13
0
1
Tengine-Ngnix高级版

Tengine介绍 Tengine是由淘宝网发起的Web服务器项目。它在Nginx的基础上,针对大访问量网站的需求,添加了很多高级功能和特性。Tengine的性能和稳定性已经在大型的网站如淘宝网,天猫商城等得...

java技术栈
2017/11/20
0
0
公司口头offer给了,又扯走流程,弄了几天,又说再考虑下

本人java从事4年,深圳,大专学历。之前因为一些原因离职,之前从事sp(增值业务),手游后端,智能家居后端工作,在俩家公司都算的上核心开发者,当然,我们公司团队也不大,前段时间因一些...

fxuantiue0400
2015/11/12
10K
16
聊聊最近的面试

楼主4年java开发,水平一般,前段时间耗时1周,面了10多家公司,现已入职。 在此记录下这段经历,顺别侃侃。 公司们: 泉壹贷,好像是这名儿。医疗业内的p2p,面试过了,钱没谈妥。技术面试官...

暗夜君王
2016/09/14
5.3K
20

没有更多内容

加载失败,请刷新页面

加载更多

怎么选择数据服务器?请记住这五条

我们应当都知道“数据无价”这个词,既然数据那么主要,选择一款安全稳定的数据服务器是很有必要的,那么如何选择一款牢靠的,稳定的数据服务器呢?我们从五个方面下手,协助您体系的了解数据...

linux-tao
20分钟前
1
0
第一讲:编写TCP Socket小程序

根据下面的步骤编写TCP Socket小程序。注意:作者必须是自己的名字。结果如下: 步骤: 1、用VC建立服务器程序 创建一个win32控制台程序 上面的代码如下,编写代码的时候切换到FileView界面,...

一匹狼工作室
22分钟前
2
0
python-protobuf2uml

首先这篇文章是参考的https://github.com/vak/protobuf2uml 本篇文章都是基于python3的 下面首先我们说一下python3的安装 wget https://github.com/protocolbuffers/protobuf/releases/down...

yiduwangkai
23分钟前
1
0
mysql通过source恢复大表小计

最近迁移一个数据库,500多张表大概600多万条数据,通过navicat导出的数据,再通过source命令导入到mysql8.0 之前也做过类似的工作,但是却从来没有这么慢过,一个小时了还没有完成,之前在笔...

休辞醉倒
24分钟前
1
0
Java、Python、C++、PHP、JavaScript这5大编程语言,我究竟该选哪个?

很多朋友在后台给我留言,问:现在这么多编程语言,Python、Java、PHP、C++、JavaScript等,究竟哪种最流行?我想这应该也是你的困扰吧! 其实他们各有优势,但是对于选择困难的程序员而言,...

Java领航员
41分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部