后端面试必备知识点
本文正在参与【[ 一起秋招吧 ] 】 征文活动,一起来聊聊校招的那些事吧,牛客周边和百元京东卡等你来领~
大家好,我是小羽,专注于后端开发相关知识的分享。今天将给大家带来的是关于后端面试常考察的必备知识点。
单元测试
我们在平时开发过程中,当完成自己的功能模块后,都需要自测一遍,这样可以保证代码的准确性,减少不必要的 bug 出现。
用的最多的也就是 junit 进行单元测试了,使用的是 junit4 这种基于注解的方式来进行单元测试。
常用注解:
1、为了和 spring 集成获取配置的 bean, 通常使用 @RunWith
来加载 springjunit 这个核心类;
2、使用 @ContextConfiguration
来加载相关的配置的文件;
3、通过 @Resource
按名字来注入具体的 bean, 最后在需要测试的方法上面加上 @Test 来进行单元测试。
测试原则:
- 源代码和测试代码需要分开;
- 测试类和目标源代码的类应该位于同一个包下面,即它们的包名应该一样;
- 测试的类名之前或之后加上
@Test
,测试的方法名通常也以 test 开头。
代码示例:
@RunWith(SpringJUnit4ClassRunner.class)//运行spring相关环境 相当于spring监听功能 @ContextConfiguration(locations={"classpath:spring-common.xml","classpath:spring-datasource.xml"})//读取spring配置文件 不识别* 只能识别具体文件 多个配置文件使用string数据传递 public class TestSpring { //注入Service层 private @Resource UserService userService; @Test public void testFind(){ List<User> userList = userService.findAllUserInfo(); for (User user : userList) { System.err.println(user.toString()); } } }
SQL 语句执行顺序
我们在编写 sql 时,查询中用到的关键词主要包含六个,并且他们的顺序依次为:select--from--where--group by--having--order by
在这里 select
和 from
是必须的,其他关键词是可选的,这六个关键词的执行顺序与 sql 语句的书写顺序并不是一样的,而是按照下面的顺序来执行:from--where--group by--having--select--order by
from:需要从哪个数据表检索数据
where:过滤表中数据的条件
group by:如何将上面过滤出的数据分组
having:对上面已经分组的数据进行过滤的条件
select:查看结果集中的哪个列,或列的计算结果
order by:按照什么样的顺序来查看返回的数据
HashMap 底层原理
HashMap 的底层是一个数组结构,数组中的每一项又是一个链表。当新建一个 HashMap 的时候,就会初始化一个数组。Entry 就是数组中的元素,每个 Entry 其实就是一个 key-value 对,它持有一个指向下一个元素的引用,这就构成了链表。
HashMap 在底层将 key-value 当成一个整体进行处理,这个整体就是一个 Entry 对象。
HashMap 底层采用一个 Entry[]
数组来保存所有的 key-value 对,当需要存储一个 Entry 对象时,会根据 hash 算法来决定其在数组中的存储位置,再根据 equals 方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Entry时,也会根据 hash 算法找到其在数组中的存储位置,再根据 equals 方法从该位置上的链表中取出该 Entry。
默认是构建一个初始容量为 16,负载因子为 0.75 的 HashMap。也就是说,默认情况下,数组大小为16,那么当 HashMap 中元素个数超过 160.75=12 的时候,就把数组的大小扩展为 216=32,即扩大一倍,然后重新计算每个元素在数组中的位置,而这是一个非常消耗性能的操作,所以如果我们已经预知 HashMap 中元素的个数,那么预设元素的个数能够有效的提高 HashMap 的性能。
Http 协议原理
HTTP 是一个超文本传输协议,属于 OSI 七层模型的应用层,由请求和响应构成,是一个标准的客户端服务器模型。HTTP是无状态的也就是说同一个客户端的这次请求和上次请求是没有对应关系。
工作流程:
1、当发送一个http请求时,首先客户机和服务器会建立连接;
2、发送请求到服务器,请求中包含了要访问的url地址,请求的方式(get/post),以及要传递的参数和头信息;
3、服务器接到请求后会进行响应,包括状态行,状态码,响应头,以及要响应的主体内容;
4、客户端接收到请求后将其展示到浏览器上然后断开和服务器端的连接。
长连接与短连接
在 HTTP/1.0 中,默认使用的是短连接。也就是说,浏览器和服务器每进行一次 HTTP 操作,就建立一次连接,但任务结束就中断连接。
从 HTTP/1.1 起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头有加入这行代码:
Connection:keep-alive
在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输 HTTP 数据的 TCP 连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。Keep-Alive 不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。实现长连接要客户端和服务端都支持长连接。
HTTP 协议的长连接和短连接,实质上是 TCP 协议的长连接和短连接。
GET、POST 区别
1、GET 提交的数据会放在 URL
之后,以 ?
分割 URL 和传输数据,参数之间以 &
相连,POST 方法是把提交的数据放在 HTTP 包的 Body 中。
2、GET 提交的数据大小有限制,最多只能有 1024 字节(因为浏览器对 URL 的长度有限制),而 POST 方法提交的数据没有限制。
3、通常用 Post
进行文件上传而 get 是不支持的。
4、GET 方式没有 POST 方式安全。
集合
Hashtable、HashMap 区别
Map 是一个以键值对存储的接口,Map下有两个具体的实现,分别是 HashMap 和 HashTable。
主要区别:
2.HashMap 是线程非安全的,HashTable 是线程安全的,所以 HashMap 的效率高于 HashTable。
3.HashMap 允许键或值为空,而 HashTable 不允许键或值为空。
Set、List、Collection、Collections 区别
1、List 和 Set 都是接口,他们都继承于接口 Collection;
2、List 是一个有序的可重复的集合,而 Set 是一个无序的不可重复的集合。
3、Collection 是集合的顶层接口,Collections 是一个封装了众多关于集合操作的静态方法的工具类,因为构造方法是私有的,所以不能实例化。
StringBuffer、StringBuilder、String 区别
分类 | 字符串类型 | 是否可变 | 字符串拼接 |
---|---|---|---|
String | 字符串常量 | 不可变 | 使用字符串拼接时是不同的2个空间 |
StringBuffer | 字符串变量 | 可变 | 线程安全,字符串拼接直接在字符串后追加 |
StringBuilder | 字符串变量 | 可变 | 非线程安全,字符串拼接直接在字符串后追加 |
1、StringBuilder 执行效率高于 StringBuffer 高于 String。
2、String 是一个常量,是不可变的,所以对于每一次 +=
赋值都会创建一个新的对象,StringBuffer 和 StringBuilder 都是可变的,当进行字符串拼接时采用 append
方法,在原来的基础上进行追加,所以性能比 String 要高,又因为 StringBuffer 是线程安全的而 StringBuilder 是线程非安全的,所以 StringBuilder 的效率高于 StringBuffer。
3、对于大数据量的字符串的拼接,采用 StringBuffer,StringBuilder。
缓存理解
缓存是为了提高应用程序的性能,减少数据库的访问次数,缓存的存储介质可以内存或者硬盘,通常将数据存储在内存里,确切的说是 jvm
的内存中。
缓存是基于 Map 这种思想构建的,以键值对的方式进行存取,之所以还可以将缓存的数据存储在硬盘中,是因为内存资源相当有限和宝贵,所以当内存资源不足的时候,就可以将其存储到硬盘中,虽然硬盘的存取速度比内存要慢,但是因为减少了网络通信量,所以还是提高程序的性能。
分类:
1、客户端缓存通常指的是 IE 浏览器的缓存,
2、服务器端缓存指的 web 服务器的缓存,通常可以通过第三方组件实现,如 redis。
我们通常将那些频繁访问但是又不是经常改变的数据进行缓存。为了保证缓存数据的有效性,在数据发生改变的时候,我们要刷新缓存,避免脏数据的出现。
刷新策略:
定时刷新
手动刷新
缓存层次:
jsp-->action-->service(通常放置在service)-->dao,缓存越靠前对性能的提升越大。
缓存空间不足需要进行清理的时候需要使用缓存策略。
缓存策略:
1、LRU 最近最少使用原则。
2、FIFO 先进先出的缓存策略。
Redis 应用场景
随着数据量的增长,MySQL 已经满足不了大型互联网类应用的需求。因此,Redis 基于内存存储数据,可以极大的提高查询性能,对产品在架构上很好的补充。在某些场景下,可以充分的利用 Redis 的特性,大大提高效率。
缓存
对于热点数据,缓存以后可能读取数十万次,因此,对于热点数据,缓存的价值非常大。例如,分类栏目更新频率不高,但是绝大多数的页面都需要访问这个数据,因此读取频率相当高,可以考虑基于 Redis 实现缓存。
会话缓存
此外,还可以考虑使用 Redis 进行会话缓存。例如,将 web session 存放在 Redis 中。
时效性
例如验证码只有60秒有效期,超过时间无法使用,或者基于 Oauth2 的 Token 只能在 5 分钟内使用一次,超过时间也无法使用。
访问频率
出于减轻服务器的压力或防止恶意的洪水攻击的考虑,需要控制访问频率,例如限制 IP 在一段时间的最大访问量。
计数器
数据统计的需求非常普遍,通过原子递增保持计数。例如,应用数、资源数、点赞数、收藏数、分享数等。
社交列表
社交属性相关的列表信息,例如,用户点赞列表、用户分享列表、用户收藏列表、用户关注列表、用户粉丝列表等,使用 Hash 类型数据结构是个不错的选择。
记录用户判定信息
记录用户判定信息的需求也非常普遍,可以知道一个用户是否进行了某个操作。例如,用户是否点赞、用户是否收藏、用户是否分享等。
交集、并集和差集
在某些场景中,例如社交场景,通过交集、并集和差集运算,可以非常方便地实现共同好友,共同关注,共同偏好等社交关系。
热门列表与排行榜
按照得分进行排序,例如,展示最热、点击率最高、活跃度最高等条件的排名列表。
最新动态
按照时间顺序排列的最新动态,也是一个很好的应用,可以使用 Sorted Set 类型的分数权重存储 Unix 时间戳进行排序。
消息队列
Redis 能作为一个很好的消息队列来使用,依赖 List 类型利用 LPUSH 命令将数据添加到链表头部,通过 BRPOP 命令将元素从链表尾部取出。同时,市面上成熟的消息队列产品有很多,例如 RabbitMQ。因此,更加建议使用 RabbitMQ 作为消息中间件。
Aajax 理解
AJAX 全称异步 JavaScript 及 XML,核心是 JavaScript 中的 XmlHttpRequest(XHR),使用ajax可以提高用户的体验度,进行异步数据传输从而提高性能。
解决 ajax 不能跨域问题:
dataType:'jsonp',可以通过设置动态的 script 标签,通过 jsonp 来解决 ajax 跨域的问题,而 jsonp 的实质就是通过动态添加 script 标签来实现的。
$.ajax({ url: some.php, async: false, success : function(){ } });
解析 xml 方式
dom4j
dom4j 是一个 Java 的 XML API,类似于 jdom,用来读写 XML 文件的。dom4j 是一个非常优秀的 Java XML API,具有性能优异、功能强大和容易使用的特点,同时它也是一个开放源代码的软件。
sax
SAX(simple API for XML)是一种 XML 解析的替代方法。相比于 DOM,SAX 是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。而且相比于DOM,SAX可以在解析文档的任意时刻停止解析,但任何事物都有其相反的一面,对于SAX来说就是操作复杂。
jaxb
JAXB(Java Architecture for XML Binding) 是一个业界的标准,是一项可以根据 XML Schema 产生 Java 类的技术。该过程中,JAXB 也提供了将 XML 实例文档反向生成 Java 对象树的方法,并能将 Java 对象树的内容重新写到 XML 实例文档。
从另一方面来讲,JAXB 提供了快速而简便的方法将 XML 模式绑定到 Java 表示,从而使得 Java 开发者在 Java 应用程序中能方便地结合 XML 数据和处理函数。
dom4j、sax 区别
dom4j 不适合大文件的解析,因为它是一下子将文件加载到内存中,所以有可能出现内存溢出,sax 是基于事件来对 xml 进行解析的,所以他可以解析大文件的 xml。
所以 dom4j 可以对 xml 进行灵活的增删改查和导航,而 sax 没有这么强的灵活性,sax 经常是用来解析大型 xml
文件,而要对 xml 文件进行一些灵活(crud)操作就用 dom4j。