JAVA面试总结(初版)

前端

1.HTML

2.方法

2.CSS

3.JS

4.JQuery

4.1.jquery的事件绑定和事件委派的区别是什么

事件绑定:将事件直接与元素进行绑定

事件委派:多用于很多元元素都要绑定事件的情况下,通过子节点绑定的元素传给父节点,来同一管理全部后代子元素,避免了很多重复的事件绑定

image-20210413113205333

4.2、说出10个jquery的选择器

JAVA面试总结(初版)_第1张图片

JAVA面试总结(初版)_第2张图片

JAVA面试总结(初版)_第3张图片

4.3.哪种方式更加高效document.getElementID(‘id’)还是$(‘#ID’)

第一种,因为它直接调用了JavaScript引擎。T…公社7十如

5.Ajax

6.VUE

1.什么是node js 起什么作用

Node js 是JS的引擎,浏览器都内置了node js 可以直接解析。但是我们可以通过装node js直接运行js程序

2.什么是npm 说出3个npm常用的命令

npm是node js的包管理工具、相当于java的maven、

安装包: npm install -D 包名(Jquery)@版本号

跟新包:npm update -D 包名

卸载包:npm uninstall -D 包名

JAVA面试总结(初版)_第4张图片

3.npm install -g -d -s是什么意思

-s 本项目使用

-D 开发时有用生产服务器提供相关包

-G 全局安装包

4.esmascript和javascript的区别

esmascript是一个标准规范

javascript是ecmascript是实现

5.babel插件是作用

Babel,在导入import和输出export等这些语法不能够没ES5解析,需要BABEL插件将其转化为能够被ES5解析的语法然后才能执行

6.es6中模块化编程是什么意思,简述一下

Es6中模块化编程就是export和import将其他JS文件导入到本文件使用

模块功能主要由两个命令构成: export和import。export命令用于规定模块的对外接口 import命令用于输入其他模块提供的功能。

7.VUE是什么

是实现了MVVM的模式的框架、

特征:双向绑定

即:改变数据就会改变视图、改变视图就会数据

8.什么是CDN

CDN的全称是Content Delivery Network,即内容分发网络。如果你想请求一个资源文件等,通过云服务器厂商,会给你最近的服务器来响应你的请求响应资源,降低网络拥塞,提高用户访问响应速度和命中率,CDN的关键技术主要有内容存储和分发技术。

9.解释比较mvvm、mvc、orm

mvvm类似于mvc

m:数据模型

v:视图

vm:把数据模型和视图连接起来的组件,相当于过去的c 特征是双向绑定mvc m:数据模型v:视图 c:控制层把数据模型和视图通过controller联系起来
orm: o:object对象 r:relation关系型数据库 m:mapper映射对象关系数据库映射以面向对象的思想操作数据库

10.常见的MVVM框架有哪些

image-20210413113829409

11.V-if v-show指令的区别

image-20210413113855654

12、V-bind v-model指令的区别

image-20210413113927695

13.什么是事件对象、怎样获得事件对象、事件对象可以干什么

JAVA面试总结(初版)_第5张图片

14.VUE中计算属性和方法的区别是什么

计算属性如果该属性后面没有改变的话,计算属性只会调用一次方法不管改不改变都会调用

15.JQuery中$(document).ready()是什么函数?为什么要用它?

jQuery使用document.ready来保证所要执行的代码是在DOM元素被加载完成的情况下执行

ready()函数用于在文档进入ready状态时执行代码。当DOM完全加载(例如HTML被完全解析DOM树构建完成时),jQuery允许你执行代码。使用$(document).ready()的最大好处在于它适用于所有浏览器,
jQuery帮你解决了跨浏览器的难题。

16.Javascript window.onload时间和JQery redy函数有什么区别

JAVA面试总结(初版)_第6张图片

17.Jquery中如何找到所有HTML select标签的选中项【选择器】

image-20210413114218536

18、JQuery中$(this)和this关键字在JQuery中有和不同

( t h i s ) 返 回 一 个 j Q u e r y 对 象 , 你 可 以 对 它 调 用 多 个 j Q u e r y 方 法 , 比 如 用 t e x t ( ) 获 取 文 本 , 用 v a l ( ) 获 取 值 等 等 。 而 t h i s 代 表 当 前 元 素 , 它 是 J a v a S c r i p t 关 键 词 中 的 一 个 , 表 示 上 下 文 中 的 当 前 D O M 元 素 。 你 不 能 对 它 调 用 j Q u e r y 方 法 , 直 到 它 被 (this)返回一个 jQuery对象,你可以对它调用多个jQuery方法,比如用 text()获取文本,用val()获取值等等。而this代表当前元素,它是JavaScript关键词中的一个,表示上下文中的当前DOM元素。 你不能对它调用jQuery方法,直到它被 (this)jQueryjQuerytext()val()thisJavaScriptDOMjQuery()函数包裹,例如$(this)。

19.使用CDN加载JQery库的主要优势是什么

节省宽带、提高页面加载速度

21.JQuery.post JQuery.get 和JQuery.ajax方法的区别

JAVA面试总结(初版)_第7张图片

22.说一下VUE父传子的过程

image-20210413114710496

23.说一下VUE中子传父的过程

JAVA面试总结(初版)_第8张图片

JAVA面试总结(初版)_第9张图片

24.VUE的每个钩子函数以及作用

JAVA面试总结(初版)_第10张图片

25.我们在created钩子函数中实行documentBy…可以吗 为什么

image-20210413114833376

26.webpack的作用

前端程序发布的时候,帮助我们把静态资源【js、图片】打包

27.eslint的作用

语法检查规范帮助我们写出严格的风格统一的代码

28.什么叫做spa什么叫做ssr各自的优缺点

JAVA面试总结(初版)_第11张图片

29.JSP的工作原理

在一个JSP文件第一次被请求时,JSP引擎把该JSP文件转换成为一个servleto

30.axios是什么特点有哪些

实现ajax异步通信

支持Promise API

拦截请求和响应

转换请求数据和响应数据

31.put delete post请求往后端传json对象的时候要怎么处理

@RequestBody

32.VUE中路由起什么作用

通过路径找组件

7.bootstrap

8.element UI

操作系统

1.linux

  1. linux的优点

  2. 什么是linux的内核版本、什么是发行版本、哪些常见的发行版本

    内核是系统的心脏,是运行程序和管理像磁盘和打印机等硬件设备的核心程序,它提供了一个在裸设备与应用程序间的抽象层。

内核的开发和规范由Linus领导的开发小组控制,版本唯一
Ubantu

centos

小红帽

  1. mkdir -p和不带p的区别

    mkdir -p 的好处是一次可以创建多级文件夹

  2. 查出占用了1111端口的进程、并且杀死用什么命令

    查出:losf -i :9000

    杀死:kill -9 9000

  3. 写出一下命令的作用

    | ls | |

| --------- | ---- |
| cd | |
| cp | |
| mv | |
| mkdir | |
| vi | |
| find | |
| tar | |
| chkconfig | |
| service | |
| cat | |
| less | |
| tail | |

2.网络通信

2.1.http 协议的状态码有哪些?含义是什么?

200 OK 客户端请求成功

301Moved Permanently(永久移除),请求的 URL 已移走。Response 中应该包含一个 Location URL,说明资源现在所处的位置

302found 重定向

400Bad Request 客户端请求有语法错误,不能被服务器所理解

401Unauthorized 请求未经授权,这个状态代码必须和 WWW-Authenticate 报头域一起使用

403 Forbidden 服务器收到请求,但是拒绝提供服务

404 Not Found 请求资源不存在,eg:输入了错误的 URL 500 Internal Server Error 服务器发生不可预期的错误

503 Server Unavailable 服务器当前不能处理客户端的请求,一段时间后可能恢复正常

2.2.Http 的请求报文组成?

请求行:

1、是请求方法,GET 和POST 是最常见的HTTP 方法,除此以外还包括 DELETE、HEAD、OPTIONS、 PUT、TRACE。

2、为请求对应的 URL 地址,它和报文头的 Host 属性组成完整的请求 URL。

3、是协议名称及版本号。请求头:

是 HTTP 的报文头,报文头包含若干个属性,格式为“属性名:属性值”,服务端据此获取客户端的信息。

与缓存相关的规则信息,均包含在 header 中请求体:

是报文体,它将一个页面表单中的组件值通过 param1=value1¶m2=value2 的键值对形式编码成一个格式化串,它承载多个请求参数的数据。不但报文体可以传递请求参数,请求 URL 也可以通过类似于“/chapter15/user.html? param1=value1¶m2=value2”的方式传递请求参数。

2.3.一次完整的 Http 请求是怎样的?

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

2.4.Tcp 和 Udp 的区别?

  1. 基于连接与无连接;

  2. 对系统资源的要求(TCP 较多,UDP 少);

  3. UDP 程序结构较简单;

  4. 流模式与数据报模式 ;

  5. TCP 保证数据正确性,UDP 可能丢包,TCP 保证数据顺序,UDP 不保证。

2.5.SSL 协议的三个特性

私密性:在握手协议定义了会话密钥后,所有的消息都被加密。

确认性:尽管会话的客户端认证是可选的,但是服务器端始终是被认证的。 可靠性:传送的消息包括消息完整性检查。

2.6.TCP 的三次握手与四次挥手

第一次握手:建立连接时,客户端发送 syn 包(syn=x)到服务器,并进入 SYN_SENT 状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。

第二次握手:服务器收到 syn 包,必须确认客户的 SYN(ack=x+1),同时自己也发送一个 SYN 包(syn=y),即 SYN+ACK 包,此时服务器进入 SYN_RECV 状态;

第三次握手:客户端收到服务器的 SYN+ACK 包,向服务器发送确认包 ACK(ack=y+1), 此包发送完毕,客户端和服务器进入 ESTABLISHED(TCP 连接成功)状态,完成三次握手。

1) 客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其 序列号为 seq=u(等于前面已经传送过来的数据的最后一个字节的序号加 1),此时,客户端进入 FIN-WAIT-1(终止等待 1)状态。 TCP 规定,FIN 报文段即使不携带数据,也要消耗一个序号。

2) 服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号 seq=v,此时,服务端就进入了 CLOSE-WAIT(关闭等待)状态。TCP 服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个 CLOSE-WAIT 状态持续的时间。

3) 客户端收到服务器的确认请求后,此时,客户端就进入 FIN-WAIT-2(终止等待 2) 状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。

4) 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1, 由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为 seq=w,此时, 服务器就进入了 LAST-ACK(最后确认)状态,等待客户端的确认。

5) 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的 序列号是 seq=u+1,此时,客户端就进入了 TIME-WAIT(时间等待)状态。注意此时 TCP 连接还没有释放,必须经过 2∗ ∗ MSL(最长报文段寿命)的时间后,当客户端撤销相应的 TCB 后,才进入 CLOSED 状态。

6) 服务器只要收到了客户端发出的确认,立即进入 CLOSED 状态。同样,撤销 TCB 后, 就结束了这次的 TCP 连接。可以看到,服务器结束 TCP 连接的时间要比客户端早一些。

2.7.为什么连接的时候是三次握手,关闭的时候却是四次握手?

因为当 Server 端收到 Client 端的 SYN 连接请求报文后,可以直接发送 SYN+ACK 报文。其中 ACK 报文是用来应答的,SYN 报文是用来同步的。但是关闭连接时,当 Server 端收到FIN 报文时,很可能并不会立即关闭 SOCKET,所以只能先回复一个 ACK 报文,告诉 Client 端,“你发的 FIN 报文我收到了”。只有等到我 Server 端所有的报文都发送完了,我才能发送FIN 报文,因此不能一起发送。故需要四步握手。

2.8. 如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP 还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置 为 2 小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后

每隔 75 秒钟发送一次。若一连发送 10 个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

2.9.http 中重定向和请求转发的区别?

本质区别:转发是服务器行为,重定向是客户端行为。

重定向特点:两次请求,浏览器地址发生变化,可以访问自己 web 之外的资源,传输的数据会丢失。

请求转发特点:一次强求,浏览器地址不变,访问的是自己本身的 web 资源,传输的数据不会丢失。

2.10. GET 和 POST 的区别?

1、GET 请求的数据会附在 URL 之后(就是把数据放置在 HTTP 协议头中),以?分割 URL 和传输数据,参数之间以&相连,如:login.action?name=zhagnsan&password=123456。POST 把提交的数据则放置在是 HTTP 包的包体中。

2、GET 方式提交的数据最多只能是 1024 字节,理论上 POST 没有限制,可传较大量的数据。其实这样说是错误的,不准确的:“GET 方式提交的数据最多只能是 1024 字节",因为 GET 是通过 URL 提交数据,那么 GET 可提交的数据量就跟 URL 的长度有直接关系了。而实际上,URL 不存在参数上限的问题,HTTP 协议规范没有对 URL 长度进行限制。这个限制是特定的浏览器及服务器对它的限制。IE 对 URL 长度的限制是 2083 字节(2K+35)。对于其他浏览器,如 Netscape、FireFox 等,理论上没有长度限制,其限制取决于操作系统的支持

3、POST 的安全性要比 GET 的安全性高。注意:这里所说的安全性和上面 GET 提到的“安全”不是同个概念。上面“安全”的含义仅仅是不作数据修改,而这里安全的含义是真正的 Security 的含义,比如:通过 GET 提交数据,用户名和密码将明文出现在 URL 上,因为登录页面有可能被浏览器缓存,其他人查看浏览器的历史纪录,那么别人就可以拿到你的账号和密码了,除此之外,使用 GET 提交数据还可能会造成 Cross-site request forgery 攻击。

4、Get 是向服务器发索取数据的一种请求,而 Post 是向服务器提交数据的一种请求, 在 FORM(表单)中,Method 默认为"GET",实质上 GET 和 POST 只是发送机制不同,并不是一个取一个发。

2.11.Http 与 Https 的区别

1、HTTP 的 URL 以 http:// 开头,而 HTTPS 的 URL 以 https:// 开头

2、HTTP 是不安全的,而 HTTPS 是安全的

3、HTTP 标准端口是 80 ,而 HTTPS 的标准端口是 443

4、在 OSI 网络模型中,HTTP 工作于应用层,而 HTTPS 的安全传输机制工作在传输层

5、HTTP 无法加密,而 HTTPS 对传输的数据进行加密

6、HTTP 无需证书,而 HTTPS 需要 CA 机构 wosign 的颁发的 SSL 证书

2.12. 什么是 Http 协议无状态协议?怎么解决 Http 协议无状态协议?

无状态协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息也就是说,当客户端一次 HTTP 请求完成以后,客户端再发送一次 HTTP 请求,HTTP 并不知道当前客户端是一个”老用户“。

可以使用 Cookie 来解决无状态的问题,Cookie 就相当于一个通行证,第一次访问的时候给客户端发送一个 Cookie,当客户端再次来的时候,拿着 Cookie(通行证),那么服务器就知道这个是”老用户“。

2.13.HTTPS 工作原理

一、首先 HTTP 请求服务端生成证书,客户端对证书的有效期、合法性、域名是否与请求的域名一致、证书的公钥(RSA 加密)等进行校验;

二、客户端如果校验通过后,就根据证书的公钥的有效, 生成随机数,随机数使用公钥进行加密(RSA 加密);

三、消息体产生的后,对它的摘要进行 MD5(或者 SHA1)算法加密,此时就得到了 RSA

签名;

四、发送给服务端,此时只有服务端(RSA 私钥)能解密。

五、解密得到的随机数,再用 AES 加密,作为密钥(此时的密钥只有客户端和服务端知道)。

数据库

1.mysql

1.MySql 的存储引擎有哪些,区别是什么

MySQL 常见的三种存储引擎为 InnoDB、MyISAM 和 MEMORY。1、事务安全:

InnoDB 支持事务安全,MyISAM 和 MEMORY 两个不支持。

2、存储限制:

InnoDB 有 64TB 的存储限制,MyISAM 和 MEMORY 要是具体情况而定。

3、空间使用:

InnoDB 对空间使用程度较高,MyISAM 和 MEMORY 对空间使用程度较低。

4、内存使用:

InnoDB 和 MEMORY 对内存使用程度较高,MyISAM 对内存使用程度较低。

5、插入数据的速度:

InnoDB 插入数据的速度较低,MyISAM 和 MEMORY 插入数据的速度较高。

6、对外键的支持:

InnoDB 对外键支持情况较好,MyISAM 和 MEMORY 两个不支持外键。

2.触发器的作用?

触发器是****一种特殊的存储过程****,主要是通过事件来触发而被执行的。它可以强化约束, 来维护数据的完整性和一致性,可以跟踪数据库内的操作从而不允许未经许可的更新和变化。可以****联级运算****。如,某表上的触发器上包含对另一个表的数据操作,而该操作又会导致该表触发器被触发。

3.什么是存储过程?用什么来调用?

存储过程是一个预编译的 SQL 语句,优点是允许模块化的设计,就是说只需创建一次, 以后在该程序中就可以调用多次。如果某次操作需要执行多次 SQL,使用存储过程比单纯 SQL语句执行要快。

调用:

1) 可以用一个命令对象来调用存储过程。

2) 可以供外部程序调用,比如:java 程序。

4.存储过程的优缺点。

优点:

1) 存储过程是预编译过的,执行效率高。

2) 存储过程的代码直接存放于数据库中,通过存储过程名直接调用,减少网络通讯。

3) 安全性高,执行存储过程需要有一定权限的用户。

4) 存储过程可以重复使用,可减少数据库开发人员的工作量。缺点:移植性差

5.SQL 优化的具体操作

1、尽量避免使用 select ,返回无用的字段会降低查询效率。优化方式:使用具体的字段代替,只返回使用到的字段。

2、尽量避免使用 in 和 not in,会导致数据库引擎放弃索引进行全表扫描。

优化方式:如果是连续数值,可以用 between 代替。如果是子查询,可以用 exists 代替。

3、尽量避免在字段开头模糊查询,会导致数据库引擎放弃索引进行全表扫描。 优化方式:尽量在字段后面使用模糊查询。

4、尽量避免进行 null 值的判断,会导致 。优化方式:可以给字段添加默认值 0,对 0 值进行判断。

6.事务的四个特性

原子性(Atomicity):

原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成 功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。

一致性(Consistency):

事务开始前和结束后,数据库的完整性约束没有被破坏。比如 A 向 B 转账,不可能 A 扣了钱,B 却没收到。

隔离性(Isolation):

隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的 事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。同一时间,只允许一 个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如 A 正在从一张银行卡中取钱,在 A 取钱的过程结束前,B 不能向这张卡转账。

持久性(Durability):

持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在 数据库系统遇到故障的情况下也不会丢失提交事务的操作。

7. 数据库乐观锁,悲观锁的区别,怎么实现

悲观锁(Pessimistic Lock),顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞挂起直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁,读锁,写锁等, 都是在做操作之前先上锁。

乐观锁(Optimistic Lock),顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改数据,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这 个数据,乐观锁适用于多读的应用类型,这样可以提高吞吐量。

两种锁各有优缺点,乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这 样就可以省去锁的开销,加大系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的 进行 retry,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。

8.事务的并发问题

1、脏读:事务 A 读取了事务 B 更新的数据,然后 B 回滚操作,那么A 读取到的数据是脏数据

2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务 A 多次读取的过程中,对数据作了更新并提交,导致事务 A 多次读取同一数据时,结果因此本事务先后两次读到的数据结果会不一致。

3、幻读:我该的数据被别人改了,像没改一样、幻读解决了不重复读,保证了同一个事务里,查询的结果都是事务开始时的状态(一致性)。

9.MySQL 的 MyISAM 与 InnoDB 两种存储引擎在,事务、锁级别,各自的适用场景?

MYISAM:由三个文件表示每个表 格式文件、数据文件、索引文件

​ 表级锁

​ 优点:可以被压缩成节省存储空间,可以转换为只读表加快检索速度

​ 缺点:不支持事务、外键

​ 适用:大量读少量写的情况下和适用压缩的只读表

INNODB:每个表在数据库目录中以.frm格式文件存储

​ 数据存储在tablespace表空间中无法被压缩和转换为只读表

​ 行级锁

​ 优点:支持事务、外键、安全性较高、支持级联删和更新,在mysql数据库崩溃后提供自动恢复机制

​ 适用:数据跟新较多的场景

Memory:每个表在数据库目录内以.frm格式存储

​ 表级锁

​ 表数据和索引被存储在内存中

​ 优点:查询效率最快

​ 缺点:不支持事务、外键,数据容易丢失

​ 适用:非永久需要的数据、或者可以从磁盘再生的数据

10.非关系型数据库和关系型数据库区别,优势比较

非关系型数据库的优势:

性能:****NOSQL**** ****是基于键值对的,****可以想象成表中的主键和值的对应关系,而且不需要经过 SQL 层的解析,所以性能非常高。

可扩展性:同样也是因为基于键值对,****数据之间没有耦合性****,所以非常容易水平扩展。 关系型数据库的优势:

复杂查询:可以用 SQL 语句方便的在一个表以及多个表之间做非常复杂的数据查询。事务支持:使得对于安全性能很高的数据访问要求得以实现。

11.数据库的五大范式

第一范式:(确保每列保持原子性)****所有字段值都是不可分解的原子值。****

第一范式是最基本的范式。如果数据库表中的所有字段值都是不可分解的原子值,就说 明该数据库表满足了第一范式。

第一范式的合理遵循需要根据系统的实际需求来定。比如某些数据库系统中需要用到“地址” 这个属性,本来直接将“地址”属性设计成一个数据库表的字段就行。但是如果系统经常会访 问“地址”属性中的“城市”部分,那么就非要将“地址”这个属性重新拆分为省份、城市、详细地址等多个部分进行存储,这样在对地址中某一部分操作的时候将非常方便。这样设计才算 满足了数据库的第一范式,如下表所示。

上表所示的用户信息遵循了第一范式的要求,这样在对用户使用城市进行分类的时候就非常 方便,也提高了数据库的性能。

第二范式:(确保表中的****每列都和主键相关****)在一个数据库表中,一个表中只能保存一种数 据,不可以把多种数据保存在同一张数据库表中。

第二范式在第一范式的基础之上更进一层。第二范式需要确保数据库表中的每一列都和 主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。也就是说在一个数 据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。

比如要设计一个订单信息表,因为订单中可能会有多种商品,所以要将订单编号和商品编号 作为数据库表的联合主键。

第三范式:(****确保每列都和主键列直接相关********,********而不是间接相关****) 数据表中的每一列数据都和主键直接相关,而不能间接相关。

第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。

比如在设计一个订单数据表的时候,可以将客户编号作为一个外键和订单表建立相应的关 系。而不可以在订单表中添加关于客户其它信息(比如姓名、所属公司等)的字段。

BCNF:符合 3NF,并且,主属性不依赖于主属性。

若关系模式属于第二范式,且每个属性都不传递依赖于键码,则 R 属于 BC 范式。

通常 BC 范式的条件有多种等价的表述:每个非平凡依赖的左边必须包含键码;每个决定因素必须包含键码。

BC 范式既检查非主属性,又检查主属性。当只检查非主属性时,就成了第三范式。满足BC

范式的关系都必然满足第三范式。

还可以这么说:若一个关系达到了第三范式,并且它只有一个候选码,或者它的每个候选码 都是单属性,则该关系自然达到 BC 范式。

一般,一个数据库设计符合 3NF 或 BCNF 就可以了。第四范式:要求把同一表内的多对多关系删除。第五范式:从最终结构重新建立原始结构。

12.什么是内连接、外连接、交叉连结、笛卡尔积等?

内连接: 只连接匹配的行

左外连接: 包含左边表的全部行(不管右边的表中是否存在与它们匹配的行),以及右边表中全部匹配的行

右外连接: 包含右边表的全部行(不管左边的表中是否存在与它们匹配的行),以及左边表中全部匹配的行

例如 1:

SELECT a.,b. FROM luntan LEFT JOIN usertable as b ON a.username=b.username

例如 2:

SELECT a.,b. FROM city as a FULL OUTER JOIN user as b ON a.username=b.username

全外连接: 包含左、右两个表的全部行,不管另外一边的表中是否存在与它们匹配的行。交叉连接: 生成笛卡尔积-它不使用任何匹配或者选取条件,而是直接将一个数据源中

的每个行与另一个数据源的每个行都一一匹配

13. SQL语言分类

数据查询语言 DQL 数据操纵语言 DML 数据定义语言 DDL 数据控制语言 DCL。

14.count(*)、count(1)、count(column)的区别

count(*)对行的数目进行计算,包含 NULL

count(column)对特定的列的值具有的行数进行计算,不包含 NULL 值。

count()还有一种使用方式,count(1)这个用法和 count(*)的结果是一样的。

15. 什么是索引?

数据库索引,是数据库管理系统中一个排序的数据结构,索引的实现通常使用 B 树及其变种 B+树。

在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构, 就是索引。

16.索引的作用?

协助快速查询、更新数据库表中数据。为表设置索引要付出代价的:

一是增加了数据库的存储空间

二是在插入和修改数据时要花费较多的时间(因为索引也要随之变动)。

17.索引的优缺点

创建索引可以大大提高系统的性能(优点):

  1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。

2. 可以大大加快数据的检索速度,这也是创建索引的最主要的原因。

  1. 可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。

  2. 在使用分组排序子句进行数据检索时,同样****可以显著减少查询中分组和排序的时****

间。

  1. 通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。 增加索引也有许多不利的方面(缺点):

  2. 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。

  3. 索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空

间,如果要建立聚簇索引,那么需要的空间就会更大。

  1. 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。

18.什么样的字段适合建索引?

唯一、不为空、经常被查询的字段

19.Hash 索引和 B+树索引的区别?

hash 索引,等值查询效率高,不能排序,不能进行范围查询;B+树数据有序,范围查询

20. MySQL 三种锁的级别

表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。

页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁 之间,并发度一般

行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

21.为什么不都用 Hash 索引而使用 B+树索引?

索引查找过程中就要产生磁盘 I/O 消耗,主要看 IO 次数,和磁盘存取原理有关。 根据B-Tree 的定义,可知检索一次最多需要访问 h 个节点。数据库系统的设计者巧妙利用了磁盘预读原理, 将一个节点的大小设为等于一个页,这样每个节点只需要一次 I/O 就可以完全

载入 局部性原理与磁盘预读

22.B 树和 B+树的区别

1、树,每个节点都存储 key 和 data,所有节点组成这棵树,并且叶子节点指针为 nul, 叶子结点不包含任何关键字信息。

2、B+树,所有的叶子结点中包含了全部关键字的信息,及指向含有这些关键字记录的 指针,且叶子结点本身依关键字的大小自小而大的顺序链接,所有的非终端结点可以看成是 索引部分,结点中仅含有其子树根结点中最大(或最小)关键字。 (而 B 树的非终节点也包含需要查找的有效信息)

23.为什么说 B+比 B 树更适合实际应用中操作系统的文件索引和数据库索引?

  1. B+的磁盘读写代价更低

B+的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对 B 树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越 多。一次性读入内存中的需要查找的关键字也就越多。相对来说 IO 读写次数也就降低了。

  1. B+tree 的查询效率更加稳定

由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同, 导致每一个数据的查询效率相当。

24.聚集索引和非聚集索引区别?

聚合索引(clustered index):

聚集索引表记录的排列顺序和索引的排列顺序一致,所以查询效率快,只要找到第一个索引值记录,其余就连续性的记录在物理也一样连续存放。聚集索引对应的缺点就是修改慢, 因为为了保证表中记录的物理和索引顺序一致,在记录插入的时候,会对数据页重新排序。聚集索引类似于新华字典中用拼音去查找汉字,拼音检索表于书记顺序都是按照 a~z 排列的,就像相同的逻辑顺序于物理顺序一样,当你需要查找 a,ai 两个读音的字,或是想一次寻找多个傻(sha)的同音字时,也许向后翻几页,或紧接着下一行就得到结果了。

非聚合索引(nonclustered index):

非聚集索引指定了表中记录的逻辑顺序,但是记录的物理和索引不一定一致,两种索引 都采用 B+树结构,非聚集索引的叶子层并不和实际数据页相重叠,而采用叶子层包含一个指向表中的记录在数据页中的指针方式。非聚集索引层次多,不会造成数据重排。

非聚集索引类似在新华字典上通过偏旁部首来查询汉字,检索表也许是按照横、竖、撇来排列的,但是由于正文中是 a~z 的拼音顺序,所以就类似于逻辑地址于物理地址的不对应。同时适用的情况就在于分组,大数目的不同值,频繁更新的列中,这些情况即不适合聚集索引。

根本区别:

聚集索引和非聚集索引的根本区别是表记录的排列顺序和与索引的排列顺序是否一致。

2.数据库优化

1.为什么mysql的表必须加上主键,mysql表是以什么形态保存在数据库中的

如果不加主键则表无序存放在磁盘中、如果加上了主键则把表转换成一个树状的结构

整个表变成了一个索引,也就是聚簇索引、一个表只有一个主键也就是一个聚簇索引

innodb memory表示以.frm保存在数据库中

myisam三个文件 数据 结构 索引

2.什么是聚集索引、什么是非聚集索引

聚簇索引就是主键索引、非聚簇索引索就是非主键索引

主键索引:根节点存的是主键、通过主键可查询到b+树的叶子节点的数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OS6kE8IS-1618290492797)(F:\pic\image-20210329212228886.png)]

非聚簇索引:根节点上存的是其他索引,叶子结点存的是主键、然后找到主键了还要在主键索引表中通过主键查询数据

JAVA面试总结(初版)_第12张图片

3.什么是覆盖索引

通过其他索引查询数据不需要回表查询

比如 id name name 为非聚簇索引

select name from table

4.B+树、B树、平衡二叉树、二叉查找树、的区别

二叉查找树:

左小右大:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g97qDer3-1618290492805)(F:/pic/image-20210329202118673.png)]

缺点:如果插入的都比根节点大或者小 容易长成歪脖子树

平衡二叉树:通过左旋、右旋解决二叉查找树歪脖子树的问题

平衡二叉树查找树基于二叉查找树优化而来,左叶子节点小于根节点、右叶子节点大于根节点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u5tKVKBP-1618290492808)(F:/pic/image-20210329202334157.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qA89OBgd-1618290492812)(F:/pic/image-20210329202350550.png)]

B树

当数据量过大时候,通过平衡二叉树存储占用内存过大,导致内存不够用就会让需要的数据放在内存,其他放在磁盘,一般而言磁盘访问世间为10ns内存为50ns,就会造成在磁盘的事件远远超过在在内存比较的事件说明大部分事件阻塞在磁盘IO上、这时候我们就需要减少磁盘读取次数、平衡二叉树做不到避免磁盘的操作、这时候就需要B数

B树一般在3层

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tjAg78Vu-1618290492815)(F:/pic/image-20210329204110497.png)]

B树 数据都在子节点上

B+树

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5djkb7CL-1618290492819)(F:/pic/image-20210329204234078.png)]

数据都在叶子节点上

区别:

B树查询事件复杂度是不固定的

B+树都要到叶子结点 事件复杂度是log(n)查询更加稳定

B+树由于节点不存才DATA都存在节点上,这样可以存跟多的key使得树更矮,IO次数更少磁盘读写代价低

b+树所有叶子节点构成一个有序链表、可以按照排序的进行范围查询、但是B树由于相邻的元素在内存中可能不相邻不支持范围查询命中率没有B+树好

5.InnoDB怎么保证一定有索引

首先如果不创建索引则会找唯一的字段、如果没有则会默认生成一个主键但是一般用自己的好

6.SQL查询顺序

select distinct 8 …7

from … 1

join 3

on 2

where … 4

group by … 5

having … 6

union 9

order by … 10

limit … 11

7.最左查询(匹配)

最左匹配是在建立了联合索引的情况下,从最左边的进行匹配,但是遇到范围查询会失效

最左匹配原则就是指在联合索引中,如果你的 SQL 语句中用到了联合索引中的最左边的索引,那么这条 SQL 语句就可以利用这个联合索引去进行匹配。

8.为什么一个表只有一个聚簇索引

因为聚集索引决定了表的存储时的排序,一个表只能有一个物理存储排序,所以只能有一个聚集索引,一个数据文件只能在一个状态下只能有一个顺序,因此跟它顺序相同的索引只能有一个,而与它排列顺序不同的可以有很多,所以,一个表只能有一个聚集索引,而可以有多个非聚集索引

3.redis

1.怎样保证缓存和 数据库中的数据一致【 怎样保证 缓存和数据库的双写一致】

​ 首先在查询的时候如果缓存中有则不执行查询方法、直接返回给缓存的数据(springboot使用 @Cacheable(value = “content”,key = “#typeid”)注释在查询方法上),如果缓存没有则执行查询方法,查完并且返回一份存在缓存中去。

​ 如果跟新(add update delete)了数据库的数据,在更新的方法上加上@CacheEvict(value = “content”,key = “#tContentType.typeId”)此注解是作用是:在更新之前和之后都删除缓存

​ 在之前删除:如果只在更新之后删除、数据库更新好了但是缓存没有删除好,就会造成数据库和缓存不一致,如果在之前删除,没有删除好缓存,数据库也不会更新,就还是一样的。

​ 在之后删除:保证,如果之后不删除,当数据库更新只在之前删除了缓存,当缓存删除之后数据库还没更新好另外一个线程读取了,把没更新好的数据又写到缓存中去了,就可以造成还是原来的缓存,不会和更新好了的数据保持一致。

2.redis 的持久化策略有哪些 项目中怎样选择

redis是支持将内存的数据持久化到磁盘上,持久化策略分为两种、一般默认的是RDB

RDB

RDB是Redis的默认持久化机制。是按照指定的时间间隔将数据持久到磁盘上,

​ 默认时间:

​ 1分钟10000个key改变 就执行RDB持久化

​ 5分钟10个key改变就执行RDB持久化

​ 15分钟1个key改变就执行RDB持久化

​ RDB持久化文件,速度比较快,存储的是一个二进制文件,传输起来很方便

但是RDB无法保证数据的绝对安全(可能还没到持久化条件被删除了)

AOF

​ AOP相对RDB持久化速度较慢、存储的是一个文本文件、到后面会越来越大传输困难

​ 持久化时间

​ appendfsync always:每执行一个写操作、立即持久化到AOF文件中、性能较低

​ appendfsc everysec:每秒执行一次持久化

​ appendfsync no:会根据你的操作系统不同,环境的不同,在一定时间内执行一次持久化

AOF相对RDB更安全、一般同时开启AOF和RDB

同时开启AOF和RBD注意事项

如果同时开启了AOF和RDB持久化,那么在Redis宕机重启后需要加载一个持久化文件,优先选择AOF文件

如果先开启了RDB,再开启AOF,如果RDB执行了持久化,那么RDB文件会被AOF文件覆盖

3. redis 的过期内存删除策略是什么

redis的删除策略分为两种:

定期删除:redis每隔一定的时间就会做一次扫描,如果key有过期了的就会删除,但是不会全部扫描所以即使有些key过期了也不会被删除,因为没有被扫描到

惰性删除:用的时候先查看一下是否有过期、如果过期了就删除、也可能导入过期了、一直没被用所以一直没有被删除

综合两种删除策略:有可能因为定期删除没有扫描到、惰性删除没有被使用到所以可能导致过期了一直没有被删除

4.redis的内存淘汰策略是什么,有哪些常见的淘汰策略

redis在内存满了的时候再添加一个新数据就会执行淘汰策略

volatile-lru:在内存不足的时候,redis会在设置过了生存时间的key中删除一个最近最少使用的key

allkeys-Iru:在内存不足时,Redis会在全部的key中干掉一个最近最少使用的key。

**volatile-lfu:**在内存不足时,Redis会在设置过了生存时间的key中干掉一个最近最少频次使用的key.

**allkeys-lfu:**在内存不足时,Redis会在全部的key中干掉一个最近最少频次使用的key,

**volatile-random:**在内存不足时,Redis会在设置过了生存时间的key中随机千掉一个。

**allkeys-random:**在内存不足时,Redis会在全部的key中随机干掉一个。

**volatile-ttl:**在内存不足时,Redis会在设置过了生存时间的key中干掉一个剩余生存时间最少的key。

**noeviction:(默认)**在内存不足时,直接报错。

lfu:次数热点

lru:时间热点

通常写一个lru算法采用LinkedHashMap

5.lru 和 lfu 指的是什么,描述一下 怎样实现lru 和 lfu 算法

lru是时间热点

lfu是访问次数的热点

LRU全称是Least Recently Used,即最近最久未使用的意思。
LRU算法的设计原则是:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。
LFU

6.什么是内存击穿 怎样防止

​ 内存击穿是值缓存中没有但数据库中有的数据(一般是指缓存到期),由于访问量过大同时读缓存,没有读到又同时去读数据库,造成数据库的压力过大

解决方案:

设置热点永不过期

加互斥锁

JAVA面试总结(初版)_第13张图片

​ 一、通过修改redis的配置文件、实现redis的密码校验


#redis.config
requirepass 密码

​ 二、三种客户端连接方式

​ redis-ch:在输入正常命令之前,先输入auth密码即可

​ 图形化界面:在连接redis的信息中添加验证的密码

​ JEDIS客户端

​ jedis.auth(password)

​ 使用jedisPool的方式

7.什么是内存穿透怎么防止

内存穿透是一直请求数据库和缓存没有的数据,缓存没有就会一直请求数据库

解决:如果是根据ID查询,如果ID是自增的将ID最大值放到redis中在查询之前直接比较一下

​ 如果不是自增长,将全部ID放在缓存的set中去,在用户查询之前去set中查看一下是否有这样的值

​ 获取客户端的IP地址、将IP访问添加限制

8.什么是内存雪崩 怎样防止

缓存雪崩是缓存的数据大面积到期,就会请求到数据库,导致数据库宕机

设置热点永不过期(不好)

数据预热:将发生大并发前让key过期时间分布均匀

9.redis的部署架构有哪些,方便用在什么样的好处

单机开发:开发的时候

主从复制:可以通过主从读写分离实现高并发(首先要主从复制)

哨兵模式:解决高可用的情况下

哨兵模式:
 监控:Sentinel会不断检查主服务和从服务是否正常运作
 通知:当被监控的某个redis服务器出现了问题,Sentinerl通过API脚本向管理员或者其他的应用程序发        送请求通知
 自动故障转移:当主节点不能正常工作时候,Sentinel会开始一次自动的故障转移操作,它会将与失效主               节点是主从关系,其中一个从节点升级为主节点,并且将其他的从节点指向新的主节点

集群:具备主从、高并发和哨兵的高可用 另外还解决了海量数据的问题

10.为什么redis的集群架构中,主节点的数量总是单数

一般集群是三主三从或者是五主五从 一台内存是32分给redis10G

redis集群是无中心化的,redis节点数必须是2n+1也就是奇数个

redis集群默认分配16384个

在存储数据的时候会进行crc16的算法,并且对16384进行取余,根据取余的结果将key-value放到对应的哈希曹中去,所有的主节点分这16384个哈希槽

为了保证数据的安全性,每一个集群的主节点至少要跟着一个丛节点,对每一个主节点单独搭建主从复制

当redis集群中超过半数宕机,redis集群就瘫痪了

JAVA面试总结(初版)_第14张图片

11.说一下redis主从复制的过程

从节点先拷贝备份文件(AOF文件或者RDB文件,先拷贝AOF文件)

然后再拷贝增量文件(日志文件,当发现日志有改变了)

image-20210402165012182

12.redis的hash曹有几个

16384

13.什么是reids哨兵模式,起什么作用

  • 主从读写分离解决了高并发的问题,哨兵模式解决了高可用的问题

  • 可以解决主从架构的单点故障的问题

  • 每一个主节点和从节点都有一个哨兵(Sentinel)

  • Sentinel会不断检查主服务器和从服务器是否运行正常,当redis服务器出现问题Sentinel会通过API脚本向管理员,或者其他的应用程序发送通知。

  • 自动故障转移:当主节点不能正常工作的时候,Sentinel会开始一次自动故障转移的操作,它会将和原来是失效的有主从关系的从节点升级为主节点,同时将其他的从节点指向新的主节点

  • JAVA面试总结(初版)_第15张图片

14.spring data redis的常见序列化方案和默认序列化方案是

JdkSerializationRedisSerializer
StringRedisSerializer
JacksonJsonRedisSerializer
默认是jdk

15.什么是redis 特征是什么

redis一款用C语言开发的基于key-value的内存数据库

特征是:

redis是c语言写的,开源的nosql数据库 和memcached类似,支持的数据类型很多.字符串(string)链表(list)集合(set)zset(有序集 合)hash(hash数据)等
redis支持多种排序方式
为了效率,存在内存当中,但与memcached不同的是会周期性更新数据写入磁盘,并在此基础实现主从同步(mster-slave)
速度快(内存中)
支持类型多
支持事务

16.为什么redis是单线程的效率还是很高

  • 由c语言写的

  • 是内存数据库速度快,绝大部分请求都是在内存操作(但是支持持久化)

  • 由于是单线程不需要多线程的上下文切换

  • 使用了多路I/O复用模型,非阻塞IO

redis 采用网络IO多路复用技术,来保证在多连接的时候系统的高吞吐量。
多路-指的是多个socket网络连接,复用-指的是复用一个线程。多路复用主要有三种技术:select,poll,epoll。epoll是最新的、也是目前最好的多路复用技术。
采用多路I/O复用技术:其一,可以让单个线程高效处理多个连接请求(尽量减少网络IO的时间消耗)。其二,Redis在内存中操作数据的速度非常快(内存里的操作不会成为这里的性能瓶颈)。主要以上两点造就了Redis具有很高的吞吐量。
采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求。

17.你们项目中哪些地方用到了redis

数据库的缓存用到了redis

集群分布式下的session共享用到了redis

实时排行榜

key-set一些交集并集的场景

key-list使用list结构实现栈和队列的结构等

用key-hash存对象等

18.redis常见的五种基本数据类型

  • String
  • List
  • Hash
  • Set
  • Zset

同时还可以用redis的其他数据结构存地图数据等

项目

1.开发运维部署

    1. 什么是JWT起什么作用

      json web token 在网络应用环境中传递声明
      Json Web Token,是基于Json的一个公开规范,这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息,
      适用于分布式站点的登陆场景
      可以用于加密
    2. 什么是单点登录系统,单点登录系统怎么实现

      单点登录SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下,
      用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任。
      以Cookie作为凭证媒介
      最简单的单点登录实现方式,是使用cookie作为媒介,存放用户凭证。
      用户登录父应用之后,应用返回一个加密的cookie,当用户访问子应用的时候,携带上这个cookie,授权应用解密cookie并进行校验,校验通过则登录当前用户。
    session共享
    通过jwt保存到前端
    通过redis保存到后端
    通过JSONP实现
    对于跨域问题,可以使用JSONP实现。
    用户在父应用中登录后,跟Session匹配的Cookie会存到客户端中,当用户需要登录子应用的时候,授权应用访问父应用提供的JSONP接口,
    并在请求中带上父应用域名下的Cookie,父应用接收到请求,验证用户的登录状态,返回加密的信息,子应用通过解析返回来的加密信息来验证用户,
    如果通过验证则登录用户。
    通过页面重定向的方式
    最后一种介绍的方式,是通过父应用和子应用来回重定向中进行通信,实现信息的安全传递。
    父应用提供一个GET方式的登录接口,用户通过子应用重定向连接的方式访问这个接口,如果用户还没有登录,则返回一个的登录页面,
    用户输入账号密码进行登录。如果用户已经登录了,则生成加密的Token,并且重定向到子应用提供的验证Token的接口,通过解密和校验之后,
    子应用登录当前用户。
  1. 分布式情况下 你们项目怎样实现session共享

    1、服务器实现的session复制或session共享,这类型的共享session是和服务器紧密相关的,比如webSphere
    或JBOSS在搭建集群时候可以配置实现session复制或session共享,但是这种方式有一个致命的缺点,就是不好扩
    展和移植,比如我们更换服务器,那么就要修改服务器配置。
    2、利用成熟的技术做session复制,比如12306使用的gemfire,比如常见的内存数据库如redis或memorycache,
    这类方案虽然比较普适,但是严重依赖于第三方,这样当第三方服务器出现问题的时候,那么将是应用的灾难。
    3、将 session维护在客户端,很容易想到就是利用cookie,但是客户端存在风险,数据不安全,而且可以存放的
    数据量比较小,所以将session维护在客户端还要对session中的信息加密。
    我们实现的方案可以说是第二种方案和第三种方案的合体,可以利用 gemfire 实现 session 复制共享,还可以将
    session维护在redis中实现session共享,同时可以将session维护在客户端的cookie中,但是前提是数据要加密。
  2. 前后端分离的情况下 你们项目怎样实现session 共享

  3. 什么是rbac、说出abac的表的设计

    Role-Based Access Control,基于角色的访问控制),就是用户通过角色和权限进行关联。
    共有五张表,分别为用户表、角色表、权限表、用户-角色关系表、角色-权限关系表。
    其中用户表于角色表是多对多的关系,角色表于权限表也是多对多关系
    1. 你们公司怎样做权限控制的

      给用户分配相应的权限,通过角色做相应的权限控制

    2. 请说出session和cookie的关系的区别

    3. 你们项目中哪些地方使用到了AOP请描述一下

      登陆验证、权限验证

    4. 蓝绿、灰度、滚动部署

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IfJOuUJB-1618290492839)(F:\pic\image-20210330084254407.png)]

    所谓蓝绿部署,是指同时运行两个版本的应用,如上图所示,蓝绿部署的时候,并不停止掉老版本,而是直接部署一套新版本,等新版本运行起来后,再将流量切换到新版本上。但是蓝绿部署要求在升级过程中,同时运行两套程序,对硬件的要求就是日常所需的二倍,比如日常运行时,需要10台服务器支撑业务,那么使用蓝绿部署,你就需要购置二十台服务器。

    滚动发布

    滚动发布能够解决掉蓝绿部署时对硬件要求增倍的问题。

    所谓滚动升级,就是在升级过程中,并不一下子启动所有新版本,是先启动一台新版本,再停止一台老版本,然后再启动一台新版本,再停止一台老版本,直到升级完成,这样的话,如果日常需要10台服务器,那么升级过程中也就只需要11台就行了。

    但是滚动升级有一个问题,在开始滚动升级后,流量会直接流向已经启动起来的新版本,但是这个时候,新版本是不一定可用的,比如需要进一步的测试才能确认。那么在滚动升级期间,整个系统就处于非常不稳定的状态,如果发现了问题,也比较难以确定是新版本还是老版本造成的问题

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w2qyPeP7-1618290492843)(F:\pic\image-20210330084424358.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aLzpyfTQ-1618290492845)(F:\pic\image-20210330084435409.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eUk0Hcys-1618290492847)(F:\pic\image-20210330084446707.png)]

    灰度发布

    灰度发布也叫金丝雀发布,起源是,矿井工人发现,金丝雀对瓦斯气体很敏感,矿工会在下井之前,先放一只金丝雀到井中,如果金丝雀不叫了,就代表瓦斯浓度高。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wMbYlIAV-1618290492851)(F:\pic\image-20210330084617120.png)]

    在灰度发布开始后,先启动一个新版本应用,但是并不直接将流量切过来,而是测试人员对新版本进行线上测试,启动的这个新版本应用,就是我们的金丝雀。如果没有问题,那么可以将少量的用户流量导入到新版本上,然后再对新版本做运行状态观察,收集各种运行时数据,如果此时对新旧版本做各种数据对比,就是所谓的A/B测试。

    当确认新版本运行良好后,再逐步将更多的流量导入到新版本上,在此期间,还可以不断地调整新旧两个版本的运行的服务器副本数量,以使得新版本能够承受越来越大的流量压力。直到将100%的流量都切换到新版本上,最后关闭剩下的老版本服务,完成灰度发布。

    如果在灰度发布过程中(灰度期)发现了新版本有问题,就应该立即将流量切回老版本上,这样,就会将负面影响控制在最小范围内。

    1. 你们公司多久上线一次

      2个星期

    2. 什么是iaas,paas,saas

      他们都是云服务模式:

    iaas:基础架构即服务:用户通过付费可以使用一些资源池(存储、计算等)

    paas:平台即服务:在Iaas上具备开发运行环境、提供IT组件,可以使用户将模块功能等嵌入到软件或者硬件中

    saas:软件即服务,软件拿来即用

    1. 简述一下什么是瀑布开发,什么是敏捷开发,什么是devops

      devops:边开发变运维

    cicd是其实现手段

    瀑布:集成太晚 交付太晚

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TTi5gSET-1618290492853)(F:/pic/image-20210330093052281.png)]

敏捷 迭代 每个小过程中是瀑布

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9ELMy3EJ-1618290492856)(F:/pic/image-20210330093334108.png)]

1)瀑布式
需求分析->设计:概要设计、详细设计->cut:coding、单元测试->(白盒测试)->集成测试:(黑盒测试)->部署
优点:文档齐整,周期长对程序员要求不高
缺点:集成晚、交付晚
2)敏捷式
把开发过程细分成多个阶段,每个阶段中有多个迭代周期,每个迭代周期中还是走瀑布模型
特点:作为整体工作,短迭代周期,每次迭代交付一些成果,关注业务优先级
基本上两个星期上一次线
3)devops(边运维,边开发)
ci:持续集成 可以将代码快速部署,测试新的开发模块与整体系统的集成问题,更快发现问题
cd:持续交付 持续部署
可以更快的部署尽可能减少部署新代码时所需的工作量

  1. 什么是ci cd,好处是什么

    CI 持续集成

    可以在早期就能发现一些问题便于解决

    繁琐的部署工作没有了。你的团队不在需要花费几天的时间去准备一个发布。

    你可以更快的进行交付,这样就加快了与客户之间的反馈环。

    轻松应对小变更,加速迭代

>CD持续交互 持续部署
>
>发布频率更快,因为你不需要停下来等待发布。每一处提交都会自动触发发布流。
>
>在小批量发布的时候,风险降低了,发现问题也可以很轻松的修复。
>
>客户每天都可以看到我们的持续改进和提升,而不是每个月或者每季度,或者每年。
  1. 简述一下你们公司的项目开发流程,多长时间上一次线

  2. 你们公司加班吗?一般什么时候加班

  3. 简述一下你们公司做ci cd的流程

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xusntAT0-1618290492860)(F:/pic/image-20210330181904569.png)]

  4. 有什么好办法能在用户感觉不到的情况下把咱的WEB系统升级了呢?

    蓝绿 资源占用大

    滚动 一般用于增加功能

    金丝雀

    都不会被感觉到

  5. 什么是ci cd 好处是什么

    ci

  6. 简述一下你们公司的项目开发流程 多长时间上一次线

2.具体项目

1.秒杀

1.1描述一下秒杀的实现过程 以及技术难点

​ 秒杀场次表 商品表 订单表

**一、**首先将描述的商品预热到redis并且显示秒杀商品到前端【秒杀】

**二、**然后写抢订单的逻辑,前端通过商品ID传给后端形成订单,并且商品数量减一【秒杀】

开抢!!!

**三、**生成延时队列,如果订单的状态改变了则证明购买成功了,如果没有改变没有支付成功,则加回商品【秒杀】

​ 1.点击抢购时生成商品订单(将商品ID传给后端,后端生成订单信息传给前端,前端购买生成商品订单),支付的时候在后端

​ 生成支付宝订单【支付】

​ 2.支付成功一半返回首页,同时支付宝给后端传给订单的信息【支付】

​ 3.当接到支付宝传给的订单的信息 进行延签【支付】

​ 4.严格的话会对订单的每个信息都进行比较【支付】

​ 5.如果没有问题则给支付宝返回一个success的问题并且修改订单状态【支付】

​ 6.如果不给支付宝返回一个success它会一天发送八次成功的信息给后端【支付】

​ 7.支付宝不同停的发送成功的消息可能会产生重复消费的问题(消息幂等)【支付】

如果订单的状态改变了则证明购买成功了,如果没有改变没有支付成功,则加回商品 【秒杀】

问题一、为什么购买太慢【秒杀】

如果使用雪花算法,大对象的工具类创建太慢了直接new出来每次购买的时候需要创建大对象非常耗时,解决办法:将其作为一个bean

问题二、如何防止一货多卖【秒杀】

1.如果使用synchronized锁不住分布式、如果使用乐观锁数据库的压力太大

2.使用redis的setnx作为锁,只有一个线程操作,【查看是否数量足够、形成新订单…】

image-20210411225047409

问题:1.不公平 如果数量还有很多但是我来的时候被其他线程锁住了,他有只买一个,而我因为没有锁直接退出去了

​ 2.一般setNX先加锁,再设置过期时间【防止线程死在里面锁就一直锁了】但是加锁和设置时间是两部操作

如果锁加了,时间还没设置好,线程死了就不会5S后自动释放锁了,又被锁死了

​ 3.如果线程就是超过了5S的执行时间呢【一般redis都是几毫秒 但是fullGC的时候会超过】,锁被释放,其他线程来了。当前 线程没操作完有会一货多卖

3.使用redisson可以解决以上三个问题

问题三、如何防止消息重复消费【支付】

当订单校验,延签都没问题了,返回给支付宝success失败了,支付宝又重新发了支付成功过来,就可能导致重复消费【一次30W 2次60W就亏大了】

解决:使用redis的setNX加锁

为消息ID 或者一个唯一标识作为KEY 并未其赋予一个初始状态

当消息消费成功改变状态,如果回应成功则不会有第二次同样的消息再来不用担心了

如果回应失败,但是状态已经改好了,第二次过来先判断状态,此时状态因为消费成功了状态改变了则直接相应支付宝

1: 描述一下秒杀的实现过程 以及技术难点
2: 锁解决什么样问题的,描述一下线程锁 悲观锁 乐观锁 分布式锁
2.1 什么是可重入锁 不可重入锁 自旋锁 可中断锁 公平锁 独享锁/共享锁 互斥锁/读写锁 分段锁
3:死锁怎样产生的, 怎样解决死锁问题
4:Arralist和LinkedList哪个是线程安全的?那线程安全的是什么?如果没有vertor 怎么保证ArrayList和LinkedList线程安全?用什么插件
5: 并发测试使用什么工具
6 redis 做分布式锁 和 zookeeper 做分布式锁的区别和各自的优势【背诵】
7: rabbitmq 延时队列怎样实现的 一般用在什么场景
8:怎样保证 两个人不能用同一个账户同时登录系统
9: 怎样保证两个人不能在 同一时间 用同一个账户登录
10:秒杀是怎么设计的
数据库设计 缓存预热 (数据结构 hash) 分布式锁(setnx) 延时队列 限流 JVM优化 堆3G 新生2G
11:秒杀系统JVM参数设置
12:如何用户拿到了秒杀商品的URL路由地址。怎么防止他提前下单
13:秒杀系统是否和商城系统分离
14:Redis怎么实现的秒杀方案,什么时候手动删除设置的锁资源

2.支付

1.支付流程

根据商户订单和价格等信息生成支付宝订单 根据支付宝订单支付 支付宝订单返回一个成功信息 根据状态修改商户订单状态

细节:幂等问题(消费成功 返回success 但是支付宝没有收到 过一会支付宝又发过来支付成功消息 就造成重复消费 解决:判断订单状态) 验签 订单信息比较 网络波动success没法给支付宝 支付宝一天发八次给我(确保支付成功后通知到商户) 防止被重复消费(查看订单状态)

JAVA面试总结(初版)_第16张图片

后端

1.Java

1.1Java基础

1.1.1、final关键字的作用

作用在变量上作为一个常量,第一次赋值后不可以被改变

作用在方法上、方法不能够被重写

作用在类上、类不可以被继承String…

1.1.2、JDK、JRE、jvm的区别

JDK:java开发工具包

JRE:java运行时环境

JVM:Java虚拟机

JDK包含了JRE,JRE包含了JVM,JDK里面有JAVA编译器JAVAC和调式工具等,JRE包含了JAVA的基础类库,如果只需要运行JAVA程序只需要JRE即可。JAVA跨平台是首先编译成字节码文件,然后通过JVM解释成相应平台的机器码,可以做到一次编译到处执行,JVM是跨平台的核心,但是JVM本身不是跨平台的,不同的平台有相应的JVM可以把字节码编译成相应平台的机器码并运行。

1.1.3、内存泄漏和内存溢出

内存泄漏:是程序申请内存后无法得到释放,一次可能不会有什么但是如果内存泄漏多了会造成内存溢出

**内存溢出:**是指应用程序在申请内存时,没有足够的内存空间供其使用。如我们在项目中对于大批量数据的导入,采用分批量提交的方式。

1.1.4**、反射中,Class.forName()和 ClassLoader.loadClass()的区别?**

Class.forName(className)方法,内部实际调用的方法是

Class.forName(className,true,classloader);

第 2 个 boolean 参数表示类是否需要初始化, Class.forName(className)默认是需要初始化, 一旦初始化, 就会触发目标对象的 static 块代码执行, static 参数也也会被再次初始化 ,ClassLoader.loadClass(className) 方 法 , 内 部 实 际 调 用 的 方 法 是ClassLoader.loadClass(className,false);第 2 个 boolean 参数,表示目标对象是否进行链接, false 表示不进行链接,由上面介绍可以,不进行链接意味着不进行包括初始化等一些列步骤,那么静态块和静态对象就不会得到执行

1.1.5、Int 和 Integer 的区别?

Integer 是 int 的包装类型,在拆箱和装箱中,二者自动转换.int 是基本类型,直接存数值; 而 integer 是对象;用一个引用指向这个对象.由于 Integer 是一个对象,在 JVM 中对象需要一定的数据结构进行描述,相比 int 而言,其占用的内存更大一些.

1.1.6、String、StringBuilder、StringBuffer 区别?

String 字符串常量 不可变 使用字符串 拼接时是不同的 2 个空间StringBuffer 字符串变量 可变 线程安全 字符串拼接直接在字符串后追加

StringBuilder 字符串变量 可变 非线程安全 字符串拼接直接在字符串后追加

  1. StringBuilder 执行效率高于 StringBuffer 高于 String.

  2. String 是一个常量,是不可变的,所以对于每一次+=赋值都会创建一个新的对象, StringBuffer 和 StringBuilder 都是可变的,当进行字符串拼接时采用 append 方法,在原来的基础上进行追加,所以性能比 String 要高,又因为 StringBuffer 是线程安全的而 StringBuilder 是线程非安全的,所以 StringBuilder 的效率高于StringBuffer.

  3. 对于大数据量的字符串的拼接,采用 StringBuffer,StringBuilder.

1.1.7、说几个常见的编译时异常

SQLException 提供有关数据库访问错误或其他错误的信息的异常。

IOexception 表示发生了某种 I / O 异常的信号。此类是由失败或中断的 I / O 操作产生的一般异常类

FileNotFoundException 当试图打开指定路径名表示的文件失败时,抛出此异常。ClassNotFoundException 找不到具有指定名称的类的定义。

EOFException 当输入过程中意外到达文件或流的末尾时,抛出此异常。

1.1.8、方法重载的规则?

方法名一致,参数列表中参数的顺序,类型,个数不同。 重载与方法的返回值无关,存在于父类和子类,同类中。 可以抛出不同的异常,可以有不同修饰符。

1.1.9、方法重写的规则?

参数列表、方法名、返回值类型必须完全一致,构造方法不能被重写;声明为 final 的方法不能被重写;声明为 static 的方法不存在重写(重写和多态联合才有意义);访问权限不能比父类更低;重写之后的方法不能抛出更宽泛的异常

1.1.10、throw 和 throws 的区别?

throw :

语句用在方法体内,表示抛出异常,由方法体内的语句处理。throw 是具体向外抛出异常的动作,所以它抛出的是一个异常实例,执行 throw 一定是抛出了某种异常。

throws:

throws 语句是用在方法声明后面,表示如果抛出异常,由该方法的调用者来进行异常的处理。throws 主要是声明这个方法会抛出某种类型的异常,让它的使用者要知道需要捕获的

异常的类型。throws 表示出现异常的一种可能性,并不一定会发生这种异常。

1.1.11、抽象类和接口的区别?

1.8之前

语法:

变量:接口中的变量只能是public static final修饰默认是常量, 抽象类中的变量可以用任何修饰符

代码块和静态代码块:抽象类可以有代码块和静态代码块接口没有

构造函数:抽象类有构造函数(任何修饰符),接口没有构造函数

普通方法:抽象类中可以有普通和抽象方法,接口都是抽象方法(1.8不一样)

实例化:抽象类和接口都不能被实例化

继承:继承抽象类必就把VM须实现所有的方法否则也必须声明为抽象类,普通类只能继承一个类可以实现多个接口

​ 但是接口可以继承多个接口

设计:抽象类:同一类事物的抽取,比如Dao层的封装,如BaseDao,DaseServiceImpl

接口:通常更像是一种标准的制定,定制系统之间的标准,例如

​ 单体项目:分层开发,interface作为各层之间的纽带,在controller中注入IuserService,在service中注入IuserDao

​ 分布式项目:面向服务的开发,抽取服务的service这个时候就会产生服务的提供者和服务的消费者两个角色这两个角色之间的纽带任然是接口

*接口的设计目的,是对类的行为进行约束,常用在框架的设计上,抽象类的实现目的,是代码复用,可以让这些类都派生于一个抽象类,在这个抽象类中实现了共有的方法,避免让所有的子类来实现这个共有的方法,这就达到了代码复用的目的*

1.8之后

​ 接口里面可以有实现的方法,必须是默认方法和静态方法

1.1.12、Java 的基础类型和字节大小?

1字节:byte boolean

2字节: char short

4字节:int flot

8字节:long double

1.1.13、四个访问修饰符合访问级别
本类 子类 其他包
public
peotetced
默认
privect
1.1.14、抽象类的意义?

1、为其他子类提供一个公共的类型

2、封装子类中重复定义的内容

3、定义抽象方法,子类虽然有不同的实现,但是定义时一致的

1.1.15、强引用和软引用和弱引用以及虚引用?
1、强引用

最普遍的一种引用方式,如 String s = “abc”,变量 s 就是字符串“abc”的强引用,只要强引用存在,则垃圾回收器就不会回收这个对象。

2、软引用(SoftReference)

用于描述还有用但非必须的对象,如果内存足够,不回收,如果内存不足,则回收。一般用 于实现内存敏感的高速缓存,软引用可以和引用队列 ReferenceQueue 联合使用,如果软引用的对象被垃圾回收,JVM 就会把这个软引用加入到与之关联的引用队列中。

3、弱引用(WeakReference)

弱引用和软引用大致相同,弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的 生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用 的对象,不管当前内存空间足够与否,都会回收它的内存。

4、虚引用(PhantomReference)

就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象 仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。 虚引用主要用来跟踪对象被垃圾回收器回收的活动。

虚引用与软引用和弱引用的一个区别在于:

虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时, 如果发现它还有虚引,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。

1.1.16、数组在内存中如何分配?

当一个对象使用 new 关键字创建的时候,会在堆上分配内存空间,然后才返回到对象的引用。这对数组来说也是一样的,因为数组也是一个对象,简单的值类型的数组,每个数组成员是一个引用(指针)引用到栈上的空间。

1.1.17、Java 中怎么创建一个不可变对象?
  1. 对象的状态在构造函数之后都不能被修改,任何修改应该通过创建一个新对象来实现.

  2. 所有的对象属性应该都设置为 final

  3. 对象创建要正确,例如:对象的应用不能在构造函数中被泄露出去

  4. 对象要设置为 final,确保不要继承的 Class 修改了 immutability 特性

1.1.18、Java 中 ++ 操作符是线程安全的吗?

不是线程安全的操作。它涉及到多个指令,如读取变量值,增加,然后存储回内存,这个过 程可能会出现多个线程交差。

1.1.19、new 一个对象的过程和 clone 一个对象的过程?

new 操作符的本意是分配内存。程序执行到 new 操作符时,首先去看 new 操作符后面的类型,因为知道了类型,才能知道要分配多大的内存空间。分配完内存之后,再调用构造函数, 填充对象的各个域,这一步叫做对象的初始化,构造方法返回后,一个对象创建完毕,可以把他的引用(地址)发布到外部,在外部就可以使用这个引用操纵这个对象。

clone 在第一步是和 new 相似的,都是分配内存,调用 clone 方法时,分配的内存和原对象(即调用 clone 方法的对象)相同,然后再使用原对象中对应的各个域,填充新对象的域,填充完成之后,clone 方法返回,一个新的相同的对象被创建,同样可以把这个新对象的引用发布到外部。

1.1.20、Java 中==和 equals()的区别?

使用==比较原生类型如:boolean、int、char 等等,使用 equals()比较对象。

1、==是判断两个变量或实例是不是指向同一个内存空间。equals 是判断两个变量或实例所指向的内存空间的值是不是相同。

2、==是指对内存地址进行比较。equals()是对字符串的内容进行比较。

3、==指引用是否相同,equals()指的是值是否相同。

1.1.21、final、finalize 和 finally 的不同之处?

final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。finally 是异常处理语句结构的一部分,表示总是执行。

finalize 是 Object 类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法, 可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。

1.1.22、java 的多态表现在哪里?

多态要有动态绑定,否则就不是多态,方法重载也不是多态(因为方法重载是编译期决定好 的,没有后期也就是运行期的动态绑定)当满足这三个条件:1、有继承 2、有重写 3、要有父类引用指向子类对象

1.1.23、静态类型有什么特点?

1、静态的属性:随着类的加载而加载,该属性不在属于某个对象,属于整个类

2、静态的方法:直接用类名调用,静态方法里不能访问非静态成员变量

3、静态类:不能直接创建对象,不可被继承

1.1.24、Java 创建对象的几种方式?

new 创建新对象;

通过反射机制;

采用 clone 机制;

通过序列化机制

1.1.25、Object 中有哪些公共方法?

clone()

hashCode()

equals()

finalize()

getClass()

notify()

notifyAll()

toString()

wait()

1.1.26、&和&&的区别

&是按位于:都为1的时候为1 两边都会运算

&&是短路运算:只要前面的为false就不会运算后面的表达式,在登录验证的时候经常用到

1.1.27、在.java 源文件中可以有多个类吗(内部类除外)?

一个.java 源文件中可以包括多个类(不是内部类),但是单个文件中只能有一个 public 类,并且该 public 类必须与文件名相同

1.1.28、如何正确的退出多层嵌套循环?

1、使用标号和 break;

2、通过在外层循环中添加标识符

1.1.29、内部类有什么作用?

1、内部类可以很好的实现隐藏,一般的非内部类,是不允许有 private 与 protected 权限的,但内部类可以

2、内部类拥有外围类的所有元素的访问权限

3、可是实现多重继承

4、可以避免修改接口而实现同一个类中两种同名方法的调用

1.1.30、深拷贝和浅拷贝的区别是什么?

浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用 仍然指向原来的对象.换言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象.

深拷贝:被复制对象的所有变量都含有与原来的对象相同的值.而那些引用其他对象的变量 将指向被复制过的新对象.而不再是原有的那些被引用的对象.换言之.深拷贝把要复制的对象所引用的对象都复制了一遍.

1.1.31、String 是基本数据类型吗?

基本数据类型包括 byte、int、char、long、float、double、boolean 和 short。java.lang.String 类是 final 类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,我们应该用 StringBuffer 类

1.1.32、static在java中的作用

static作用在变量上:

只有一个,可以被类名直接调用,修改,所有类和对象共享的成员

非静态变量和静态变量都可以被对象直接调用和修改且一个对象一份新的

只有静态变量才可以被类名直接调用 对象和所有类共享只一份

static修饰的变量在类加载期间初始化,且在方法区中分配,属于线程共享区,所有的对象实例共享一份数据。而非静态变量在堆中对象专有

static作用在方法上:

可以使用使用类名.方法名直接调用方法 而不要创建对象再调用方法避免了先要new出对象的繁琐和资源消耗,

注意:静态方法只能调用静态变量和静态方法 非静态方法都可调用 因为静态方法和变量在方法区中不在堆中 在对象创建之前就有了 所以调用非静态方法都可能还没被创建 同样在静态方法中不能使用this 和super指针 因为静态是单独存在方法区中的

static一个很重要的用途就是实现单例设计模式。单利模式的特点是该类只能有一个实例,为了实现这一功能,必须隐藏类的构造函数,即把构造函数声明为private,并提供一个创建对象的方法,由于构造对象被声明为private,外界无法直接创建这个类型的对象,只能通过该类提供的方法来获取类的对象,要达到这样的目的只能把创建对象的方法声明为static

static作用在类上:

作用在类上:只能修饰内部类

在单例模式上用

static作用在代码块上:

代码块:没有名字的函数体 每次new的时候执行

静态代码块:类被加载的时候执行 只执行一次

执行顺序 静态代码块》代码块》构造函数

1.1.33、什么是值传递和引用传递?

对象被值传递,意味着传递了对象的一个副本。因此,就算是改变了对象副本,也不会影响 源对象的值,对象被引用传递,意味着传递的并不是实际的对象,而是对象的引用。因此, 外部对引用对象所做的改变会反映到所有的对象上。

1.1.34、重载和重写的区别?

方法的重写 Overriding 和重载 Overloading 是 Java 多态性的不同表现。重写 Overriding 是父类与子类之间多态性的一种表现,重载 Overloading 是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽” 了。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型, 则称为方法的重载(Overloading)。

1.1.35、成员变量和局部变量的区别有哪些?

1、从语法形式上,看成员变量是属于类的,而局部变量是在方法中定义的变量或是方法的参数;成员变量可以被 public,private,static 等修饰符所修饰,而局部变量不能被访问控制修饰符及 static 所修饰;成员变量和局部变量都能被 final 所修饰;

2、从变量在内存中的存储方式来看,成员变量是对象的一部分,而对象存在于堆内存,局部变量存在于栈内存

3、从变量在内存中的生存时间上看,成员变量是对象的一部分,它随着对象的创建而存在, 而局部变量随着方法的调用而自动消失。

4、成员变量如果没有被赋初值,则会自动以类型的默认值而赋值(一种情况例外被 final 修饰但没有被 static 修饰的成员变量必须显示地赋值);而局部变量则不会自动赋值。

1.1.36、静态方法和实例方法有何不同?

静态方法和实例方法的区别主要体现在两个方面:

在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方 式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。

静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不 允许访问实例成员变量和实例方法;实例方法则无此限制

1.1.37、什么是多态?

允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不 同的行为方式。(发送消息就是函数调用)

1.1.38、多态的优点?

可替换性(substitutability)。多态对已存在代码具有可替换性。例如,多态对圆 Circle 类工作,对其他任何圆形几何体,如圆环,也同样工作。

可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。

动态绑定

1.1.39、多态存在的三个必要条件?

要有继承。

要有方法的重写。

父类引用指向子类对象(对于父类中定义的方法,如果子类中重写了该方法,那么父类类型的引用将会调用子类中的这个方法,这就是动态连接)

1.1.40、列出一些常见的运行时异常?

ArithmeticException( 算 术 异 常 )

ClassCastException ( 类 转 换 异 常 )

IllegalArgumentException (非法参数异常)

IndexOutOfBoundsException (下标越界异常)

NullPointerException ( 空 指 针 异 常 )

SecurityException (安全异常)

并发修改异常

1.1.41、什么是可重入锁

synchronized与Lock都是可重入锁

可重入锁 :当一个线程执行代码的时候发现别的线程锁住了,如果不可重入则直接走了,比如秒杀的时候,不公平

​ 可重入锁则一直尝试,直到别的线程把锁释放、获取。 和自旋锁差不多

1.1.42、什么是反射?

反射就是动态加载对象,并对对象进行剖析。在运行状态中,对于任意一个类,都能够 知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法,这种动 态获取信息以及动态调用对象方法的功能成为 Java 反射机制。

1.1.43、反射的作用?

反射就是动态加载对象,并对对象进行剖析。在运行状态中,对于任意一个类,都能够 知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法,这种动 态获取信息以及动态调用对象方法的功能成为 Java 反射机制。

1.1.44、获取 class 的三种方式?

对象调用 getClass() 方法来获取;类名.class 的方式得到;通过 Class 对象的 forName() 静态方法来获取

1.1.45、break 和 continue 的区别?

break 和 continue 都是用来控制循环的语句。break 用于完全结束一个循环,跳出循环体执行循环后面的语句。continue 用于跳过本次循环,继续下次循环。

1.1.46、运行时异常与一般异常有何异同?

异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能 遇到的异常,是一种常见运行错误。java 编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。

1.1.47、switch 能否作用在 byte、long、string 上?

不可以作用在

boolean 1

float 4

long 8

double 8

1.1.48、Set 里的元素是不能重复的,那么用什么方法来区分重复与否呢?**

Set 里的元素是不能重复的,元素重复与否是使用 equals()方法进行判断的。

equals()和==方法决定引用值是否指向同一对象equals()在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值。

hashset还要重写hashcode()

1.1.49、什么是迭代器(Iterator)?

Iterator 接口提供了很多对集合元素进行迭代的方法。每一个集合类都包含了可以返回迭代器实例的

迭代方法。迭代器可以在迭代的过程中删除底层集合的元素。

克隆(cloning)或者是序列化(serialization)的语义和含义是跟具体的实现相关的。因此, 应该由集合类的具体实现来决定如何被克隆或者是序列化。

1.1.50、Enumeration 接口和 Iterator 接口的区别有哪些?

Enumeration 速度是 Iterator 的 2 倍,同时占用更少的内存。但是, Iterator 远远比Enumeration 安全,因为其他线程不能够修改正在被 iterator 遍历的集合里面的对象。同时,Iterator 允许调用者删除底层集合里面的元素,这对 Enumeration 来说是不可能的。

1.1.51、字符串常量池到底存在于内存空间的哪里?

jdk 6.0 字符串常量池在方法区,方法区的具体体现可以看做是堆中的永久区。jdk 7.0 java 虚拟机规范中不再声明方法区,字符串常量池存放在堆空间中jdk 8.0 java 虚拟机规范中又声明了元空间,字符串常量池存放在元空间中

1.1.52、Java 中的编译期常量是什么?使用它又什么风险?

公共静态不可变(public static final )变量也就是我们所说的编译期常量,这里的 public 可选的。实际上这些变量在编译时会被替换掉,因为编译器知道这些变量的值,并且知道这些变量在运行时不能改变。这种方式存在的一个问题是你使用了一个内部的或第三方库中的公有编译时常量,但是这个值后面被其他人改变了,但是你的客户端仍然在使用老的值,甚至你已经部署了一个新的 jar。为了避免这种情况, 当你在更新依赖 JAR 文件时,确保重新编译你的程序。

1.1.53、说出 5 个 JDK 1.8 引入的新特性?

Java 8 在 Java 历史上是一个开创新的版本,下面 JDK 8 中 5 个主要的特性: Lambda 表达式,允许像对象一样传递匿名函数 Stream API,充分利用现代多核 CPU,可以写出很简洁的代码 Date 与 Time API,最终,有一个稳定、简单的日期和时间库可供你使用 扩展方法,现在,接口中可以有静态、默认方法。 重复注解,现在你可以将相同的注解在同一类型上使用多次。

1.1.54、两个对象的hashcode相同则equals一定相同吗反过来呢,什么情况下hashcode相同

hashcode相同并不一定equals相同,在map中hashcode相同只能说明两个entry的哈希值相同也就是哈希冲突equals并不一定相同,equals相同hashcode相同。基本数据类型值相同哈希值就相同,同一个对象哈希值相同,list内容和顺序一样哈希值相同set内容相同哈希值相同

1.1.55、string的常用方法

split():切片

indexOf(‘a’):返回指定字符索引

charSet(5) :返回指定索引的字符

Substring():截取

Trim():两头去空

Replasce(a,b):替换

1.1.56、IO流分为几种

Mkdir()创建目录

createFile()创建文件

getParent()获取父目录路径

Delete()删除文件

Exists()文件是否存在

isFile()是否是文件

isDirectory()是否是目录

getName()获取文件名字

1.1.57、Int 和Integer的区别

Int 是基本数据类型,Integer是包装数据类型,因为JAVA方便用面向对象的思想操作推出了Integer

Int 默认值0 Integer默认值是null

int比较用== Integer比较用Equals()

Integer类是int类的包装类,在jdk1.5引入了自动装箱和拆箱的操作

Integer值为-128到127会存入常量池

一般类的属性都使用包装类型,方法的参数用包装类型,局部方法的变量用基本数据类型

1.1.58、Math.Round(-1.5)等于多少?

大于5 全部取,负数(取反)

等于5 正数取

小于5 全不取(就是前面的整数)

Math(5.6) 6

Math(-5.6) -6

Math(5.5) 6

Math(-5.5) -5

Math(5.4) 5

Math(-5.4) -5

1.1.59、java中创建一个不可变对象

不可变对象:对象在构造函数实例化后不能被修改,任何修改必须创建一个新的对象

  1. 对象必须设置成final

  2. 对象的所有属性必须被设置为final

  3. 所有属性属性被设置为私有的,这样就不会被直接访问

为什么要设置成不可变对象?

  1. 对象要创建正确,不能再构造方法中泄漏出类的应用

  2. 不要提供set方法,通过构造器初始化所有的属性

因为不可变对象对于缓存是非常好的,因为不用担心会改变

1.1.60、为什么重写equals方法时要重写hashcode()方法

因为在hashmap中判断两个对象是否相等,首先判断哈希值是否相等,hash值相等之后才回用equals比较内容是否相等,

如果不重写hashcode()可能因为hashmap等不允许出现重复的元素而出现重复的元素,hashcode()是对不同的对象产生不同的hash码,如果不重写可能导致同一对象不同的hash码

1.1.61、序列化

应用场景:把对象永久存储在磁盘上,网络传输

  1. 被序列化的对象必须实现Servlizeble标记接口

  2. ObjectOutPutStream 的WriteObject(OBJ)可以把对象写到磁盘上

  3. ObjectInputStream 的ReadObject(OBJ)可以从磁盘读取对象

序列化机制算法:

​ 对象序列化都会有一个编号

​ 当程序试图将对象序列化的时候会查看有没有被序列化过,没有到话就会将对象转成字节序列并输出,如果被序列化过则输出序列化的编号

UID:一般序列化时候会显示生成一个UID,没有的话会自动生成一个。当我们序列化后对该类修改了,然后反序列化回来会和类的UID进行比较,改了就会报版本不一致的错误

注意:类名,属性都会被序列化

​ 但是静态属性(static)和瞬态属性(TranSient)不会被序列化

​ 如果对象有引用数据类型的属性也必须是可序列化的

1.1.62、compareble和comparaTor的区别

Comparable:内部比较器 需要比较的类实现Comparable接口并实现其comparaTo方法在comparaTo方法里自定义实体需要用什么属性比较一般大于返回1等于返回0 小于返回-1

在测试的时候,集合把很多对象加入进去了用Collections.sort(list)即可进行排序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E2jjpVU3-1618290492874)(…/AppData/Local/Temp/ksohtml16760/wps1.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c6QVqPWO-1618290492877)(…/AppData/Local/Temp/ksohtml16760/wps2.jpg)]

****comparaTor****:是外部比较接口,不需要比较的对象实现,而是创建好了加入到集合了只后,用匿名内部类实现ComparaTor接口写比较规则

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a4zHzNpz-1618290492879)(…/AppData/Local/Temp/ksohtml16760/wps3.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a3bGvy3a-1618290492884)(…/AppData/Local/Temp/ksohtml16760/wps4.jpg)]

区别:comparable:需要实体类实现compara接口

comparaTor:不需要实现comparator接口

comparable是在集合内部排序

comparaTor是在集合外部排序

comparable接口包含comparaTo方法

comparable接口是实现compare方法,但是他还有一个equals方法

1.1.63、字符串的常量池存在于内存空间的哪里

1.6存在于方法区里面

1.7存在堆空间里

1.8方法区永久代变为元空间,存在元空间里

基本数据类型存在栈中,字符串不在,字符串和常量池的常量都在方法区中

1.1.64、用哪两种方式实现集合的排序
  1. 使用treeSet和treeMap

  2. 使用Collections的sort()方法

1.1.65、枚举可以存哪些数据类型

基本数据类型 string 数组 集合 对象都行

1.1.66、注解的属性

基本数据类型 string 数组 不能存集合对象

1.1.67、JAVA中如何将字符串反转

toString方法

因为toString方法是Object里面已经有了的方法,而所有类都是继承Object,所以“所有对象都有这个方法”。

它通常只是为了方便输出,比如System.out.println(xx),括号里面的“xx”如果不是String类型的话,就自动调用xx的toString()方法

总而言之,它只是sun公司开发java的时候为了方便所有类的字符串操作而特意加入的一个方法

  1. 利用 StringBuffer 或 StringBuilder 的 reverse 成员方法:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1UJKwyGS-1618290492892)(…/AppData/Local/Temp/ksohtml16760/wps5.jpg)]

2先将string字符串转换为char数组 然后通过下标倒过来存进String

注 string和char区别 char只能存一个字符 单引号

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QXlNypbc-1618290492893)(…/AppData/Local/Temp/ksohtml16760/wps6.jpg)]

1.2.Java IO

1.2.1、Java中IO流分为哪几种

流:不同设备数据传输称为流

1.按照数据的流向分为

输入流 输出流

2.按照所操作的数据单元分为

字节流 字符流

字节流:每次读取(写出)一个字节,当传输的资源文件有中文时,就会出现乱码。

字符流:每次读取(写出)两个字节,有中文时,使用该流就可以正确传输显示中文。

1字符 = 2字节; 1字节(byte) = 8位(bit); 一个汉字占两个字节长度。

3.按照角色可分为

节点流:从或向一个特定的地方(节点)读写数据。如FileInputStream。

处理流(包装流):是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。

1.2.2、字节流和字符流的区别?

字符流和字节流的使用非常相似,但是实际上字节流的操作不会经过缓冲区(内存)而是直 接操作文本本身的,而字符流的操作会先经过缓冲区(内存)然后通过缓冲区再操作文件以字节为单位输入输出数据,字节流按照 8 位传输

以字符为单位输入输出数据,字符流按照 16 位传输

1.2.3、什么是 Java 序列化,如何实现 Java 序列化?

序列化就是一种用来处理对象流的机制,将对象的内容进行流化。可以对流化后的对象进行 读写操作,可以将流化后的对象传输于网络之间。序列化是为了解决在对象流读写操作时所 引发的问题

序列化的实现:将需要被序列化的类实现 Serialize 接口,没有需要实现的方法,此接口只是为了标注对象可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,再使用 ObjectOutputStream 对象的 write(Object obj)方法就可以将参数 obj 的对象写出

1.2.4、什么是节点流,什么是处理流,各有什么好处,处理流的创建有什么特征?

节点流 直接与数据源相连,用于输入或者输出

处理流:在节点流的基础上对之进行加工,进行一些功能的扩展 处理流的构造器必须要 传入节点流的子类

1.2.5、有哪些可用的 Filter 流?

在 java.io 包中主要由 4 个可用的 filter Stream。两个字节 filter stream,两个字符 filter stream. 分别是 FilterInputStream, FilterOutputStream, FilterReader and FilterWriter.这些类是抽象类,不能被实例化的。

1.2.6、如何实现对象克隆

有两种方式:

1). 实现 Cloneable 接口并重写 Object 类中的 clone()方法;

2). 实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆

1.2.7、什么是缓冲区?有什么作用?

缓冲区就是一段特殊的内存区域,很多情况下当程序需要频繁地操作一个资源(如文件或数 据库)则性能会很低,所以为了提升性能就可以将一部分数据暂时读写到缓存区,以后直接从此区域中读这样就可以显著的提升性能。

对于 Java 字符流的操作都是在缓冲区操写数据即可,作的,所以如果我们想在字符流操作中主动将缓冲区刷新到文件则可以使用 flush() 方法操作。

1.2.8、什么是阻塞 IO?什么是非阻塞 IO?

IO 操作包括:对硬盘的读写、对 socket 的读写以及外设的读写。

当用户线程发起一个 IO 请求操作(本文以读请求操作为例),内核会去查看要读取的数据是否就绪,对于阻塞 IO 来说,如果数据没有就绪,则会一直在那等待,直到数据就绪;对于非阻塞 IO 来说,如果数据没有就绪,则会返回一个标志信息告知用户线程当前要读的数据没有就绪。当数据就绪之后,便将数据拷贝到用户线程,这样才完成了一个完整的 IO 读请求操作,也就是说一个完整的 IO 读请求操作包括两个阶段:

1) 查看数据是否就绪;

2) 进行数据拷贝(内核将数据拷贝到用户线程)。

那么阻塞(blocking IO)和非阻塞(non-blocking IO)的区别就在于第一个阶段,如果数据没有就绪,在查看数据是否就绪的过程中是一直等待,还是直接返回一个标志信息。

Java 中传统的 IO 都是阻塞 IO,比如通过 socket 来读数据,调用 read()方法之后,如果数据没有就绪,当前线程就会一直阻塞在 read 方法调用那里,直到有数据才返回;而如果是非阻塞 IO 的话,当数据没有就绪,read()方法应该返回一个标志信息,告知当前线程数据没有就绪,而不是一直在那里等待。

1.2.9、BIO,NIO,AIO有什么区别

同步:java 自己去处理 io。

异步:java 将 io 交给操作系统去处理,告诉缓存区大小,处理完成回调。阻塞:使用阻塞 IO 时,Java 调用会一直阻塞到读写完成才返回。

非阻塞:使用非阻塞 IO 时,如果不能立马读写,Java 调用会马上返回,当 IO 事件分发器通知可读写时在进行读写,不断循环直到读写完成。

BIO:同步并阻塞,服务器的实现模式是一个连接一个线程,这样的模式很明显的一个缺陷是:由于客户端连接数与服务器线程数成正比关系,可能造成不必要的线程开销,严重的还 将导致服务器内存溢出。当然,这种情况可以通过线程池机制改善,但并不能从本质上消除 这个弊端。

NIO:在 JDK1.4 以前,Java 的 IO 模型一直是 BIO,但从 JDK1.4 开始,JDK 引入的新的 IO 模型 NIO,它是同步非阻塞的。而服务器的实现模式是多个请求一个线程,即请求会注册到多路复用器 Selector 上,多路复用器轮询到连接有 IO 请求时才启动一个线程处理。AIO:JDK1.7 发布了 NIO2.0,这就是真正意义上的异步非阻塞,服务器的实现模式为多个有效请求一个线程,客户端的 IO 请求都是由 OS 先完成再通知服务器应用去启动线程处理(回调)。

应用场景:并发连接数不多时采用 BIO,因为它编程和调试都非常简单,但如果涉及到高并发的情况,应选择 NIO 或 AIO,更好的建议是采用成熟的网络通信框架 Netty。

适用场景

BIO:适用于连接数目比较小,并且一次发送大量数据的场景;

NIO:适用于连接数目多,连接比较短,常用于聊天服务器开发工作(榜上有名的Netty是很大的实践);比如聊天服务器

AIO:适用于连接数目多,连接比较长。这个目前市面上应用还不是很广泛。比如滴滴打车

同步阻塞

BIO:同步阻塞

NIO:同步非阻塞

AIO:异步非阻塞

操作结构

BIO

同步阻塞编程方式 JDK1.4以前用的 传统的

结构:

一、服务端准备好

二、客户端发请求

三、服务端创立一个线程和一个socket和这个客户端通信

如果有很多客户端访问服务端没有线程可用的新来的客户端就会被阻塞或被拒绝 改进方式:创立线程池 适应连接数目小的应用

NIO

NIO最重要的是 一个连接创建后 不需要对应一个线程 这个连接会被注册到多路复用器上

当一个客户端请求时候,服务端会产生一个对应的通道注册在多路复用器上,可以一个线程处理在多路复用器对应的很多客户端通道(比如客户端一写数据,线程就把数据写到缓存里缓存会写进客户端,另一个需要读这个线程也在缓存中读)所以这个线程是面向缓存的不是直接和客户端进行操作

但是当并发量太大了的话还是有BIO的问题 线程不够用这类

AIO

与NIO不同的是 当进行读写操作是直接调用writer和reader方法即可 这两种方法均为异步(不一定立马返回结果)

对于读而言:当有流可读取时候,操作系统会将可读的流传入read方法的缓冲区,并通知程序

对于写而言:当操作系统将writer方法传递的流写入完毕时候操作系统主动通知程序

可理解为读和写都是异步的,完成后会主动调用回到函数

1.2.10、IO里面的常见类,字节流、字符流、接口、实现类、方法阻塞?

输入流就是从外部文件输入到内存,输出流主要是从内存输出到文件。

IO 里面常见的类,第一印象就只知道 IO 流中有很多类,IO 流主要分为字符流和字节流。字符 流 中 有 抽 象 类 InputStream 和 OutputStream , 它 们 的 子 类 FileInputStream , FileOutputStream,BufferedOutputStream 等。字符流 BufferedReader 和 Writer 等。都实现了 Closeable, Flushable, Appendable 这些接口。程序中的输入输出都是以流的形式保存的,流中保存的实际上全都是字节文件。

java 中的阻塞式方法是指在程序调用改方法时,必须等待输入数据可用或者检测到输入结束或者抛出异常,否则程序会一直停留在该语句上,不会执行下面的语句。比如 read()和readLine()方法。

1.2.11、谈谈对 NIO的认知?

对于 NIO,它是非阻塞式,核心类:

1.Buffer 为所有的原始类型提供 (Buffer)缓存支持。2.Charset 字符集编码解码解决方案

3.Channel 一个新的原始 I/O 抽象,用于读写 Buffer 类型,通道可以认为是一种连接,可以是到特定设备,程序或者是网络的连接。

1.2.12、NIO和传统的IO有什么区别?

1、传统 IO 一般是一个线程等待连接,连接过来之后分配给 processor 线程,processor 线程与通道连接后如果通道没有数据过来就会阻塞(线程被动挂起)不能做别的事情。NIO 则不同,首先,在 selector 线程轮询的过程中就已经过滤掉了不感兴趣的事件,其次,在 processor 处理感兴趣事件的 read 和 write 都是非阻塞操作即直接返回的,线程没有被挂起。

2、传统 io 的管道是单向的,nio 的管道是双向的。

3、两者都是同步的,也就是 java 程序亲力亲为的去读写数据,不管传统 io 还是 nio 都需要read 和 write 方法,这些都是 java 程序调用的而不是系统帮我们调用的,nio2.0 里这点得到了改观,即使用异步非阻塞 AsynchronousXXX 四个类来处理。

1.3.Java 集合

1.3.1、集合架构图

JAVA面试总结(初版)_第17张图片

1.3.2、List
特征 ArrayList LinkedList Vector
底层数据结构 数组 双向链表 数组
特点 查询快、增删慢(移动)、效率高 增删快、查询快、效率高 查询快、增删慢、效率低
存储重复元素 有序、可以 可以 可以
线程安全 不安全 不安全 安全
1.3.3、Set
特征 HashSet LinkedHashSet TreeSet
底层数据结构 哈希表 链表+哈希表 二叉树
特点 元素唯一且已经排好序
存储重复元素 无序、唯一 唯一 唯一,有序
线程安全 不安全 不安全 不安全
存储NULL 可以存NULL
1.3.4、Map
特征 HashMap HashTable LinkedHashMap TreeMap
底层数据结构 哈希表 哈希表 双向链表+哈希表 红黑树
特点
存储重复元素 无序、唯一 唯一 唯一 有序、唯一
线程安全 不安全 安全 不安去
存储NULL 最多一个KEY为null多个value为null value和key都不能为null

ArrayXxx:底层数据结构是数组,查询快,增删慢
LinkedXxx:底层数据结构是链表,查询慢,增删快
HashXxx:底层数据结构是哈希表。依赖两个方法:hashCode()和equals()
TreeXxx:底层数据结构是二叉树。两种方式排序:自然排序和比较器排序

1.3.5、list、set、queue、map、stack的特点与用法?

List:有序、可以重复、可以用 Iterator 实现单向遍历,也可用ListIterator 实现双向遍历。ListIterator是List的专属

Set: 无序、不可重复、最多存一个null

Map:无序、不可重复、hashmap可以重复、

queue:先进先出

stack:后进先出

1.3.6、ArrayList,Vector, LinkedList比较

1.ArrayList,Vector, LinkedList元素都是可以重复,且有序的,

ArratList是数组结构,LinkedList是双向链表、Vector是数组

ArrayList 和Vector 查询快。增删慢,LinkedList增删满查询快

Vector是线程安全的 而ArrayList和LinkedList不是线程安全的

2.一般如果需要使用线程安全的不采用Vector 可以用Collections的

synchronizedList()将链表变成线程安全的 同时也可以使用copyOnWriterArrayList这种读无锁写有锁定来实现,同时copyOnWriterArrayList解决并发修改异常效率最高

3.ArrayList采用懒加载第一次add的时候才初始化内存容量,默认为10当容量不足时候扩容为原来的1.5倍,一般在尾部插入较好,如果在中间插入需要大量移动其他元素代价太高,扩容是将原来的元素和新加的元素赋值到新长度的数组中去

4.Vector和ArraList一样,默认为0扩容为原来的2倍但是采用了synchronized修饰但是线程安全的但是锁的粒度太粗了读读都互斥导致性能很低,这一点可以用CopeOnWriteArrayList代替

5.LinkedList是基于双向链表的,插入很方便、但是查询需要重头开始所以速度很慢,随机插入效率很高

1.3.7、Hashtable和Hashmap的区别?

HashTable是线程安全你的HashMap是线程不安全的

HashMap key可以null但是最多一个 HashMap 值和key都不能null

HashMap采用Iterator遍历HashTable采用Enumeration遍历

HashTable初始容量为11没次扩容为原来的2N+1(奇数、素数)HashMap初始容量为16没次扩容为原来的2倍(2的幂)

HashMap 把 Hashtable 的 contains 方法去掉了,改成 containsValue 和 containsKey。因为 contains 方法容易让人引起误解。HashMap加载因子为0.75当容量在75%的时候进行扩容。

1.3.8、HashMap7/8比较

HashMap在1.8之前是数组加链表的结构

HashMap在1.8改成了数组+链表+红黑树 提高查找的效率

继承了动态数组的查询快的优点和链表的插入快的优点

HashMap不是线程安全的,相对于HashTable来说它可以为null

在1.8中当单向链表的节点大于等于8的时候转化为红黑树,小于8的时候又转化为单向链表

hashamap在1.8之前每个节点是一个entry在1.8改成了Node

链表插入:7上8下

1.3.9、HahsMap源码解析

hash是什么?

将通过哈希算法将任意长度的数字(比如一个哈希值)转化为固定长度。在哈希表中是对哈希变是数组的长度进行取余方便存储在哈希表的数组中

hash冲突?

在hashmap通过hasH算法存储的时候难免会产生哈希冲突

hashMap存储结构?

1.7是数组加链表 1.8是数组加链表加红黑树

1.7是entry 1.8是node

在1.8中每一个Node结构中有 key value next hash字段, next字段就是当产生hash冲突的时候将其连接到链表的头部或者尾部,1.7头 1.8尾

如果在创建hashamap的时候没有指定散列表数组长度是多少?

默认是16

散列表(数组加链表)是懒加载一开始没有默认初始容量当第一次put的时候才会变成16

默认的负载因子是多少?

默认是0.75 当超过容量的75%的时候第一次扩容

链表转化为红黑树有什么条件?

两个指标:

一、链表长度达到8

二、数组达到64

当都达到了才转化

Node字段有一个hash字段,这个hash字段的值是key对象的hashCode()吗?

不是 这个hash字段的值是key的hashcode 的高16位 异惑^ 低16位得到一个新的hash值 主要解决分布不均匀的问题 优化hash算法(因为高16位没有起到作用)

1.3.10、HashSet的底层实现是什么?

HashSet 的实现是依赖于 HashMap 的,HashSet 的值都是存储在 HashMap 中的。在 HashSet 的构造法中会初始化一个 HashMap 对象,HashSet 不允许值重复。

因此,HashSet 的值是作为 HashMap 的 key 存储在 HashMap 中的,当存储的值已经存在时返回 false。

1.3.11、TreeMap、HashMap、LindedHashMap的区别?

LinkedHashMap 可以保证 HashMap 集合有序。存入的顺序和取出的顺序一致。TreeMap 实现SortMap 接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用 Iterator 遍历 TreeMap 时,得到的记录是排过序的。HashMap 不保证顺序,即为无序的,具有很快的访问速度。HashMap 最多只允许一条记录的键为 Null;允许多条记录的值为 Null;HashMap 不支持线程的同步。

1.3.12、Iterator和ListIterator的区别是什么?

Iterator 可用来遍历 Set 和 List 集合,但是 ListIterator 只能用来遍历 List。Iterator 对集合只能是前向遍历,ListIterator 既可以前向也可以后向。

ListIterator 实现了 Iterator 接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。

1.3.13、Enumeration接口和Iterator接口的区别有哪些?

Enumeration 速度是 Iterator 的 2 倍,同时占用更少的内存。但是, Iterator 远远比Enumeration 安全,因为其他线程不能够修改正在被 iterator 遍历的集合里面的对象。同时,Iterator 允许调用者删除底层集合里面的元素,这对 Enumeration 来说是不可能的。

1.3.14、List, Set, Map 是否继承自 Collection 接口?

只有List 和Set 接口继承于Collection 接口,Map 是与Collection 并列的接口概念

1.3.15、ConcurrentHashMap源码分析?

concurrencHashMap()和copyonWriteArrayList和CopyOnWriteArraySet一样都是读写分离

HashMap在并发环境下可能会形成环形链表(扩容时候)在get操作时候导致cpu空转

HashTable是线程安全的,但是会锁住整个表、性能太低了

JAVA面试总结(初版)_第18张图片

1.7.中ConcurrentHashMap是采用了分段锁、容器中有多把锁、每一把锁,锁一段数据,不同线程访问不同段的数据,这样就可以避免线程的竞争

未完。。。

1.4.Java JVM

1.4.1、JVM的堆内存和栈内存

存储区别:栈运行方法 堆存储实体(数组、对象)

默认值:栈没有默认值 堆有默认值

生命周期:栈内存使用完毕就释放 堆内存等待JVM回收垃圾

在JVM中,内存分为堆内存跟栈内存。他们二者的区别是: 当我们创建一个对象(new Object)时,就会调用对象的构造函数来开辟空间,将对象数据存储到堆内存中,与此同时在栈内存中生成对应的引用,当我们在后续代码中调用的时候用的都 是栈内存中的引用。还需注意的一点,基本数据类型是存储在栈内存中。

1.4.2、Java 的内存划分?

程序计数器(PC,Program Counter Register)。在 JVM 规范中,每个线程都有它自己的程序计数器,并且任何时间一个线程都只有一个方法在执行,也就是所谓的当前方法。程序计 数器会存储当前线程正在执行的 Java 方法的 JVM 指令地址;或者,如果是在执行本地方法,则是未指定值(undefined)。(唯一不会抛出 OutOfMemoryError)

第二,Java 虚拟机栈(Java Virtual Machine Stack),早期也叫 Java 栈。每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame),对应着一次次的 Java 方法调用。

前面谈程序计数器时,提到了当前方法;同理,在一个时间点,对应的只会有一个活动的栈 帧,通常叫作当前帧,方法所在的类叫作当前类。如果在该方法中调用了其他方法,对应的 新的栈帧会被创建出来,成为新的当前帧,一直到它返回结果或者执行结束。JVM 直接对Java 栈的操作只有两个,就是对栈帧的压栈和出栈。

栈帧中存储着局部变量表、操作数(operand)栈、动态链接、方法正常退出或者异常退出 的定义等。

第三,堆(Heap),它是 Java 内存管理的核心区域,用来放置 Java 对象实例,几乎所有创建的 Java 对象实例都是被直接分配在堆上。堆被所有的线程共享,在虚拟机启动时,我们指定的“Xmx”之类参数就是用来指定最大堆空间等指标。

( 编译器通过逃逸分析,确定对象是在栈上分配还是在堆上分配)

理所当然,堆也是垃圾收集器重点照顾的区域,所以堆内空间还会被不同的垃圾收集器进行 进一步的细分,最有名的就是新生代、老年代的划分。

第四,方法区(Method Area)。这也是所有线程共享的一块内存区域,用于存储所谓的元

(Meta)数据,例如类结构信息,以及对应的运行时常量池、字段、方法代码等。

由于早期的 Hotspot JVM 实现,很多人习惯于将方法区称为永久代(Permanent Generation)。 Oracle JDK 8 中将永久代移除,同时增加了元数据区(Metaspace)。

第五,****运行时常量池********(********Run-Time Constant**** ****Pool********)********,这是方法区的一部分****。如果仔细分析过反编译的类文件结构,你能看到版本号、字段、方法、超类、接口等各种信息,还有一项信息 就是常量池。Java 的常量池可以存放各种常量信息,不管是编译期生成的各种字面量,还是需要在运行时决定的符号引用,所以它比一般语言的符号表存储的信息更加宽泛。

第六,本地方法栈(Native Method Stack)。它和 Java 虚拟机栈是非常相似的,支持对本地方法的调用,也是每个线程都会创建一个。在 Oracle Hotspot JVM 中,本地方法栈和 Java 虚拟机栈是在同一块儿区域,这完全取决于技术实现的决定,并未在规范中强制。

1.4.3、什么是 Java 虚拟机?为什么 Java 被称作是无关平台的编程语言?

Java 虚拟机是一个可以执行 Java 字节码的虚拟机进程。Java 源文件被编译成能被 Java 虚拟机执行的字节码文件。 Java 被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译。Java 虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特性。

1.4.4、 如何判断一个对象应该被回收?
  1. 在 Java 中采取了 可达性分析法

经过一系列GC 一个对象和任何一个对象内有可达路径,则为不可达,被判定为不可达并不一定会被回收,被判定不可达的至少要经过2次GC

2.引用计数法、被引用+1 完成引用-1 没有为0 缺点:不能识别循环引用

1.4.5、 GC 触发的条件?

1)程序调用 System.gc 时可以触发;(2)系统自身来决定 GC 触发的时机

1.4.6、可以作为 GCRoots 的对象有哪些?

虚拟机栈中引用的对象

方法区中类静态属性引用的对象方法区中常量引用的对象

本地方法栈中引用的对象

1.4.7、JVM 中一次完整的 GC 流程是怎样的,对象如何晋升到老年代?

Java 堆 = 老年代 + 新生代新生代 = Eden + S0 + S1

当 Eden 区的空间满了, Java 虚拟机会触发一次 Minor GC,以收集新生代的垃圾,存活下来的对象,则会转移到 Survivor 区。

大对象(需要大量连续内存空间的 Java 对象,如那种很长的字符串)直接进入老年态; 如果对象在 Eden 出生,并经过第一次 Minor GC 后仍然存活,并且被 Survivor 容纳的话,年

龄设为 1,每熬过一次 Minor GC,年龄+1,若年龄超过一定限制(15),则被晋升到老年态。即长期存活的对象进入老年态。

老年代满了而无法容纳更多的对象,Minor GC 之后通常就会进行 Full GC,Full GC 清理整个内存堆 – 包括年轻代和年老代。

Major GC 发生在老年代的 GC,清理老年区,经常会伴随至少一次 Minor GC,比 Minor GC

慢 10 倍以上。

1.4.8、双亲委派模型?

双亲委派模型工作过程是:

如果一个类加载器收到类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求 委派给父类加载器完成。每个类加载器都是如此,只有当父加载器在自己的搜索范围内找不 到指定的类时(即 ClassNotFoundException),子加载器才会尝试自己去加载。

1.4.9、为什么需要双亲委派模型?

防止内存中出现多份同样的字节码

防止重复加载同一字节码,

保证核心class不会被串改

1.4.10、怎么打破双亲委派模型?

打破双亲委派机制则不仅要继承 ClassLoader 类,还要重写 loadClass 和 findClass 方法。

1.4.11、导致 Full GC 一般有哪些情况?

1). 新生代设置过小

一是新生代 GC 次数非常频繁,增大系统消耗;二是导致大对象直接进入旧生代,占据了旧生代剩余空间,诱发 Full GC

2). 新生代设置过大

一是新生代设置过大会导致旧生代过小(堆总量一定),从而诱发 Full GC;二是新生代 GC

耗时大幅度增加

3). Survivor 设置过小

导致对象从 eden 直接到达旧生代

4). Survivor 设置过大

导致 eden 过小,增加了 GC 频率

一般说来新生代占整个堆 1/3 比较合适

GC 策略的设置方式

1). 吞吐量优先 可由-XX:GCTimeRatio=n 来设置

2). 暂停时间优先 可由-XX:MaxGCPauseRatio=n 来设置

1.4.12、Minor GC,Full GC 触发条件?

Minor GC 触发条件:当 Eden 区满时,触发 Minor GC。Full GC 触发条件:

(1) 调用 System.gc 时,系统建议执行 Full GC,但是不必然执行

(2) 老年代空间不足

(3) 方法区空间不足

(4) 通过 Minor GC 后进入老年代的平均大小大于老年代的可用内存

(5) 由 Eden 区、From Space 区向 To Sp3ace 区复制时,对象大小大于 To Space 可存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小

1.4.13、JVM 性能调优?

1、设定堆内存大小

-Xmx:堆内存最大限制。

2、设定新生代大小。 新生代不宜太小,否则会有大量对象涌入老年代

-XX:NewSize:新生代大小

-XX:NewRatio 新生代和老生代占比

-XX:SurvivorRatio:伊甸园空间和幸存者空间的占比

3、设定垃圾回收器 年轻代用 -XX:+UseParNewGC 年老代用-XX:+UseConcMarkSweepGC

1.4.14、Java 内存模型?

Java 内存模型定义了多线程之间共享变量的可见性以及如何在需要的时候对共享变量进行同步。JMM 内部的实现通常是依赖于所谓的内存屏障,通过禁止某些重排序的方式,提供内存可见性保证,也就是实现了各种 happen-before 规则。

与 JVM 内存模型不同。

Java 内存模型即 Java Memory Model,简称 JMM。JMM 定义了 Java 虚拟机(JVM)在计算机内存(RAM)中的工作方式。JVM 是整个计算机虚拟模型,所以 JMM 是隶属于 JVM 的。

Java 内存模型定义了多线程之间共享变量的可见性以及如何在需要的时候对共享变量进行同步。

Java 线程之间的通信采用的是过共享内存模型,这里提到的共享内存模型指的就是 Java 内存模型(简称 JMM),JMM 决定一个线程对共享变量的写入何时对另一个线程可见。从抽象的角度来看,JMM 定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本。

1.4.15、Java 中堆和栈有什么区别?

最主要的区别就是栈内存用来存储局部变量和方法调用。

而堆内存用来存储 Java 中的对象。无论是成员变量,局部变量,还是类变量,它们指向的对象都存储在堆内存中。

独有还是共享

栈内存归属于单个线程,每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可 见,即栈内存可以理解成线程的私有内存。

而堆内存中的对象对所有线程可见。堆内存中的对象可以被所有线程访问。 异常错误

如果栈内存没有可用的空间存储方法调用和局部变量,JVM 会抛出

java.lang.StackOverFlowError。

而如果是堆内存没有可用的空间存储生成的对象,JVM 会抛出 java.lang.OutOfMemoryError。空间大小

栈的内存要远远小于堆内存,如果你使用递归的话,那么你的栈很快就会充满。如果递归没 有及时跳出,很可能发生 StackOverFlowError 问题。

1.4.16、常见的垃圾回收算法有哪些?简述其原理?

GC 最基础的算法有三种: 标记 -清除算法、复制算法、标记-压缩算法,我们常用的垃圾回收器一般都采用分代收集算法。

标记 -清除算法,“标记-清除”(Mark-Sweep)算法,如它的名字一样,算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。

复制算法,“复制”(Copying)的收集算法,它将可用内存按容量划分为大小相等的两块, 每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面, 然后再把已使用过的内存空间一次清理掉。

标记-压缩算法,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象 进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存

分代收集算法,“分代收集”(Generational Collection)算法,把 Java 堆分为新生代和老年代, 这样就可以根据各个年代的特点采用最适当的收集算法。

1.4.17、解释栈(stack)、堆(heap)和方法区(method area)的用法?

通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都 使用 JVM 中的栈空间;而通过 new 关键字和构造器创建的对象则放在堆空间,堆是垃圾收集器管理的主要区域,由于现在的垃圾收集器都采用分代收集算法,所以堆空间还可以细分 为新生代和老生代,再具体一点可以分为 Eden、Survivor(又可分为 From Survivor 和 To Survivor)、Tenured;方法区和堆都是各个线程共享的内存区域,用于存储已经被 JVM 加载的类信息、常量、静态变量、JIT 编译器编译后的代码等数据;程序中的字面量(literal)如直接书写的 100、”hello”和常量都是放在常量池中,常量池是方法区的一部分,。栈空间操作起来最快但是栈很小,通常大量的对象都是放在堆空间,栈和堆的大小都可以通过 JVM 的启动参数来进行调整,栈空间用光了会引发 StackOverflowError,而堆和常量池空间不足则会引发 OutOfMemoryError。

1.4.18、什么是类的加载?

类的加载是将字节码文件加载到内存中去,创建一个类的Class类通过这个Class类可以创建很多类的对象。类加载器分为启动类加载器,扩展类加载器、应用程序类加载器、自定义类加载器。通过不同的类加载器可以加载器不同来源的字节码文件

反射就是通过获取到CLASS对象而创建相应的类的对象

1.4.19、类加载器有哪些?

****启动类加载器:****Bootstrap ClassLoader,负责加载存放在 JDK\jre\lib(JDK 代表 JDK 的安装目录, 下同)下,或被-Xbootclasspath 参数指定的路径中的,并且能被虚拟机识别的类库

****扩展类加载器****:Extension ClassLoader,

该加载器由 sun.misc.Launcher$ExtClassLoader 实现, 它负责加载 DK\jre\lib\ext 目录中,或者由 java.ext.dirs 系统变量指定的路径中的所有类库(如javax.*开头的类),开发者可以直接使用扩展类加载器。

****应用程序类加载器****:Application ClassLoader,该类加载器由 sun.misc.Launcher$AppClassLoader

来实现,它负责加载用户类路径(ClassPath)所指定的类,开发者可以直接使用该类加载器

****自定义类加载器****:继承CLASSloader类、并实现其loderclass方法和findclass方法

1.4.20、Java 对象创建过程?
  1. JVM 遇到一条新建对象的指令时首先去检查这个指令的参数是否能在常量池中定义到一个类的符号引用。然后加载这个类(类加载过程在后边讲)

  2. 为对象分配内存。一种办法“指针碰撞”、一种办法“空闲列表”,最终常用的办法“本地线程 缓冲分配(TLAB)”

  3. 将除对象头外的对象内存空间初始化为 0

  4. 对对象头进行必要设置

1.4.21、 Java 中类的生命周期使什么?

1、加载,查找并加载类的二进制数据,在 Java 堆中也创建一个 java.lang.Class 类的对象

2、连接,连接又包含三块内容:验证、准备、初始化。 1)验证,文件格式、元数据、字节码、符号引用验证; 2)准备,为类的静态变量分配内存,并将其初始化为默认值; 3) 解析,把类中的符号引用转换为直接引用

3、初始化,为类的静态变量赋予正确的初始值

4、使用,new 出对象程序中使用

5、卸载,执行垃圾回收

1.4.22、都有哪些垃圾回收器?

Serial 收集器,串行收集器是最古老,最稳定以及效率高的收集器,可能会产生较长的停顿, 只使用一个线程去回收。

ParNew 收集器,ParNew 收集器其实就是 Serial 收集器的多线程版本。

Parallel 收集器,Parallel Scavenge 收集器类似 ParNew 收集器,Parallel 收集器更关注系统的吞吐量。

Parallel Old 收集器,Parallel Old 是 Parallel Scavenge 收集器的老年代版本,使用多线程和“标记-整理”算法

CMS 收集器,CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。

G1 收集器,G1 (Garbage-First)是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器. 以极高概率满足 GC 停顿时间要求的同时,还具备高吞吐量性能特征

1.4.23、 JVM 调优命令?

Sun JDK 监控和故障处理命令有 jps jstat jmap jhat jstack jinfo

1、jps,JVM Process Status Tool,显示指定系统内所有的 HotSpot 虚拟机进程。

2、jstat,JVM statistics Monitoring 是用于监视虚拟机运行时状态信息的命令,它可以显示出虚拟机进程中的类装载、内存、垃圾收集、JIT 编译等运行数据。

3、jmap,JVM Memory Map 命令用于生成 heap dump 文件

4、jhat,JVM Heap Analysis Tool 命令是与 jmap 搭配使用,用来分析 jmap 生成的 dump,jhat

内置了一个微型的 HTTP/HTML 服务器,生成 dump 的分析结果后,可以在浏览器中查看

5、jstack,用于生成 java 虚拟机当前时刻的线程快照。

6、jinfo,JVM Configuration info 这个命令作用是实时查看和调整虚拟机运行参数。

1.4.24、JVM 调优工具?

常用调优工具分为两类,jdk 自带监控工具:jconsole 和 jvisualvm,第三方有:MAT(Memory AnalyzerTool)、GChisto。

1、jconsole,Java Monitoring and Management Console 是从 java5 开始,在 JDK 中自带的 java

监控和管理控制台,用于对 JVM 中内存,线程和类等的监控

2、jvisualvm,jdk 自带全能工具,可以分析内存快照、线程快照;监控内存变化、GC 变化等。

3、MAT,Memory Analyzer Tool,一个基于 Eclipse 的内存分析工具,是一个快速、功能丰富的 Java heap 分析工具,它可以帮助我们查找内存泄漏和减少内存消耗

4、GChisto,一款专业分析 gc 日志的工具

1.4.25、描述一下 JVM 加载 class 文件的原理机制?

JVM 中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java 中的类加载器是一个重要的 Java 运行时系统组件,它负责在运行时查找和装入类文件中的类。类的加载是指把类的.class 文件中的数据读入到内存中,通常是创建一个字节数组读入.class 文件

1.4.26、GC 是什么?为什么要有 GC?

GC 是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会

导致程序或系统的不稳定甚至崩溃,Java 提供的 GC 功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,

Java 语言没有提供释放已分配内存的显示操作方法。

1.4.27、垃圾回收器的基本原理是什么?

对于 GC 来说,当程序员创建对象时,GC 就开始监控这个对象的地址、大小以及使用情况。通常,GC 采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象

是"可达的",哪些对象是"不可达的"。当 GC 确定一些对象为"不可达"时,GC 就有责任回收这些内存空间。可以。程序员可以手动执行 System.gc(),通知 GC 运行,但是 Java 语言规范并不保证 GC 一定会执行。

1.4.28、 Java 中的引用类型有几种?

强引用:String a=”sd” 只要强引用存在,垃圾回收器就不会回收这个对象

软引用:如果内存足够则不回收,如果内存不足则回收,一般用于内存敏感的高速缓存,缓存数据,提高数据的获取速度。如果软引用被回收JVM会将此引用加入到引用队列中去

弱引用:弱引用比软引用更悲催,不管内存足不足够,当JVM发现只有弱引用的时候就会回收,短时间缓存某些次要数据。;

虚引用:使对象进入不可用状态,等****待****下次JVM垃圾回收,从而使对象进入引用列队中。

引用队列:通过引用队列可以了解JVM垃圾回收情况

1.5.Java JUC

1.5.1、Java创建线程之后,直接调用start()方法和run()的区别?

启动一个线程是调用 start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由 JVM 调度并执行。这并不意味着线程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。

1.5.2、线程B怎么知道线程A修改了变量?

volatile 修饰变量

synchronized 修饰修改变量的方法

wait/notify while 轮询

1.5.3、synchronized 和 Volatile、CAS 比较?

synchronized 是悲观锁,属于抢占式,会引起其他线程阻塞。volatile 提供多线程共享变量可见性和禁止指令重排序优化。CAS 是基于冲突检测的乐观锁(非阻塞)

1.5.4、 线程间通信,wait 和 notify 的理解和使用?

1 wait 和 notify 必须配合 synchronized 关键字使用。

2 wait 方法释放锁,notify 方法不释放锁。

3 还要注意一点 就是涉及到线程之间的通信,就肯定会用到 validate 修饰。

1.5.5、定时线程的使用?

1、普通线程死循环

2、使用定时器 timer

3、使用定时调度线程池 ScheduledExecutorService

1.5.6、线程同步的方法?

wait():使一个线程处于等待状态,并且释放所持有的对象的 lock。

sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException 异常。

notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒 某一个等待状态的线程,而是由 JVM 确定唤醒哪个线程,而且不是按优先级。

notityAll():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是 让它们竞争。

1.5.7、进程和线程的区别?

1、调度:线程作为CPU调度和分配的基本单位,进程作为拥有资源的基本单位。

2、并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可以并发执行。

3、拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于 进程的资源。

4、系统开销:在创建或撤销进程的时候,由于系统都要为之分配和回收资源,导致系统的明显大于创建或撤销线程时的开销。但进程有独立的地址空间,进程崩溃后,在保护模式下 不会对其他的进程产生影响,而线程只是一个进程中的不同的执行路径。线程有自己的堆栈 和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多 进程的程序要比多线程的程序健壮,但是在进程切换时,耗费的资源较大,效率要差些。

1.5.8、什么叫线程安全?

如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。 如果每次运行结果和单线程运行的结果是一样的,而且其他的变量 的值也和预期的是一样的,就是线程安全的。一个线程安全的计数器类的同一个实例对象在被多个线程使用的情况下也不会出现计算失误。很显然你可以将集合类分 成两组,线程安全和非线程安全的。

1.5.9、线程的几种状态?

1、新建状态(New):新创建了一个线程对象。

2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的 start()方法。该状态的线程位于“可运行线程池”中,变得可运行,只等待获取 CPU 的使用权。即在就绪状态的进程除 CPU 之外,其它的运行所需资源都已全部获得。

3、运行状态(Running):就绪状态的线程获取了 CPU,执行程序代码。

4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃 CPU 使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。

阻塞的情况分三种:

(1) 、等待阻塞:运行的线程执行 wait()方法,该线程会释放占用的所有资源,JVM 会把该线程放入“等待池”中。进入这个状态后,是不能自动唤醒的,必须依靠其他线程调用 notify() 或 notifyAll()方法才能被唤醒,

(2) 、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则 JVM

会把该线程放入“锁池”中。

(3) 、其他阻塞:运行的线程执行 sleep()或 join()方法,或者发出了 I/O 请求时,JVM 会把该线程置为阻塞状态。当 sleep()状态超时、join()等待线程终止或者超时、或者 I/O 处理完毕时, 线程重新转入就绪状态。

5、死亡状态(Dead):线程执行完了或者因异常退出了 run()方法,该线程结束生命周期。

1.5.10、volatile 变量和 atomic 变量有什么不同?

volatile 变量和 atomic 变量看起来很像,但功能却不一样。Volatile 变量可以确保先行关系, 即写操作会发生在后续的读操作之前, 但它并不能保证原子性。例如用 volatile 修饰 count 变量那么 count++ 操作就不是原子性的。而 AtomicInteger 类提供的 atomic 方法可以让这种操作具有原子性如 getAndIncrement()方法会原子性 的进行增量操作把当前值加一,其它数据类型和引用变量也可以进行相似操作。

1.5.11、Java中什么是静态条件?

竞态条件会导致程序在并发情况下出现一些 bugs。多线程对一些资源的竞争的时候就会产生竞态条件,如果首先要执行的程序竞争失败排到后面执行了, 那么整个程序就会出现一些不确定的 bugs。这种 bugs 很难发现而且会重复出现,因为线程间的随机竞争。

1.5.12、 Java 中如何停止一个线程?

Java 提供了很丰富的 API 但没有为停止线程提供 API。JDK 1.0 本来有一些像 stop(), suspend() 和 resume()的控制方法但是由于潜在的死锁威胁因此在后续的 JDK 版本中他们被弃用了, 之后 Java API 的设计者就没有提供一个兼容且线程安全的方法来停止一个线程。当 run() 或者 call() 方法执行完的时候线程会自动结束,如果要手动结束一个线程,你可以用 volatile 布尔变量来退出 run()方法的循环或者是取消任务来中断线程。

1.5.13、线程池的优点
1.5.1

1) 重用存在的线程,减少对象创建销毁的开销。

2) 可有效的控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。

3) 提供定时执行、定期执行、单线程、并发数控制等功能。

1.5.14、 volatile 的理解?

volatile 关键字的两层语义

一旦一个共享变量(类的成员变量、类的静态成员变量)被 volatile 修饰之后,那么就具备了两层语义:

1) 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。

2) 禁止进行指令重排序。

用 volatile 修饰之后,变量的操作:

第一:使用 volatile 关键字会强制将修改的值立即写入主存;

第二:使用 volatile 关键字的话,当线程 2 进行修改时,会导致线程 1 的工作内存中缓存变量 stop 的缓存行无效(反映到硬件层的话,就是 CPU 的 L1 或者 L2 缓存中对应的缓存行无效);

第三:由于线程 1 的工作内存中缓存变量stop 的缓存行无效,所以线程 1 再次读取变量 stop

的值时会去主存读取。

1.5.15、实现多线程有几种方式?

在语言层面有两种方式。java.lang.Thread 类的实例就是一个线程但是它需要调用java.lang.Runnable 接口来执行,由于线程类本身就是调用的 Runnable 接口所以你可以继承java.lang.Thread 类或者直接调用 Runnable 接口来重写 run()方法实现线程。

1.5.16、Java 中 notify 和 notifyAll 有什么区别?

notify()方法不能唤醒某个具体的线程,所以只有一个线程在等 待的时候它才有用武之地。而 notifyAll()唤醒所有线程并允许他们争夺锁确保了至少有一个线程能继续运行。

1.5.17、什么是乐观锁和悲观锁?

什么是乐观锁:乐观锁是每次读写时候不会去上锁,认为别的线程不会修改,但是会进行比较自己拿去的数据和之前记录进行比较没有改变就替换,被改变了则从新操作,底层就是CAS的思想

悲观锁:每次拿数据的时候认为别的线程都会修改,所以每次都会加锁,别的线程会一直阻塞直到拿到锁为止

乐观锁适用于多读的场景

悲观锁使用与多写的场景

1.5.18、线程的创建方式?

方式一:继承 Thread 类

方式二:实现 Runnable 接口

方式三:实现 Callable 接口方式四:使用线程池的方式

1.5.19、线程池的作用?

创建线程要花费昂贵的资源和时间,如果任务来了才创建线程那么响应时间会变长,而且一个进程能创建的线程数有限。为了避免这些问题,在程序启动的时 候就创建若干线程来响应处理,它们被称为线程池,里面的线程叫工作线程。从 JDK1.5 开始,Java API 提供了 Executor框架让你可以创建不同的线程池。比如单线程池,每次处理一个任务;数目固定的线程池或者是缓存线程池(一个适合很多生存期短 的任务的程序的可扩展线程池)。

1.5.20、wait 和 sleep 的区别?

sleep 是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程, 但是监控状态依然保持,到时后会自动恢复。调用 sleep 不会释放对象锁。

wait 是 Object 类的方法,对此对象调用 wait 方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出 notify 方法(或 notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。

1.5.21、产生死锁的条件?

资源互斥: 当一个资源被一个进程使用时候, 其他继承不能使用该资源

资源不可剥夺: 进程已持有的资源在使用完之前是不可被剥夺的, 只能在使用完后由自己释放

请求和保持: 当进程在请求其他资源的时候, 对自己已持有的资源保持不放

循环等待: 即存在一个等待队列: 例如: A 占有 B 的资源, B 占有 C 的资源, C 占有 A 的资源, 这样就形成了一个等待环路

解决死锁方法

资源一次性分配(破坏请求条件): 一次性分配所有的资源, 这样就不会再有请求了

(破坏保持条件): 一个进程只要有一个资源得不到分配, 就也不给这个进程分配其他资源

可剥夺资源(破坏不可剥夺性): 一个进程即使获得了部分资源, 但是如果得不到其他资源, 就需要释放掉已有的资源

资源有序分配(破坏循环等待): 系统为每类资源分配一个编号, 每一个进程按照编号以递增的顺序请求资源, 释放则相反

1.5.22、请写出实现线程安全的几种方式?

方式一:使用同步代码块方式二:使用同步方法

方式三:使用ReentrantLock

1.5.23、守护线程是什么?它和非守护线程的区别?

程序运行完毕,jvm 会等待非守护线程完成后关闭,但是 jvm 不会等待守护线程.守护线程最典型的例子就是 GC 线程.

1.5.24、什么是多线程的上下文切换?

多线程的上下文切换是指 CPU 控制权由一个已经正在运行的线程切换到另外一个就绪并等待获取 CPU 执行权的线程的过程.

1.5.24、Callable 和 Runnable 的区别是什么?

callable抛出异常

callable有返回值

.Callable 通常需要和Future/FutureTask 结合使用,用于获取异步计算结果.

1.5.25、线程阻塞有哪些原因?

1、sleep() 允许 指定以毫秒为单位的一段时间作为参数,它使得线程在指定的时间内进入阻塞状态,不能得到 CPU 时间,指定的时间一过,线程重新进入可执行状态。典型地,sleep()被用在等待某个资源就绪的情形:测试发现条件不满足后,让线程阻塞一段时间后重新测试, 直到条件满足为止

2、suspend() 和 resume() 两个方法配套使用,suspend()使得线程进入阻塞状态,并且不会自动恢复,必须其对应的 resume() 被调用,才能使得线程重新进入可执行状态。典型地, suspend() 和 resume() 被用在等待另一个线程产生的结果的情形:测试发现结果还没有产生后,让线程阻塞,另一个线程产生了结果后,调用 resume() 使其恢复。

suspend会导致死锁,因为挂起后,是不释放锁的,别人也就阻塞着,如果没人唤醒,那就一直死锁

3、yield() 使当前线程放弃当前已经分得的 CPU 时间,但不使当前线程阻塞,即线程仍处于可执行状态,随时可能再次分得 CPU 时间。调用 yield() 的效果等价于调度程序认为该线程已执行了足够的时间从而转到另一个线程

4、wait() 和 notify() 两个方法配套使用,wait() 使得线程进入阻塞状态,它有两种形式, 一种允许 指定以毫秒为单位的一段时间作为参数,另一种没有参数,前者当对应的 notify() 被调用或者超出指定时间时线程重新进入可执行状态,后者则必须对应的 notify() 被调用.

1.5.26、synchronized 和 Lock 的区别?

主要相同点:Lock 能完成 synchronized 所实现的所有功能

主要不同点:Lock 有比 synchronized 更精确的和更好的性能。synchronized 会自动释放锁,而 Lock 一定要求程序员手工释放,并且必须在 finally 从句中释放。

1.5.27、ThreadLocal 是什么?有什么作用?

Java中的ThreadLocal类允许我们创建只能被同一个线程读写的变量。因此,如果一段代码含有一个ThreadLocal变量的引用,即使两个线程同时执行这段代码,它们也无法访问到对方的ThreadLocal变量。

就是当我们只想在本身的线程内使用的变量,可以用 ThreadLocal 来实现,并且这些变量是和线程的生命周期密切相关的,线程结束,变量也就销毁了

所以说 ThreadLocal 不是为了解决线程间的共享变量问题的,如果是多线程都需要访问的数据,那需要用全局变量加同步机制。

Static 就只有一份

使用场景

1.存放当前session用户

简单说 ThreadLocal 就是一种以空间换时间的做法,在每个 Thread 里面维护了一个以开地址法实现的 ThreadLocal.ThreadLocalMap,把数据进行隔离,数据不共享,自然就没有线程安全方面的问题了。

1.5.28、交互方式分为同步和异步两种?

同步交互:指发送一个请求,需要等待返回,然后才能够发送下一个请求,有个等待过程; 异步交互:指发送一个请求,不需要等待返回,随时可以再发送下一个请求,即不需要等待。区别:一个需要等待,一个不需要等待,在部分情况下,我们的项目开发中都会优先选择不 需要等待的异步交互方式

1.5.29、什么是线程?

线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作 单位。程序员可以通过它进行多处理器编程,你可以使用多线程对 运算密集型任务提速

1.5.30、什么是 FutureTask?

FutureTask 实现 Future 接口和 RunnableFuture 接口,意味着可以将 FutureTask 用作 Runnable

在 Java 并发程序中 FutureTask 表示一个可以取消的异步运算。它有启动和取消运算、查询运算是否完成和取回运算结果等方法。只有当运算完 成的时候结果才能取回,如果运算尚未完成 get 方法将会阻塞。一个 FutureTask 对象可以对调用了 Callable 和 Runnable 的对象进行包 装,由于 FutureTask 也是调用了 Runnable 接口所以它可以提交给 Executor 来执行。

1.5.31、Java 中 interrupted 和 isInterruptedd 方法的区别?

*interrupted********()* ****和********isInterrupted()********的主要区别是前者会将中断状态清除而后者不会****。Java 多线程的中断机制是用内部标识来实现的,调用 Thread.interrupt()来中断一个线程就会设置中断标识为 true。当中断线程调用静态方法 Thread.interrupted()来 检查中断状态时,中断状态会被清零。而非静态方法 isInterrupted()用来查询其它线程的中断状态且不会改变中断状态标识。简单的说就是任何抛 出 InterruptedException 异常的方法都会将中断状态清零。无论如何,一个线程的中断状态有有可能被其它线程调用中断来改变。

1.5.32、死锁的原因?

1) 是多个线程涉及到多个锁,这些锁存在着交叉,所以可能会导致了一个锁依赖的闭环。例如:线程在获得了锁 A 并且没有释放的情况下去申请锁 B,这时,另一个线程已经获得了锁 B,在释放锁 B 之前又要先获得锁 A,因此闭环发生,陷入死锁循环。

2) 默认的锁申请操作是阻塞的。

所以要避免死锁,就要在一遇到多个对象锁交叉的情况,就要仔细审查这几个对象的类中的 所有方法,是否存在着导致锁依赖的环路的可能性。总之是尽量避免在一个同步方法中调用 其它对象的延时方法和同步方法。

1.5.32、什么是自旋

很多 synchronized 里面的代码只是一些很简单的代码,执行时间非常快,此时等待的线程都加锁可能是一种不太值得的操作,****因为线程阻塞涉及到用户态和内核态切换的问题****。既然synchronized 里面的代码执行得非常快, 不妨让等待锁的线程不要被阻塞, 而是在synchronized 的边界做忙循环,这就是自旋。如果做了多次忙循环发现还没有获得锁,再阻塞,这样可能是一种更好的策略。

1.5.32、怎么唤醒一个阻塞的线程?

如果线程是因为调用了 wait()、sleep()或者 join()方法而导致的阻塞,可以中断线程,并且通过抛出 InterruptedException 来唤醒它;如果线程遇到了 IO 阻塞,无能为力,因为 IO 是操作系统实现的,Java 代码并没有办法直接接触到操作系统。

1.5.33、如果提交任务时,线程池队列已满,这时会发生什么?

许多程序员会认为该任务会阻塞直到线程池队列有空位。事实上如果一个任务不能被调度执 行那么 ThreadPoolExecutor’s submit()方法将会抛出一个 RejectedExecutionException 异常。

1.5.34、什么是线程局部变量?

线程局部变量是局限于线程内部的变量,属于线程自身所有,不在多个线程间共享。Java 提供 ThreadLocal 类来支持线程局部变量,是一种实现线程安全的方式。但是在管理环境下(如web 服务器)使用线程局部变量的时候要特别小心,在这种情况下,工作线程的生命周期比任何应用变量的生命周期都要长。任何线程局部变量一旦在工作完成后没有释放,Java 应用就存在内存泄露的风险。

1.5.35、使用 volatile 关键字的场景?

synchronized 关键字是防止多个线程同时执行一段代码,那么就会很影响程序执行效率,而volatile 关键字在某些情况下性能要优于 synchronized,但是要注意 volatile 关键字是无法替代synchronized 关键字的,因为volatile 关键字无法保证操作的原子性。通常来说,使用volatile 必须具备以下 2 个条件:

1) 对变量的写操作不依赖于当前值

2) 该变量没有包含在具有其他变量的不变式中

1.5.36、线程池的工作原理,几个重要参数?

ThreadPoolExecutor(intcorePoolSize,intmaximumPoolSize,longkeepAliveTi me,TimeUnit unit,BlockingQueue workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)

参数说明:

corePoolSize 核心线程数

maximumPoolSize 最大线程数,一般大于等于核心线程数

keepAliveTime 线程存活时间(针对最大线程数大于核心线程数时,非核心线程) unit 存活时间单位,和线程存活时间配套使用

workQueue 任务队列threadFactory 创建线程的工程handler 拒绝策略

1.5.37、线程池的类型?

五种线程池:

ExecutorService threadPool = null;

threadPool = Executors.newCachedThreadPool();//有缓冲的线程池,线程数 JVM 控制

threadPool = Executors.newFixedThreadPool(3);//固定大小的线程池threadPool = Executors.newScheduledThreadPool(2);

threadPool = Executors.newSingleThreadExecutor();//单线程的线程池,只有一个线程在工

threadPool = new ThreadPoolExecutor();//默认线程池,可控制参数比较多

1.5.38、 线程池的阻塞队列有哪些?

三种阻塞队列:

BlockingQueue workQueue = null;

workQueue = new ArrayBlockingQueue<>(5);//基于数组的先进先出队列,有界workQueue = new LinkedBlockingQueue<>();//基于链表的先进先出队列,无界workQueue = new SynchronousQueue<>();//无缓冲的等待队列,无界

四种拒绝策略

等待队列已经排满了,再也塞不下新任务,同时线程池中线程也已经达到 maximumPoolSize

数量,无法继续为新任务服务,这个时候就需要使用拒绝策略来处理。

RejectedExecutionHandler rejected = null;

rejected = new ThreadPoolExecutor.AbortPolicy();//默认,队列满了丢任务抛出异常,直接抛出 RejectedExecutionException 异常阻止系统正常运行。

rejected = new ThreadPoolExecutor.DiscardPolicy();//队列满了丢任务不异常,直接丢弃任务,不予任何处理也不抛出异常。如果允许任务丢失,这是最好的一种方案。

rejected = new ThreadPoolExecutor.DiscardOldestPolicy();//将最早进入队列的任务删,之后再尝试加入队列, 抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务。

rejected = new ThreadPoolExecutor.CallerRunsPolicy();//如果添加到线程池失败,那么主线程会自己去执行该任务,调用者运行”一种调节机制,该策略既不会丢弃任务,也不会抛出异常,而是将某些任务回退给调用者,从而降低新任务的流量。

1.6设计模式

1.说一下你熟悉的设计模式?

单例模式:保证被创建一次,节省系统开销。 工厂模式(简单工厂、抽象工厂):解耦代码。

观察者模式:定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,它的所有的 依赖者都会收到通知并自动更新。

外观模式:提供一个统一的接口,用来访问子系统中的一群接口,外观定义了一个高层的接 口,让子系统更容易使用。

模版方法模式:定义了一个算法的骨架,而将一些步骤延迟到子类中,模版方法使得子类可 以在不改变算法结构的情况下,重新定义算法的步骤。

状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

2.简单工厂和抽象工厂的区别?

简单工厂:用来生产同一等级结构中的任意产品,对于增加新的产品,无能为力。

工厂方法:用来生产同一等级结构中的固定产品,支持增加任意产品。

抽象工厂:用来生产不同产品族的全部产品,对于增加新的产品,无能为力;支持增加产品族。

3. 设计模式的优点?

设计模式可在多个项目中重用。

设计模式提供了一个帮助定义系统架构的解决方案。 设计模式吸收了软件工程的经验。

设计模式为应用程序的设计提供了透明性。

设计模式是被实践证明切实有效的,由于它们是建立在专家软件开发人员的知识和经验 之上的。

4. 设计模式的六大基本原则?

(1) 单一原则(Single Responsibility Principle):一个类只负责一项职责,尽量做到类的只有一个行为原因引起变化;

(2) 里氏替换原则(LSP liskov substitution principle):子类可以扩展父类的功能,但不能改变原有父类的功能;

(3) 依赖倒置原则(dependence inversion principle):面向接口编程; (4)接口隔离(interface segregation principle):建立单一接口;

(5)迪米特原则(law of demeter LOD):最少知道原则,尽量降低类与类之间的耦合; (6)开闭原则(open closed principle):用抽象构建架构,用实现扩展原则;

5.单例模式?
6.设计模式的分类?
  1. 根据目的来分

根据模式是用来完成什么工作来划分,这种方式可分为创建型模式、结构型模式和行为型模 式 3 种。

创建型模式:用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使用分离”。

GoF 中提供了单例、原型、工厂方法、抽象工厂、建造者等 5 种创建型模式。

结构型模式:用于描述如何将类或对象按某种布局组成更大的结构,GoF 中提供了代理、适配器、桥接、装饰、外观、享元、组合等 7 种结构型模式。

行为型模式:用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责。GoF 中提供了模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器等 11 种行为型模式。

  1. 根据作用范围来分

根据模式是主要用于类上还是主要用于对象上来分,这种方式可分为类模式和对象模式两 种。

类模式:用于处理类与子类之间的关系,这些关系通过继承来建立,是静态的,在编译 时刻便确定下来了。GoF 中的工厂方法、(类)适配器、模板方法、解释器属于该模式。

对象模式:用于处理对象之间的关系,这些关系可以通过组合或聚合来实现,在运行时 刻是可以变化的,更具动态性。GoF 中除了以上 4 种,其他的都是对象模式。

7.种设计模式的具体的每种模式的功能?

单例(Singleton)模式:某个类只能生成一个实例,该类提供了一个全局访问点供外部获取 该实例,其拓展是有限多例模式。

原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。

工厂方法(Factory Method)模式:定义一个用于创建产品的接口,由子类决定生产什么产品。

抽象工厂(AbstractFactory)模式:提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。

建造者(Builder)模式:将一个复杂对象分解成多个相对简单的部分,然后根据不同需 要分别创建它们,最后构建成该复杂对象。

代理(Proxy)模式:为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。

适配器(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。

桥接(Bridge)模式:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替 继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。

装饰(Decorator)模式:动态的给对象增加一些职责,即增加其额外的功能。

外观(Facade)模式:为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。

享元(Flyweight)模式:运用共享技术来有效地支持大量细粒度对象的复用。

组合(Composite)模式:将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。

模板方法(TemplateMethod)模式:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。

策略(Strategy)模式:定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。

命令(Command)模式:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。

职责链(Chain of Responsibility)模式:把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。

状态(State)模式:允许一个对象在其内部状态发生改变时改变其行为能力。

观察者(Observer)模式:多个对象间存在一对多关系,当一个对象发生改变时,把这 种改变通知给其他多个对象,从而影响其他对象的行为。

中介者(Mediator)模式:定义一个中介对象来简化原有对象之间的交互关系,降低系 统中对象间的耦合度,使原有对象之间不必相互了解。

迭代器(Iterator)模式:提供一种方法来顺序访问聚合对象中的一系列数据,而不暴 露聚合对象的内部表示。

访问者(Visitor)模式:在不改变集合元素的前提下,为一个集合中的每个元素提供多 种访问方式,即每个元素有多个访问者对象访问。

备忘录(Memento)模式:在不破坏封装性的前提下,获取并保存一个对象的内部状态, 以便以后恢复它。

解释器(Interpreter)模式:提供如何定义语言的文法,以及对语言句子的解释方法, 即解释器。

8.UML 是什么?

**统一建模语言(Unified Modeling Language,UML)**是用来设计软件蓝图的可视化建模语言, 1997 年被国际对象管理组织(OMG)采纳为面向对象的建模语言的国际标准。它的特点是简单、统一、图形化、能表达软件设计中的动态与静态信息。

统一建模语言能为软件开发的所有阶段提供模型化和可视化支持。而且融入了软件工程领域 的新思想、新方法和新技术,使软件设计人员沟通更简明,进一步缩短了设计时间,减少开 发成本。它的应用领域很宽,不仅适合于一般系统的开发,而且适合于并行与分布式系统的 建模。

UML 从目标系统的不同角度出发,定义了用例图、类图、****对象图****、状态图、活动图、时序图、协作图、构件图、部署图等 9 种图。

2.JavaWeb

1.session 和 cookie 的区别?

session存在服务器,cookie存在客户端

sessionID存在客户端的cookie里面,每次通过cookie里的sessionId获取对应的session

因为session存在服务器占服务器的内存,所以一般存的都是重要的信息,默认的时间是30分钟

cookie分为永久cookie和会话cookie永久cookie存在于硬盘里面,会话cookie存在浏览器里,浏览器关闭则cookie消失

那么,session 在什么情况下丢失,就是在服务器关闭的时候,或者是 session 过期(默认时间是 30 分钟),再或 者 调 用 了 invalidate() 的 或 者 是 我 们 想 要 session 中 的 某 一 条 数 据 消 失 调 用session.removeAttribute()方法,然后 session 在什么时候被创建呢,确切的说是通过调用getsession()来创建,这就是 session 与 cookie 的区别.

2.session 和 cookie 联系?

session 是通过cookie 来工作的session 和cookie 之间是通过 C O O K I E [ ′ P H P S E S S I D ′ ] 来 联 系 的 , 通 过 _COOKIE['PHPSESSID']来联系的, 通过 COOKIE[PHPSESSID]_COOKIE[‘PHPSESSID’]可以知道 session 的 id,从而获取到其他的信息。

在购物网站中通常将用户加入购物车的商品联通 session_id 记录到数据库中,当用户再次访问是,通过 sessionid 就可以查找到用户上次加入购物车的商品。因为 sessionid 是唯一的, 记录到数据库中就可以根据这个查找了。

3.servlet 的生命周期?

实例化阶段。调bai用Servlet的构造器,创建一du个zhi Servlet对象;构造器只 执行一次;

2.初始化阶段。 调用daoinit()方法zhuan。整个servlet生命周期中,init()方法只执shu行一次;

3.就绪。调用service()方法。即创建的servlet方法。方法可以被多次调用。

4.销毁。调用destroy()方法。只执行一次。。通常情况下Servlet容器停止或者重新启动都会引起销毁Servlet对象的动作,但除此之外,Servlet容器也有自身管理Servlet对象的准则,整个生命周期并不需要人为进行干预。当 Web 容器关闭或者 Servlet 对象要从容器中被删除时,会自动调用 destory()方法。

4.什么是 webservice?

Web service平台是一套标准,它定义了应用程序如何在Web上实现互操作性。可以通过任何语言写客户端和服务端进行交互

5.jsp 和 servlet 的区别、共同点、各自应用的范围?

JSP是servlet的简易版本,本质上就是servlet。JSP侧重于视图,servlet侧重于逻辑控制

JSP编辑后就是sevlet

6.转发(forward)和重定向(redirect)的区别?

  1. 从地址栏显示来说

forward 是服务器请求资源,服务器直接访问目标地址的URL,把那个URL 的响应内容读取过来, 然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址.

redirect 是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的 URL.

  1. 从数据共享来说

forward:转发页面和转发到的页面可以共享 request 里面的数据. redirect:不能共享数据.

  1. 从运用地方来说

forward:一般用于用户登陆的时候,根据角色转发到相应的模块. redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等

  1. 从效率来说forward: 高 . redirect:低.

7.request.getAttribute()和 request.getParameter()有何区别?

1、request.getParameter()取得是通过容器的实现来取得通过类似 post,get 等方式传入的数据。

2、request.setAttribute()和 getAttribute()只是在 web 容器内部流转,仅仅是请求处理阶段。

3、getAttribute 是返回对象,getParameter 返回字符串

4、getAttribute()一向是和 setAttribute()一起使用的,只有先用 setAttribute()设置之后,才能够通过 getAttribute()来获得值,它们传递的是 Object 类型的数据。而且必须在同一个 request 对象中使用才有效。,而 getParameter()是接收表单的 get 或者 post 提交过来的参数

8.jsp 静态包含和动态包含的区别?

  1. 两者格式不同,静态包含:<%@ include file=“文件” %>,而动态包含:

    1. 包含时间不同,静态包含是先将几个文件合并,然后再被编译,缺点就是如果含有相同的 标签,会出错。动态包含是页面被请求时编译,将结果放在一个页面。

    2. 生成的文件不同,静态包含会生成一个包含页面名字的 servlet 和 class 文件;而动态包含会各自生成对应的 servlet 和 class 文件

    3. 传递参数不同,动态包含能够传递参数,而静态包含不能

9.MVC 的各个部分都有哪些技术来实现?如何实现?

MVC 是Model-View-Controller 的简写。“Model” 代表的是应用的业务逻辑(通过 JavaBean, EJB 组件实现), “View” 是应用的表示面(由 JSP 页面产生),“Controller” 是提供应用的处理过程控制(一般是一个 Servlet),通过这种设计模型把应用逻辑,处理过程和显示

逻辑分成不同的组件实现。这些组件可以进行交互和重用。

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

JSP 有 9 个内置对象:

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

response:封装服务器对客户端的响应; pageContext:通过该对象可以获取其他对象; session:封装用户会话的对象;

application:封装服务器运行环境的对象; out:输出服务器响应的输出流对象; config:Web 应用的配置对象;

page:JSP 页面本身(相当于 Java 程序中的 this); exception:封装页面抛出异常的对象。

11. Http 请求的 get 和 post 方法的区别。

  1. get的数据在地址栏 post的在请求体内

  2. get不安全 post不会出现在地址栏是安全的

  3. get的信息在地址栏有大小限制,不同浏览器有不同的大小限制

  4. get是向服务器请求数据、Post是修改数据

  5. get请求会被缓存在浏览器中Post不会被缓存在浏览器

12.tomcat 容器是如何创建 servlet 类实例?用到了什么原理?

当容器启动的时候加载web.xml查看servlet注册信息,通过反射的方式创建servlet实例

如果load-on-startup为正数则一开始就实例化,如果为负数则第一次请求实例

当容器启动时,会读取在 webapps 目录下所有的 web 应用中的 web.xml 文件,然后对 xml 文件进行解析,并读取 servlet 注册信息。然后,将每个应用中注册的 servlet 类都进行加载, 并通过反射的方式实例化。(有时候也是在第一次请求时实例化)

在 servlet 注册时加上1如果为正数,则在一开始就实例化,如果不写或为负数,则第一次请求实例化。

13.JDBC 访问数据库的基本步骤是什么?

第一步:Class.forName()加载数据库连接驱动;

第二步:DriverManager.getConnection()获取数据连接对象;

第三步:根据 SQL 获取 sql 会话对象,有 2 种方式 Statement、PreparedStatement ;

第四步:执行 SQL,执行 SQL 前如果有参数值就设置参数值 setXXX();

第五步:处理结果集;

第六步:关闭结果集、关闭会话、关闭连接。

14.为什么要使用 PreparedStatement?

PreparedStatement 接口继承 Statement,PreparedStatement 实例包含已编译的 SQL 语句,所以其执行速度要快于 Statement 对象。

作为 Statement 的子类, PreparedStatement 继承了 Statement 的所有功能。三种方法

execute、 executeQuery 和 executeUpdate 已被更改以使之不再需要参数。在 JDBC 应用中,多数情况下使用 PreparedStatement,原因如下:

代码的可读性和可维护性。Statement 需要不断地拼接,而 PreparedStatement 不会。PreparedStatement 尽最大可能提高性能。DB 有缓存机制,相同的预编译语句再次被调用不会再次需要编译。

最重要的一点是极大地提高了安全性。Statement 容易被 SQL 注入,而 PreparedStatement

传入的内容不会和 sql 语句发生任何匹配关系。

15.数据库连接池的原理。为什么要使用连接池?

1、数据库连接是一件费时的操作,连接池可以使多个操作共享一个连接。

2、数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放 回去。我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是 我们可以通过连接池的管理机制监视数据库的连接的数量、使用情况,为系统开发,测试及 性能调整提供依据。

3、使用连接池是为了提高对数据库连接资源的管理

16.execute,executeQuery,executeUpdate 的区别是什么?

1、Statement 的 execute(String query)方法用来执行任意的 SQL 查询,如果查询的结果是一个ResultSet,这个方法就返回 true。如果结果不是 ResultSet,比如 insert 或者 update 查询,它就会返回 false 。 我们可以通过它的 getResultSet 方法来获取 ResultSet , 或者通过getUpdateCount()方法来获取更新的记录条数。

2、Statement 的 executeQuery(String query)接口用来执行 select 查询,并且返回 ResultSet。即使查询不到记录返回的 ResultSet 也不会为 null。我们通常使用 executeQuery 来执行查询语句, 这样的话如果传进来的是 insert 或者 update 语句的话, 它会抛出错误信息为“executeQuery method can not be used for update”的 java.util.SQLException。 ,

3、Statement 的 executeUpdate(String query)方法用来执行 insert 或者 update/delete(DML) 语句,或者 什么也不返回,对于 DDL 语句,返回值是 int 类型,如果是 DML 语句的话,它就是更新的条数,如果是 DDL 的话,就返回 0。

只有当你不确定是什么语句的时候才应该使用 execute() 方法, 否则应该使用

executeQuery 或者 executeUpdate 方法。

17. JDBC 的 ResultSet 是什么?

在查询数据库后会返回一个 ResultSet,它就像是查询结果集的一张数据表。

ResultSet 对象维护了一个游标,指向当前的数据行。开始的时候这个游标指向的是第一行。如果调用了 ResultSet 的 next()方法游标会下移一行,如果没有更多的数据了,next()方法会返回 false。可以在 for 循环中用它来遍历数据集。

默认的 ResultSet 是不能更新的,游标也只能往下移。也就是说你只能从第一行到最后一行遍历一遍。不过也可以创建可以回滚或者可更新的 ResultSet

当生成 ResultSet 的 Statement 对象要关闭或者重新执行或是获取下一个 ResultSet 的时候,ResultSet 对象也会自动关闭。

可以通过 ResultSet 的 getter 方法,传入列名或者从 1 开始的序号来获取列数据。

18. 什么是 Servlet?

Servlet 是继承Servlet是一个JAVA类主要用于处理客户端传来的 HTTP 请求,并返回一个响应。

19.doGet 和 doPost 方法有什么区别?

doGet:GET 方法会把名值对追加在请求的 URL 后面。因为 URL 对字符数目有限制,进而限制了用在客户端请求的参数值的数目。并且请求中的参数值是可见的,因此,敏感信息不能 用这种方式传递。

doPOST:POST 方法通过把请求参数值放在请求体中来克服GET 方法的限制,因此,可以发送的参数的数目是没有限制的。最后,通过 POST 请求传递的敏感信息对外部客户端是不可见的。

20. JSP 有哪些动作?分别是什么?

JSP 共有以下 6 种基本动作

jsp:include:在页面被请求的时候引入一个文件。jsp:useBean:寻找或者实例化一个 JavaBean。jsp:setProperty:设置 JavaBean 的属性。jsp:getProperty:输出某个 JavaBean 的属性。jsp:forward:把请求转到一个新的页面。

jsp:plugin:根据浏览器类型为 Java 插件生成 OBJECT 或 EMBED 标记

21.JSP 常用的指令?

page:针对当前页面的指令。include:包含另一个页面taglib:定义和访问自定义标签

22.页面间对象传递的方法?

request、session、application、cookie

23.JSP 中动态 INCLUDE 与静态 INCLUDE 的区别?

动态 include 用于 jsp:include 动作实现它总是会检查所含文件的变化,适用于包含动态页面,并且可以带参数。

静态include 用include 伪码实现,不会检查所含文件的变化,适用于包含静态页面<%@include file=“include.html”%>.

24.JSP 的四大范围?

JSP 中的四种作用域包括 page、request、session 和 application,具体来说: page 代表与一个页面相关的对象和属性。

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

session 代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的 session 中。

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

25. BS 与 CS 的联系与区别?

1.硬件环境不同:

C/S 一般建立在专用的网络上, 小范围里的网络环境, 局域网之间再通过专门服务器提供连接和数据交换服务.

B/S 建立在广域网之上的, 不必是专门的网络硬件环境,例与电话上网, 租用设备. 信息自己管理. 有比 C/S 更强的适应范围, 一般只要有操作系统和浏览器就行 2.对安全要求不同

C/S 一般面向相对固定的用户群, 对信息安全的控制能力很强. 一般高度机密的信息系统采用 C/S 结构适宜. 可以通过 B/S 发布部分可公开信息.

B/S 建立在广域网之上, 对安全的控制能力相对弱, 可能面向不可知的用户。3.对程序架构不同

C/S 程序可以更加注重流程, 可以对权限多层次校验, 对系统运行速度可以较少考虑.

B/S 对安全以及访问速度的多重的考虑, 建立在需要更加优化的基础之上. 比 C/S 有更高的要求 B/S 结构的程序架构是发展的趋势, 从 MS 的.Net 系列的 BizTalk 2000 Exchange 2000 等, 全面支持网络的构件搭建的系统. SUN 和IBM 推的JavaBean 构件技术等,使 B/S 更加成熟. 4.软件重用不同

C/S 程序可以不可避免的整体性考虑, 构件的重用性不如在 B/S 要求下的构件的重用性

好.

B/S 对的多重结构,要求构件相对独立的功能. 能够相对较好的重用.就入买来的餐桌可

以再利用,而不是做在墙上的石头桌子 5.系统维护不同

C/S 程序由于整体性, 必须整体考察, 处理出现的问题以及系统升级. 升级难. 可能是再做一个全新的系统

B/S 构件组成,方面构件个别的更换,实现系统的无缝升级. 系统维护开销减到最小.用户从网上自己下载安装就可以实现升级. 6.处理问题不同

C/S 程序可以处理用户面固定, 并且在相同区域, 安全要求高需求, 与操作系统相关. 应该都是相同的系统

B/S 建立在广域网上, 面向不同的用户群, 分散地域, 这是C/S 无法作到的. 与操作系统平台关系最小. 7.用户接口不同

C/S 多是建立的 Window 平台上,表现方法有限,对程序员普遍要求较高

B/S 建立在浏览器上, 有更加丰富和生动的表现方式与用户交流. 并且大部分难度减低, 减低开发成本. 8.信息流不同

C/S 程序一般是典型的中央集权的机械式处理, 交互性相对低

B/S 信息流向可变化, B-B B-C B-G 等信息、流向的变化, 更像交易中心。

26. 说出 Servlet 的生命周期,并说出 Servlet 和 CGI 的区别?

Web 容器加载 Servlet 并将其实例化后,Servlet 生命周期开始,容器运行其 init 方法进行Servlet 的初始化,请求到达时运行其 service 方法,service 方法自动派遣运行与请求对应的doXXX 方法(doGet,doPost)等,当服务器决定将实例销毁的时候调用其 destroy 方法。与 cgi 的区别在于 servlet 处于服务器进程中,它通过多线程方式运行其 service 方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而 CGI 对每个请求都产生新的进程, 服务完成后就销毁,所以效率上低于 servlet。

27. 如何防止表单重复提交?

针对于重复提交的整体解决方案:

1.用 redirect(重定向)来解决重复提交的问题2.点击一次之后,按钮失效

  1. 通过 loading(Loading 原理是在点击提交时,生成 Loading 样式,在提交完成之后隐藏该样式)

  2. 自定义重复提交过滤器

28.** request 作用?

1、获取请求参数 getParameter()

2、获取当前 Web 应用的虚拟路径 getContextPath

3、转发 getRequestDispatcher(路径).forward(request,response); 4、它还是一个域对象

29.get 请求中文乱码?

1、乱码的根本原因:

浏览器的编码方式 UTF-8 和 服务器的解码方式 ISO-859-1 不一样

2、解决方法:

  1. 第一种方式 使用 URLEncoder 和 URLDecoder 两个类 编解码。先以 iso-8895-1 进行编码,然后再以 utf-8 进行解码

  2. 第二种方式 使用 String 类的方法进行编解码

  3. 第三种方式 更改 server.xml 配置文件。

GET 请求是在URL 地址栏中传递请求参数的,它会被 Tomcat 服务器自动解码,而 Tomcat

服务器默认的字符集也是 ISO-8859-1,

所以我们需要修改 Tomcat 服务器的字符集为 UTF-8。

30.post 请求中文乱码问题?

1、post 请求方式乱码的原因是:因为 post 是以二进制流的形式发送到的服务器。服务器收到数据后。默认以 iso-8859-1 进行编码。

2、post 请求乱码解决,只需要在获取请求参数之前调用

request.setCharacterEncoding(“UTF-8”); 方法设置字符集 即可。

31. 响应乱码?

1、原因: 由服务器编码,默认使用 ISO-8859-1 进行编码由浏览器解码,默认使用 GBK 进行解码

2、解决方案

方法 1:设置响应头

response.setHeader(“Content-Type”,“text/html;charset=utf-8”);

方法 2:设置响应的内容类型

response.setContentType(“text/html;charset=utf-8”);

通过这种方式可以在响应头中告诉浏览器响应体的编码方式是 UTF-8;同时服务器也会采用该字符集进行编码

但需要注意的是,两种方法一定要在 response.getWriter()之前进行。

32.Cookie 对象的缺陷?

1、Cookie 是明文的,不安全

2、不同的浏览器对 Cookie 对象的数量和大小有限制

3、Cookie 对象携带过多费流量

4、Cookie 对象中的 value 值只能是字符串,不能放对象网络中传递数据只能是字符串

33.Session 的运行机制?

1、在服务器端创建 Session 对象,该对象有一个全球唯一的 ID

2 、在创建 Session 对象的同时创建一个特殊的 Cookie 对象, 该 Cookie 对象的名字是JSESSIONID,该 Cookie 对象的 value 值是 Session 对象的那个全球唯一的 ID,并且会将这个特殊的 Cookie 对象携带发送给浏览器

3、以后浏览器再发送请求就会携带这个特殊的 Cookie 对象

4、服务器根据这个特殊的 Cookie 对象的 value 值在服务器中寻找对应的 Session 对象,以此来区分不同的用户

34.钝化和活化?

1、Session 与 session 域中的对象一起从内存中被序列化到硬盘上的过程我们称为钝化。服务器关闭时会发生钝化。

2、Session 与 session 域中的对象一起从硬盘上反序列化到内存中的过程我们称为活化。服务器再次开启时会发生活化。

3、要保证 session 域中的对象能和 Session 一起被钝化和活化,必须保证对象对应的类实现

Serializable 接口

35.Filter 的工作原理?

Filter 接口中有一个 doFilter 方法,当我们编写好 Filter,并配置对哪个 web 资源进行拦截后,

WEB 服务器每次在调用 web 资源的 service 方法之前,

都会先调用一下 filter 的 doFilter 方法,因此,在该方法内编写代码可达到如下目的: 调用目标资源之前,让一段代码执行。

是否调用目标资源(即是否让用户访问 web 资源)。调用目标资源之后,让一段代码执行。

web 服务器在调用 doFilter 方法时,会传递一个 filterChain 对象进来,filterChain 对象是

filter 接口中最重要的一个对象,它也提供了一个

doFilter 方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则 web 服务器就会调用 web 资源的 service 方法,即 web 资源就会被访问,

否则 web 资源不会被访问

36.Filter 链是什么?

在一个 web 应用中,可以开发编写多个 Filter,这些 Filter 组合起来称之为一个 Filter 链。web 服务器根据 Filter 在 web.xml 文件中的注册顺序,

决定先调用哪个 Filter,当第一个 Filter 的 doFilter 方法被调用时,web 服务器会创建一个代表 Filter 链的 FilterChain 对象传递给该方法。在 doFilter

方法中,开发人员如果调用了FilterChain 对象的doFilter 方法,则web 服务器会检查FilterChain

对象中是否还有 filter,如果有,则调用第 2 个 filter, 如果没有,则调用目标资源。

37.监听器类型?

按监听的对象划分:servlet2.4 规范定义的事件有三种:

1.用于监听应用程序环境对象(ServletContext)的事件监听器 2.用于监听用户会话对象(HttpSession)的事件监听器

3.用于监听请求消息对象(ServletRequest)的事件监听器 按监听的事件类项划分

  1. 用于监听域对象自身的创建和销毁的事件监听器

  2. 用于监听域对象中的属性的增加和删除的事件监听器

  3. 用于监听绑定到 HttpSession 域中的某个对象的状态的事件监听器

在一个 web 应用程序的整个运行周期内, web 容器会创建和销毁三个重要的对象,

ServletContext,HttpSession,ServletRequest。

38.Servlet Filter Listener 启动顺序?

启动的顺序为 listener->Filter->servlet.

简单记为:理(Listener)发(Filter)师(servlet).

执行的顺序不会因为三个标签在配置文件中的先后顺序而改变。

3.SSM

1.Spring

1.1.Spring 中 beanFactory 和 ApplicationContext 的联系和区别?

BeanFactory 是 spring 中较为原始的 Factory,无法支持 spring 的许多插件,如 AOP 功能、

Web 应用等。

ApplicationContext 接口是通过 BeanFactory 接口派生而来的,除了具备 BeanFactory 接口的功能外,还具备资源访问、事件传播、国际化消息访问等功能。

总体区别如下:

1) 使用 ApplicationContext,配置 bean 默认配置是 singleton,无论是否使用,都会被实例化。优点是预先加载,缺点是浪费内存;

2) 使用 BeanFactory 实例化对象时,配置的 bean 等到使用的时候才会被实例化。优点是节约内存,缺点是速度比较慢,多用于移动设备的开发;

3) 没有特殊要求的情况下,应该使用 ApplicationContext 完成,ApplicationContext 可以实现

BeanFactory 所有可实现的功能,还具备其他更多的功能。

1.2.SpringIOC 注入的几种方式?

构造器注入

set 方法注入

接口注入

1.3. 拦截器与过滤器的区别?

1、拦截器是基于 java 的反射机制的,而过滤器是基于函数回调

2、拦截器不依赖与 servlet 容器,过滤器依赖与 servlet 容器。

3、拦截器只能对 action 请求起作用,而过滤器则可以对几乎所有的请求起作用。

4、拦截器可以访问 action 上下文、值栈里的对象,而过滤器不能访问。

5、在 action 的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次

1.4. SpringIOC 是什么?

Spring IOC 负责创建对象,管理对象(通过依赖注入(DI),装配对象,配置对象,并且管理这些对象的整个生命周期。

1.5. AOP 有哪些实现方式?

实现 AOP 的技术,主要分为两大类:

静态代理 - 指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强;

编译时编织(特殊编译器实现)

类加载时编织(特殊的类加载器实现)。

动态代理 - 在运行时在内存中“临时”生成 AOP 动态代理类,因此也被称为运行时增强。

JDK 动态代理、CGLIB

1.6. 解释一下代理模式?

1、代理模式: 代理模式就是本该我做的事,我不做,我交给代理人去完成。就比如,我生产了一些产品,我自己不卖,我委托代理商帮我卖,让代理商和顾客打交道,我自己负责主要产品的生产就可以了。 代理模式的使用,需要有本类,和代理类,本类和代理类共同实现统一的接口。然后在 main 中调用就可以了。本类中的业务逻辑一般是不会变动的,在我们需要的时候可以不断的添加代理对象,或者修改代理类来实现业务的变更。

2、代理模式可以分为: 静态代理 优点:可以做到在不修改目标对象功能的前提下,对目标功能扩展 缺点:因为本来和代理类要实现统一的接口,所以会产生很多的代理类,类太多,一旦接口增加方法,目标对象和代理对象都要维护。 动态代理(JDK 代理/接口代理) 代理对象,不需要实现接口,代理对象的生成,是利用 JDK 的 API,动态的在内存中构建代理对象,需要我们指定代理对象/目标对象实现的接口的类型。 Cglib 代理 特点: 在内存中构建一个子类对象,从而实现对目标对象功能的扩展。

3、使用场景: 修改代码的时候。不用随便去修改别人已经写好的代码,如果需要修改的话, 可以通过代理的方式来扩展该方法。 隐藏某个类的时候,可以为其提供代理类 当我们要扩展某个类功能的时候,可以使用代理类 当一个类需要对不同的调用者提供不同的调用权限的时候,可以使用代理类来实现。 减少本类代码量的时候。 需要提升处理速度的时候。就比如我们在访问某个大型系统的时候,一次生成实例会耗费大量的时间,我们可以采用代理模式,当用来需要的时候才生成实例,这样就能提高访问的速度。

1.7. Spring bean 的生命周期?

1、Spring 容器根据配置中的 bean 定义中实例化 bean。

2、Spring 使用依赖注入填充所有属性,如 bean 中所定义的配置。

3 、如果 bean 实现 BeanNameAware 接口, 则工厂通过传递 bean 的 ID 来调用

setBeanName()。

4 、 如果 bean 实现 BeanFactoryAware 接口, 工厂通过传递自身的实例来调用

setBeanFactory()。

5、如果存在与 bean 关联的任何 BeanPostProcessors,则调用 preProcessBeforeInitialization()

方法。

6、如果为 bean 指定了 init 方法( 的 init-method 属性),那么将调用它。

7 、 最 后 , 如 果 存 在 与 bean 关 联 的 任 何 BeanPostProcessors , 则 将 调 用

postProcessAfterInitialization() 方法。

8、如果 bean 实现 DisposableBean 接口,当 spring 容器关闭时,会调用 destory()。

9、如果为 bean 指定了 destroy 方法( 的 destroy-method 属性),那么将调用它。

1.8. Spring 框架中都用到了哪些设计模式?

代理模式,在 AOP 中被使用最多。

单例模式,在 Spring 配置文件中定义 bean 的时候默认的是单例模式。工厂模式, BeanFactory 用来创建对象的实例。

模板方法, 用来解决重复性代码。

前端控制器,Spring 提供了 DispatcherSerclet 来对请求进行分发。视图帮助,Spring 提供了一系列的 JSP 标签。

依赖注入,它是惯穿于 BeanFactory/ApplicationContext 接口的核心理念。

1.9. Spring 中的事件处理?

1、Spring 的核心是 ApplicatonContext,它负责管理 bean 的完整的生命周期。Spring 提供了以下 内 置 事 件 : ContextRefreshedEvent ContextStartedEvent ContextStoppedEvent ContextClosedEvent RequestHandleEvent

2、由于 Spring 的****事件处理是单线程的****,所以如果一个事件被发布,直至并且除非所有的接收者得到的该消息,该进程被阻塞并且流程将不会继续。因此,如果事件处理被使用,在 设计应用程序时应注意。

3、****监听上下文事件****

4、自定义事件

1.10. 使用 Sping 框架的好处是什么?

低入侵式设计

解耦

集成

DI

声明式事务

1.11. 解释 Spring 支持的几种 bean 的作用域?

当通过 Spring 容器创建一个 Bean 实例的时候,不仅可以完成 bean 实例的实力化,还可以为 bean 指定作用域。Spring bean 元素的支持以下 5 种作用域:

Singleton:单例模式,在整个 spring IOC 容器中,使用 singleton 定义的 bean 将只有一个实例。

Prototype:多例模式,每次通过容器中的 getBean 方法获取 prototype 定义的 beans 时,都会产生一个新的 bean 的实例。

Request:对于每次 Http 请求,使用 request 定义的 bean 都会产生一个新的实例,只有在

web 应用时候,该作用域才会有效。

Session:对于每次 Http Session,使用 session 定义的 Bean 都将产生一个新的实例。

Globalsession:每个全局的 Http Sesisonn,使用 session 定义的本都将产生一个新的实例

1.12. 在 Spring 中如何注入一个 java 集合?

Spring 提供理论四种集合类的配置元素:

lt;List&: 该标签用来装配 有重复值的 list 值lt;set&: 该标签用来装配没有重复值的 set 值lt;map&:该标签科以用来注入键值对

lt;props&: 该标签用来支持注入键值对和字符串类型键值对。

1.13. 什么是 Spring bean?

它们是构成用户应用程序主干的对象。

Bean 由 Spring IoC 容器管理。

它们由 Spring IoC 容器实例化,配置,装配和管理。

Bean 是基于用户提供给容器的配置元数据创建。

1.14. 什么是 spring 自动装配?

就是将bean自动注入带另一个bean的属性里去,默认是不开启的,只要把bean放到ioc容器中去在不指定装配方式的情况下会自动注入。他有一定的局限性,就是会被构造注入,属性注入覆盖,一般不会使用自动装配。使用的话常用的有两种情况,byName和ByType一般采用bYnAME

1.15. 自动装配有哪些方式?

1、no - 这是默认设置,表示没有自动装配。应使用显式 bean 引用进行装配。

2、byName - 它根据 bean 的名称注入对象依赖项。它匹配并装配其属性与 XML 文件中由相同名称定义的 bean。

3、byType - 它根据类型注入对象依赖项。如果属性的类型与 XML 文件中的一个 bean 名称匹配,则匹配并装配属性

。4、构造函数 - 它通过调用类的构造函数来注入依赖项。它有大量的参数。

5、autodetect - 首先容器尝试通过构造函数使用 autowire 装配,如果不能,则尝试通过

byType 自动装配。

1.16.自动装配有什么局限?

1、覆盖的可能性 - 您始终可以使用 和 设置指定依赖项,这将覆盖自动装配。

2、基本元数据类型 - 简单属性(如原数据类型,字符串和类)无法自动装配。

3、令人困惑的性质 - 总是喜欢使用明确的装配,因为自动装配不太精确。

1.17. Spring 的重要注解?

@Controller - 用于 Spring MVC 项目中的控制器类。

@Service - 用于服务类。

@RequestMapping - 用于在控制器处理程序方法中配置 URI 映射。

@ResponseBody - 用于发送 Object 作为响应,通常用于发送 XML 或 JSON 数据作为响应。

@PathVariable - 用于将动态值从 URI 映射到处理程序方法参数。

@Autowired - 用于在 spring bean 中自动装配依赖项。

@Qualifier - 使用 @Autowired 注解,以避免在存在多个 bean 类型实例时出现混淆。

@Scope - 用于配置 spring bean 的范围。

@Configuration,@ComponentScan 和 @Bean - 用于基于 java 的配置。

@Aspect,@Before,@After,@Around,@Pointcut - 用于切面编程(AOP)。

1.18. @Component, @Controller, @Repository, @Service 有何区别?

1、 @Component:这将 java 类标记为 bean。它是任何 Spring 管理组件的通用构造型。

spring 的组件扫描机制现在可以将其拾取并将其拉入应用程序环境中。

2、@Controller:这将一个类标记为 Spring Web MVC 控制器。标有它的 Bean 会自动导入到 IoC 容器中。

3、@Service:此注解是组件注解的特化。它不会对 @Component 注解提供任何其他行为。您可以在服务层类中使用 @Service 而不是 @Component,因为它以更好的方式指定了意图。

4、@Repository:这个注解是具有类似用途和功能的 @Component 注解的特化。它为 DAO 提供了额外的好处。它将 DAO 导入 IoC 容器,并使未经检查的异常有资格转换为 Spring DataAccessException。

1.19.列举 spring 支持的事务管理类型?

Spring 支持两种类型的事务管理:

程序化事务管理:在此过程中,在编程的帮助下管理事务。它为您提供极大的灵活性,但维 护起来非常困难。

声明式事务管理:在此,事务管理与业务代码分离。仅使用注解或基于 XML 的配置来管理事务。

1.19. Spring 框架的事物管理有哪些优点?

1、它为不同的事务 API(如 JTA, JDBC, Hibernate, JPA, 和 JDO)提供了统一的编程模型。

2、它为编程式事务管理提供了一个简单的 API 而非一系列复杂的事务 API(如 JTA).

3、它支持声明式事务管理。

4、它可以和 Spring 的多种数据访问技术很好的融合。

1.20. Spring AOP(面向切面)编程的原理?

1、AOP 面向切面编程,它是一种思想。它就是针对业务处理过程中的切面进行提取,以达到优化代码的目的,减少重复代码的目的。 就比如,在编写业务逻辑代码的时候,我们习惯性的都要写:日志记录,事物控制,以及权限控制等,每一个子模块都要写这些代码,代 码明显存在重复。这时候,我们运用面向切面的编程思想,采用横切技术,将代码中重复的 部分,不影响主业务逻辑的部分抽取出来,放在某个地方进行集中式的管理,调用。 形成日志切面,事物控制切面,权限控制切面。 这样,我们就只需要关系业务的逻辑处理,即提高了工作的效率,又使得代码变的简洁优雅。这就是面向切面的编程思想,它是面向对象 编程思想的一种扩展。

2、AOP 的使用场景: 缓存、权限管理、内容传递、错误处理、懒加载、记录跟踪、优化、校准、调试、持久化、资源池、同步管理、事物控制等。 AOP 的相关概念: 切面(Aspect)

连接点(JoinPoint) 通知(Advice) 切入点(Pointcut) 代理(Proxy): 织入(WeaVing) 3、Spring AOP 的编程原理? 代理机制 JDK 的动态代理:只能用于实现了接口的类产生代理。Cglib 代理:针对没有实现接口的类产生代理,应用的是底层的字节码增强技术,生成当前类的子类对象。

1.21. Spring 中@Autowire 与@Resource 的区别?

@Autowire 默认按照类型装配,默认情况下它要求依赖对象必须存在如果允许为 null,可以设置它 required 属性为 false,如果我们想使用按照名称装配,可以结合@Qualifier 注解一起使用;

@Resource 默认按照名称装配,当找不到与名称匹配的 bean 才会按照类型装配,可以通过name 属性指定,如果没有指定 name 属性,当注解标注在字段上,即默认取字段的名称作为 bean 名称寻找依赖对象,当注解标注在属性的 setter 方法上,即默认取属性名作为 bean 名称寻找依赖对象

1.22.什么是控制反转(IOC),什么是依赖注入(DI)?

IOC:就是对象之间的依赖关系由容器来创建,对象之间的关系本来是由我们开发者自己创建和维护的,在我们使用 Spring 框架后,对象之间的关系由容器来创建和维护,将开发者做的事让容器做,这就是控制反转。BeanFactory 接口是 Spring Ioc 容器的核心接口。

DI:我们在使用 Spring 容器的时候,容器通过调用 set 方法或者是构造器来建立对象之间的依赖关系。

控制反转是目标,依赖注入是我们实现控制反转的一种手段。

1.23.Spring 事务传播行为?

JAVA面试总结(初版)_第19张图片

1.24解释一下以下注解

image-20210413115606643

1.25说出10个常见的get方法

JAVA面试总结(初版)_第20张图片

2.SpringMVC

2.1. SpringMVC 和 struts2 的区别有哪些?

核心控制器不同,Strusts2使用的核心控制器是filter,而SpringMVC的核心控制器是一个servlet

拦截器,Struts2有自己的拦截器实现,而springMVC使用了AOP方式

Struts2是类级别的拦截,而springMVC是方法级别的拦截,所以struts2的每个类共享一个request上下文,而springmvc每个方法独享一个request上下文,而方法同时又跟一个URL对应

struts2是每个请求都会实例一个action, 而springMVC是单例模式

2.2.Spring MVC 框架有什么用?

模型-视图-控制器 ,逻辑视图分开 松散耦合

**2.**3.SpringMVC 工作流程?

1、用户发送请求至前端控制器 DispatcherServlet

2、DispatcherServlet 收到请求调用 HandlerMapping 处理器映射器。

3、处理器映射器根据请求 url 找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给 DispatcherServlet。

4、DispatcherServlet 通过 HandlerAdapter 处理器适配器调用处理器

5、执行处理器(Controller,也叫后端控制器)。 6、Controller 执行完成返回 ModelAndView

7、HandlerAdapter 将 controller 执行结果 ModelAndView 返回给 DispatcherServlet 8、DispatcherServlet 将 ModelAndView 传给 ViewReslover 视图解析器

9、ViewReslover 解析后返回具体 View

10、DispatcherServlet 对 View 进行渲染视图(即将模型数据填充至视图中)。

11、DispatcherServlet 响应用户

JAVA面试总结(初版)_第21张图片

3.MyBatis

2.1. hibernate 和 mybatis 的区别?

相同点:

1)都属于 ORM 框架2)都是对 jdbc 的包装3)都属于持久层的框架不同点:

1) hibernate 是面向对象的,mybatis 是面向 sql 的;

2) hibernate 全自动的 orm,mybatis 是半自动的 orm;

  1. hibernate 查询映射实体对象必须全字段查询,mybatis 可以不用;

4) hibernate 级联操作,mybatis 则没有;

5) hibernate 编写 hql 查询数据库大大降低了对象和数据库的耦合性,mybatis 提供动态 sql, 需要手写 sql,与数据库之间的耦合度取决于程序员所写的 sql 的方法,所以 hibernate 的移植性要远大于 mybatis。

6) hibernate 可以夸数据库,mybatis 依赖于具体的数据库。

7) hibernate 拥有完整的日志系统,mybatis 则相对比较欠缺。

2.2.MyBatis 的优点?

1、基于 SQL 语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响, SQL 写在 XML 里,解除 sql 与程序代码的耦合,便于统一管理;提供 XML 标签,支持编写动态 SQL 语句,并可重用。

2、与 JDBC 相比,减少了 50%以上的代码量,消除了 JDBC 大量冗余的代码,不需要手动开关连接;

3、很好的与各种数据库兼容(因为 MyBatis 使用 JDBC 来连接数据库,所以只要 JDBC 支持的数据库 MyBatis 都支持)。

4、能够与 Spring 很好的集成;

5、提供映射标签,支持对象与数据库的 ORM 字段关系映射;提供对象关系映射标签,支持对象关系组件维护。

2.3.MyBatis 框架的缺点?

(1) SQL 语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写 SQL 语句的功底有一定要求。

(2) SQL 语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。

2.4.MyBatis 框架使用的场合?

(1) MyBatis 专注于 SQL 本身,是一个足够灵活的 DAO 层解决方案。

(2) 对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis 将是不错的选择。

2.5.Mybatis 是如何 sql 执行结果封装为目标对象?都有哪些映射形式?

第一种是使用标签,逐一定义数据库列名和对象属性名之间的映射关系。

第二种是使用 sql 列的别名功能,将列的别名书写为对象属性名。

三 设置忽略驼峰

四 直接返回map

有了列名与属性名的映射关系后,Mybatis 通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。

2.6.Mybatis 中#{}和${}的区别是什么?

#{}是预编译处理,${}是字符串替换。

Mybatis 在处理#{}时,会将 sql 中的#{}替换为?号,调用 PreparedStatement 的 set 方法来赋值;

Mybatis 在处理 时 , 就 是 把 {}时,就是把 {}替换成变量的值。使用#{}可以有效的防止 SQL 注入,提高系统安全性。

2.2.MyBatis 的优点?
2.2.MyBatis 的优点?
2.2.MyBatis 的优点?
2.2.MyBatis 的优点?
2.2.MyBatis 的优点?
2.2.MyBatis 的优点?

4.SpringBoot

1.如何重新加载 Spring Boot 上的更改,而无需重新启动服务器?

这可以使用 DEV 工具来实现。通过这种依赖关系,您可以节省任何更改,嵌入式 tomcat 将重新启动。Spring Boot 有一个开发工具(DevTools)模块,它有助于提高开发人员的生产力。Java 开发人员面临的一个主要挑战是将文件更改自动部署到服务器并自动重启服务器。开发人员可以重新加载 Spring Boot 上的更改,而无需重新启动服务器。这将消除每次手动部署更改的需要。Spring Boot 在发布它的第一个版本时没有这个功能。这是开发人员最需要的功

能。DevTools 模块完全满足开发人员的需求。该模块将在生产环境中被禁用。它还提供 H2

数据库控制台以更好地测试应用程序。

2.什么是 Spring Boot?

多年来,随着新功能的增加,spring 变得越来越复杂。只需访问 https://spring.io/projects 页面,我们就会看到可以在我们的应用程序中使用的所有 Spring 项目的不同功能。如果必须启动一个新的 Spring 项目,我们必须添加构建路径或添加 Maven 依赖关系,配置应用程序服务器,添加 spring 配置。因此,开始一个新的 spring 项目需要很多努力,因为我们现在必须从头开始做所有事情。

Spring Boot 是解决这个问题的方法。Spring Boot 已经建立在现有spring 框架之上。使用 spring 启动,我们避免了之前我们必须做的所有样板代码和配置。因此,Spring Boot 可以帮助我们以最少的工作量,更加健壮地使用现有的 Spring 功能。

如果使用spring开发有一个缺点就是每集成一个功能或者模块就必须添加相应的依赖和配置,如果功能多了的或需要每个都添加并配置,是一个很麻烦的事情。而springBoot是在spring的基础上,把一些功能模块的配置工作简化需要的时候只需要直接添加即可,他大大减少了通过spring开发的工作量,是对spring的一个扩展

3.什么是 JavaConfig?

Spring JavaConfig 是 Spring 社区的产品,它提供了配置 Spring IoC 容器的纯 Java 方法。因此它有助于避免使用 XML 配置。使用 JavaConfig 的优点在于:

面向对象的配置。由于配置被定义为 JavaConfig 中的类,因此用户可以充分利用 Java 中的面向对象功能。一个配置类可以继承另一个,重写它的@Bean 方法等。

减少或消除 XML 配置。基于依赖注入原则的外化配置的好处已被证明。但是,许多开发人员不希望在 XML 和 Java 之间来回切换。JavaConfig 为开发人员提供了一种纯 Java 方法来配置与 XML 配置概念相似的 Spring 容器。从技术角度来讲,只使用 JavaConfig 配置类来配置容器是可行的,但实际上很多人认为将 JavaConfig 与 XML 混合匹配是理想的。

类型安全和重构友好。JavaConfig 提供了一种类型安全的方法来配置Spring 容器。由于Java 5.0 对泛型的支持,现在可以按类型而不是按名称检索 bean,不需要任何强制转换或基于字符串的查找。

4.如何重新加载 Spring Boot 上的更改,而无需重新启动服务器?

这可以使用 DEV 工具来实现。通过这种依赖关系,您可以节省任何更改,嵌入式 tomcat 将重新启动。Spring Boot 有一个开发工具(DevTools)模块,它有助于提高开发人员的生产力。Java 开发人员面临的一个主要挑战是将文件更改自动部署到服务器并自动重启服务器。开发人员可以重新加载 Spring Boot 上的更改,而无需重新启动服务器。这将消除每次手动部署更改的需要。Spring Boot 在发布它的第一个版本时没有这个功能。这是开发人员最需要的功

能。DevTools 模块完全满足开发人员的需求。该模块将在生产环境中被禁用。它还提供 H2

数据库控制台以更好地测试应用程序。

5.Spring Boot 中的监视器是什么?

Spring boot actuator 是 spring 启动框架中的重要功能之一。Spring boot 监视器可帮助您访问生产环境中正在运行的应用程序的当前状态。有几个指标必须在生产环境中进行检查和监控。即使一些外部应用程序可能正在使用这些服务来向相关人员触发警报消息。监视器模块公开了一组可直接作为 HTTP URL 访问的 REST 端点来检查状态。

6.如何在 Spring Boot 中禁用 Actuator 端点安全性?

默认情况下,所有敏感的 HTTP 端点都是安全的,只有具有 ACTUATOR 角色的用户才能访问它们。安全性是使用标准的 HttpServletRequest.isUserInRole 方法实施的。 我们可以使用management.security.enabled = false 来禁用安全性。只有在执行机构端点在防火墙后访问时, 才建议禁用安全性。

7.什么是 WebSocket?

WebSocket 是一种计算机通信协议,通过单个 TCP 连接提供全双工通信信道。WebSocket 是双向的 -使用 WebSocket 客户端或服务器可以发起消息发送。WebSocket 是全双工的 -客户端和服务器通信是相互独立的。

单个 TCP 连接 -初始连接使用 HTTP,然后将此连接升级到基于套接字的连接。然后这个单一连接用于所有未来的通信

Light -与 http 相比,WebSocket 消息数据交换要轻得多。

8.什么是 Swagger?你用 Spring Boot 实现了它吗?

Swagger 广泛用于可视化 API,使用 Swagger UI 为前端开发人员提供在线沙箱。Swagger 是用于生成 RESTful Web 服务的可视化表示的工具,规范和完整框架实现。它使文档能够以与服务器相同的速度更新。当通过 Swagger 正确定义时,消费者可以使用最少量的实现逻辑来理解远程服务并与其进行交互。因此,Swagger 消除了调用服务时的猜测。

5.小框架

1.Maven

1.maven的5种作用范围

Compile(默认):都有效

Priveded:编译,测试,运行(部署的包有服务器提供)

Runtime:在测试阶段有效

Test:测试阶段有效

System:编译、测试、运行阶段(部署阶段有系统提供(需要指定路径))

依赖传递:A依赖B B依赖C A可以C的

Complie、Runtime可以依赖传递,其他不能

继承传递:都可以

  1. maven私服仓库类型

一、代理仓库(代理带三方仓库)

Release 存正式的 jar

快照 存测试的jar

3rd part 存第三方的jar 中心仓库没有的

二、宿主仓库(存储本地资源)

三、仓库组(有多个代理和宿主仓库组成)

  1. Maven命令

Mvn clean 清除

Mvn compiler 编译到target

Mvn pakage 打包

Mvn install 打包到本地仓库

Mvn deploy 打包到私服和本地仓库

  1. maven三大坐标

Groupid

Atfacit

Version

  1. Maven的包

Pom(父版本)

Jar 扩展jar包

War 项目

2.Junit

3.Git

https://blog.csdn.net/weixin_44995668/article/details/115194971

4.Docker

  1. Docker原理

    Docker是C/S结构的又分为两部分、一部分是Docker客户端、一部分是Docker守护线程、首先由客户端发出创建容器的请求、查询本地有没有该镜像、如果有则创建容器、如果没有则到远程拉取镜像到本地、或者创建自己的镜像再创建容器

  2. Docker和虚拟机的区别

    虚拟机是操作系统的级别、容器是进程的级别、操作系统占用资源多、容器少、容器是秒级别启动、而操作系统是分钟级别启动。容器集群规模更加大于操作系统的级别可以达到上万而操作系统一般是上百

  3. Docker的网络模式

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z5WnKgat-1618290492920)(F:\pic\1.png)]

    host模式

    如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。

    使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性不好。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N50FFCIa-1618290492922)(F:\pic\2.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gY9xQ6Cr-1618290492925)(F:\pic\image-20210329162126038.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mFr5v4pN-1618290492927)(F:\pic\image-20210329162206028.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pxo7XFD2-1618290492930)(F:\pic\image-20210329162231857.png)]

    4.docker-compose是什么

    docker-compose是容器编排工具

    dockerfile:自定义镜像

    docker-compose:可以通过文件的方式帮我们自动创建管理多个容器

    5.harbor是什么

    harbor是分发和存储docker镜像的私服,可以将镜像上传和下载

    6.云服务的特征是什么

    按使用量计费

    资源共享池

    多租户隔离

    7.docker中容器镜像仓库的概念分别是什么

    镜像相当于一个模板,通过这个模板创建容器
    容器可以理解为一个简易的linux系统,里面可以运行一个或一组应用
    仓库是存放镜像的地方,分为私有仓库和公有仓库

    8.写出10个docker命令

    启动Docker: systemctl start docekr
    寻找镜像: docker search mysql
    创建容器
    docker run --name zoukx-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7

    --name 容器名字:zoykx-mysql
    -p 3306(宿主机):3306(容器)
    -e 参数为root MYSQL_ROOT_PASSWORD=root
    -d 后台运行
    mysql:5.7镜像和版本
    和镜像相关
    查询本地镜像 : docker images
    拉取镜像 : docker pull 镜像名:版本
    删除镜像 : docker rmi -f(强制删除) 镜像ID
    和容器相关
    创建容器 :docker run --name dd --p 3306:3306 -d -e properties=dev -v ././…(数据卷边)
    查看正在运行的容器:docker ps
    docker ps -a 没有开启的 也查询
    docker ps q以ID返回
    docekr ps -aq查询所有并且以ID返回
    删除容器 :docker rm -f(强制删除)
    停止容器: docker stop ID
    删除全部容器:docker rm $(docker ps -aq)
    停止全部容器:docker stop $(docker ps -qa)
    数据卷
    创建数据卷:docker volumn create 名字
    删除数据卷: docker volumn rm 名字
    容器映射数据卷: docker run -v 路径:容器内部路径 容器ID
    Dockerfile创建镜像
    编辑Dockerfile:vi Dockerfile 在jar同一目录下
    创建镜像:Docker build -t movie(镜像名字): 版本 .(不能少)
    Docker-compose
    创建编排yaml:vi docker-compose.yaml (里面需要创建好的镜像)
    编排容器:docker-compose up -d
    卸载容器:docker-compose down
    harbor
    推送镜像: docker push 标记的ID :版本

    9.如何查看镜像支持的环境变量、怎样设置环境变量

    查看环境变量
    docker inspect centos | grep SERVER
    doecker exec env
    设置环境变量
    1)在通过Dockerfile打包镜像的时候可以配置环境变量:
    2)启动设置docker run --env
    3)启动时加载文件docker run --env-file

    10.如何批量清理临时镜像文件

    docker rmi $( docker images -q )

    11.如何停止所有正在运行的容器

    docker kill $(docker ps -q)

    12.如何清理批量后台停止的容器

    docker rm $(docker ps -aq)

    13.可以在一个容器中同时运行多个应用进程吗?

    可以在一个容器中运行组成应用程序的所有进程,但这使得该容器非常难以管理。

    14.Dockerfile中Add与copy的区别是什么

    add 能完成copy的所有事情
    1: add 还能解压
    2:add 还能从url 拷贝文件到镜像

    15.你怎么理解springboot和云服务集成这句话

6.Jenkins

7.插件

1.lombok
2.MyBatis分页插件Plaghper

6.Nginx

1. nginx是什么 特征是什么

是一个高性能HTTP和反向代理服务器,也是一个静态资源服务器

特点:占用内存少,并发能力强

1.反向代理

2.负载均衡

3.动静分离

2.你们公司中用nginx 的使用场景

Http服务器:当只有静态资源的时候可以使用Nginx作为服务器

静态服务器:可以将一些静态资源放到Ngin上,通常提供一个上传的功能

反向代理:通过Nginx处理对外的请求,将请求转发给内部网络的服务器,并将服务器处理的结果传给请求方

简单来说就是真实的服务器不能直接被外部网络访问,所以需要一台代理服务器,而代理服务器能被外部网络访问的同时又跟真实服务器在同一个网络环境,当然也可能是同一台服务器,端口不同而已。

负载均衡:负载均衡就是将请求分发到多态服务器上面去

Nginx自带三种负载均衡策略:

​ 1.**轮询(**默认)按时间顺序逐一分配到不同的后端服务器,也就是说第一次请求分配到第一台服务器上,第二次请求分配到第二台服务器上,如果只有两台服务器,第三次请求继续分配到第一台上

​ 2.权重

JAVA面试总结(初版)_第22张图片

​ 3.IP哈希:解决一个IP如果第一次到一台服务器保存了session,第二次到另外一台没有了session要重新登录(上面不能解决)

上面的2种方式都有一个问题,那就是下一个请求来的时候请求可能分发到另外一个服务器,当我们的程序不是无状态的时候(采用了session保存数据),这时候就有一个很大的很问题了,比如把登录信息保存到了session中,那么跳转到另外一台服务器的时候就需要重新登录了,所以很多时候我们需要一个客户只访问一个服务器,那么就需要用iphash了,iphash的每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。

  1. fair(第三方)

JAVA面试总结(初版)_第23张图片

JAVA面试总结(初版)_第24张图片

3.什么是正向代理 什么是反向代理

正向代理代理的是客户端

JAVA面试总结(初版)_第25张图片

反向代理代理的是服务端

JAVA面试总结(初版)_第26张图片

4.nginx做为企业应用的入口如果nginx 挂了怎么办 【换句话说:怎样保证nginx的高可用】

因为nginx是我们所有项目的入口,必须要保证nginx的高可用,这里一般都用的nginx集群,并同时加入了keepalive来做的双机热备处理,通过请求一个vip(virtual ip:虚拟ip)来达到请求真实IP地址的功能,而VIP能够在一台机器发生故障时候,自动漂移到另外一台机器上,从来达到了高可用的功能

高可用故障切换转移原理
Keepalived高可用故障切换,是通过VRRP虚拟路由器冗余协议来实现的。

在Keepalived服务正常工作时,主Master节点会不断地向备节点发送(多播的方式)心跳消息,用以告诉备Backup节点自己还活着,当主Master节点发生故障时,就无法发送心跳消息,备节点无法检测到来自主Master节点心跳了,于是调用自身的接管程序,接管主Master节点的IP资源及服务。而当主Master节点恢复时,备Backup节点又会释放主节点故障时自身接管的IP资源及服务,恢复到原来的备用角色。

5.nginx的 负载均衡算法或者说【负载均衡的方式】有 哪些

轮询

权重

IP哈希

6.分布式 集群 环境下 怎么实现session 中的状态共享

JAVA面试总结(初版)_第27张图片

**解决方式一: **session复制

(1)session复制

tomcat的session复制,可以实现session共享

优点:不需要额外开发,只需搭建tomcat集群即可

缺点:tomcat 是全局session复制,集群内每个tomcat的session完全同步(也就是任何时候都完全一样的) 在大规模应用的时候,用户过多,集群内tomcat数量过多,session的全局复制会导致集群性能下降, 因此,tomcat的数量不能太多,5个以下为好。
**解决方式二: **session绑定

当用户A第一次访问系统时,tomcat1对其进行服务,那么,下次访问时仍然让tomcat1对其进行服务

**解决方式三: **session存在redis

可以将用户的会话保存在redis中,每次从redis中查询用户信息,就可以很好的解决会话共享问题。如图:

JAVA面试总结(初版)_第28张图片

四、实际应用

(1)用户登录问题

对于大型分布式系统,可以使用单点登录系统进行登录,其中用户的session保存在redis缓存系统中

(2)用户短信验证

当需要对用户短信进行校验前,调取第三方服务获取验证码,需要先将验证码保存在session中,然后与用户提交的验证码进行比对

7.Nginx的进程模型

采用一个master进程和多个worker进程的工作模式
1、master进程主要负责收集、分发请求。当一个请求过来时,master拉起一个worker进程负责处理这个请求
2、master进程也要负责监控worker的状态,保证高可靠性
3、worker进程议案设置为和CPU核心数一致或者其二倍。Nginx的worker进程和Apache的不一样。Apache的进程在同一时间只能处理一个请求,所以它会开启很多个进程,几百甚至几千个。而Nginx的worker进程在同一时间可以处理的请求数只受内存限制,因此可以处理更多请求

8.Nginx是如何实现高并发的?

Nginx之所以可以实现高并发,与它采用的epoll模型有很大的关系。epoll模型采用异步非阻塞的事件处理机制。这种机制让Nginx进程同时监控多个事件
简单地说,就是异步非阻塞,使用了epoll模型和大量的底层代码优化

7.RabbitMQ

1.什么是MQ MQ的优缺点是什么

Message Queue 消息队列(消息中间件)
通过利用可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成
优点解耦:需要消息的系统自己从消息队列中订阅,从而在不修改系统的情况下实现更多的功能
异步:将消息写入消息队列,非必要的业务逻辑以异步的方式运行,加快响应速度
削峰:使用时慢慢从队列中拉取消息,从而减少前置服务高并发导致后置服务也高并发
缺点:可用性降低:因为增加了消息中间件导致中间件出现问题的时候会出现服务不可用,稳定性下降
系统更复杂:比如一致性问题、如何保证消息不被重复消费,如何保证消息可靠传输

2.项目中哪些地方用到mq 请分别说明场景

支付

转账 发短信

作为第三方消息让两个地方进行通讯

在不同系统通过MQ一部调用

3.市面上常见mq 产品的比较

JAVA面试总结(初版)_第29张图片

JAVA面试总结(初版)_第30张图片

4. javaee 是什么 他的13个开发规范分别是什么

JAVAEE平台由一整套服务(Services)、应用程序接口(APIs)和协议构成,它对开发基于Web的多层应用提供了功能支持,下面对JAVAEE中的13种技术规范进行简单的描述。

1、JDBC(Java Database Connectivity)

JDBC API为访问不同的数据库提供了一种统一的途径,像ODBC一样,JDBC对开发者屏蔽了一些细节问题,另外,JDCB对数据库的访问也具有平台无关性。

2、JNDI(Java Naming and Directory Interface,Java命名和目录接口)

JNDI 是SUN公司提供的一种标准的Java命名系统接口,JNDI提供统一的客户端API,通过不同的访问提供者接口JNDI服务供应接口(SPI)的实现,由管理者将JNDI API映射为特定的命名服务和目录系统,使得Java应用程序可以和这些命名服务和目录服务之间进行交互。

在没有JNDI之前:

开发的时候,在连接数据库代码中需要对JDBC驱动程序类进行应用,通过一个URL连接到数据库。但是这样存在问题,比如我要改一种数据库,是不是要更换驱动,更换URL。每次都要进行这些配置和管理。

在有了JNDI之后:

可以在J2ee容器中配置JNDI参数,定义一个数据源,在程序中,通过数据源名称引用数据源从而访问后台数据库。在程序中定义一个上下文类,然后用content.lookup("就可以成功引入数据源了。

在DataSource中事先建立多个数据库连接,保存在数据库连接池中,当程序访问数据库时,只用从连接池中取空闲状态的数据库连接即可,访问结束,销毁资源,数据库链接重新回到连接池

例如:数据源定义

3、EJB(Enterprise

EJB是sun的JavaEE服务器端组件模型,设计目标与核心应用是部署分布式应用程序。用通俗的话来理解,就是把已经打包好的东西放到服务器中去执行,这样是凭借了java跨平台的优势,利用EJB技术部署分布式系统可以不限于特定的平台。包括四种对象类型:无状态会话bean(提供独立服务),有状态会话bean(提供会话交互),实体bean(持久性数据在内存中的体现,服务器崩溃后可恢复),消息驱动bean。

EJB定义了服务器端组件是如何被编写以及提供了在组件和管理它们的服务器和组件间的标准架构协议.

4、RMI(Remote Method Invocation,远程方法调用)

RMI是Java的一组拥护开发分布式应用程序的API。RMI使用Java语言接口定义了远程对象,它集合了Java序列化和Java远程方法协议(。是一种被EJB使用的更底层的协议。

可以理解为,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法。可以用此这个方法调用的任何对象必须实现该远程接口。

5、Java IDL/CORBA

Java IDL技术在Java平台上添加了CORBA(Common Object Request Broker Architecture)功能,提供了基于标准的操作能力和连接性。Java IDL技术使得分布式的Java Web应用能够通过使用工业标准的IDL和IIOP(Internet Inter-ORB Protocol)来透明地调用远程网络服务的操作。运行时组件(Runtime Components)包括了一个用于分布式计算且使用IIOP通信的Java ORB.我对这个规范的理解,它也是借用了java的集成,让新旧系统集成,或是客户端跨平台的使用。

6、JSP全名为Java Server Pages

中文名叫java服务器页面,其根本是一个简化的Servlet设计,它是由Sun Microsystems公司倡导、许多公司参与一起建立的一种动态网页技术标准。JSP的定义让我想到做BS项目时候的ASP.NET技术。JSP页面也是用HTML和JS的交互,服务器在页面被客户端所请求以后对这些Java代码进行处理,然后将生成的HTML页面返回给客户端的浏览器。

7、Java Servlet

一种J2EE组件,servlet可被认为是运行在服务器端的applet,Servlets提供了基于组件、平台无关的方法用以构建基本Web的应用程序。Servlet必须部署在Java servlet容器才能使用,为了在web容器里注册上面的Servlet,为应用建一个web.xml入口文件。servlets全部由Java写成并且生成HTML。

8、XML(Extensible Markup Language)

XML可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。近年来,随着 Web的应用越来越广泛和深入,人们渐渐觉得HTML不够用了,HTML过于简单的语法严重地阻碍了用它来表现复杂的形式。尽管HTML推出了一个又一个新版本,已经有了脚本、表格、帧等表达功能,但始终满足不了不断增长的需求。

有人建议直接使用SGML 作为Web语言,这固然能解决HTML遇到的困难。但是SGML太庞大了,用户学习和使用不方便尚且不说,要全面实现SGML的浏览器就非常困难,于是自然会想到仅使用SGML的子集,使新的语言既方便使用又实现容易。正是在这种形势下,Web标准化组织W3C建议使用一种精简的SGML版本——XML应运而生了。 XML的发展和Java是相互独立的,但是,它和Java具有的相同目标正是平台独立性。通过将Java和XML的组合,您可以得到一个完美的具有平台独立性的解决方案。

9、JMS即Java消息服务(Java Message Service)

JMS应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。用一个很形象的例子,如果有人请我吃饭,她给我打电话占线,她决定先去占个位置,但是如果没有短信技术,那么是不是我就不知道她给我的消息了呢?为了保证这样的异步通信,我可以看到短信,准时去赴约。JMS就是提供了这样一个面向消息的中间件。它们提供了基于存储和转发的应用程序之间的异步数据发送,即应用程序彼此不直接通信,而是与作为中介的MOM 通信。MOM提供了有保证的消息发送,应用程序开发人员无需了解远程过程调用(PRC)和网络/通信协议的细节。

10、JTA,即Java Transaction API

JTA允许应用程序执行分布式事务处理——在两个或多个网络计算机资源上访问并且更新数据。JDBC驱动程序的JTA支持极大地增强了数据访问能力。利用了事务处理,可以让数据等到同步的更新,技术上可以支持多个服务器的分布式访问。

11、JTS(Java Transaction Service)

JTS是CORBA OTS事务监控的基本的实现。JTS规定了事务管理器的实现方式。该事务管理器是在高层支持Java Transaction API (JTA)规范,并且在较底层实现OMG OTS specification的Java映像。JTS事务管理器为应用服务器、资源管理器、独立的应用以及通信资源管理器提供了事务服务。

12、JavaMail

JavaMail API提供了一种独立于平台和独立于协议的框架来构建邮件和消息传递应用程序。不仅支持SMTP服务器,也支持IMAP服务器。是一个提供给使用Java平台的开发者处理电子邮件有关的编程接口。

13、JAF(JavaBeans Activation Framework)

JavaMail利用JAF来处理MIME编码的邮件附件。MIME的字节流可以被转换成Java对象,或者转换自Java对象。大多数应用都可以不需要直接使用JAF

5. amqp 和 jms的比较

JMS(java message service)

由Sun公司早期提出的消息标准,是一个Java平台中关于面向消息中间件(MOM)的API,旨在为java应用提供统一的消息操作。

AMQP(advanced message queuing protocol)

在2003年时被提出,最早用于解决金融领不同平台之间的消息传递交互问题。顾名思义,AMQP是一种协议,更准确的说是一种binary wire-level protocol(链接协议)。这是其和JMS的本质差别,AMQP不从API层进行限定,而是直接定义网络交换的数据格式。这使得实现了AMQP的provider天然性就是跨平台的。意味着我们可以使用Java的AMQP provider,同时使用一个python的producer加一个rubby的consumer。从这一点看,AQMP可以用http来进行类比,不关心实现的语言,只要大家都按照相应的数据格式去发送报文请求,不同语言的client均可以和不同语言的server链接。

amqp和jms的具体局别

1、通信平台的区别
JMS: 只允许基于JAVA实现的消息平台的之间进行通信
AMQP: 允许多种消息协议进行通信,比如ruby的storm和java的jms都可以在AMQP上进行通信。
结论: AMQP允许多种技术同时进行协议通信

2、通信机制的区别
JMS:消息生产者和消息消费者必须知道对方的Queue
AMQP: 消息生产者和消息消费者无须知道对方的Queue,消息生产者将Exchange通过Route key和任意Queue绑定。消息消费者通过Route key从任意Queue中获取Exchange.

3、消息传输机制的区别
JMS:支持点对点(point-to-point,简称PTP)、发布/订阅(publish/subscribe,简称pub/sub)
AMQP:根据headers匹配,根据路由键匹配、一个exchange绑定多个queue,多个exchange绑定到一个queue

4、其他区别:消息体的区别

6. rabbitmq 中的5种工作模式是什么

简单队列模式:

JAVA面试总结(初版)_第31张图片

work模式:
一个生产者对应多个消费者,但是只能有一个消费者获得消息,也称之为竞争消费者模式。

JAVA面试总结(初版)_第32张图片

发布/订阅模式(广播模式):
一个消费者将消息首先发送到交换器,交换器绑定多个队列,然后被监听该队列的消费者所接收并消费。

JAVA面试总结(初版)_第33张图片

路由模式:
生产者将消息发送到direct交换器,在绑定队列和交换器的时候有一个路由key,生产者发送的消息会指定一个路由key,那么消息只会发送到相应key相同的对列,接着监听该队列的消费者消费消息。

JAVA面试总结(初版)_第34张图片

主题模式:
上面的路由模式是根据路由key进行完整匹配(完全相等才发送消息),这里的通配符模式通俗的来讲就是模糊匹配。
符号"#" 表示匹配0个或者多个单词,符号"*"表示匹配一个词。

JAVA面试总结(初版)_第35张图片

7.mq的消息堆积了该怎么办

1.首先查看为什么消费慢

可以分析网络、SQL、JVM、缓存等方面

2.添加消费者一起消费

RabbitMQ支持多消费者绑定同一队列,消息Broker会把消息轮询的发送给每一个消费者。通过同一个队列多消费者监听,实现消息的争抢,加快消息消费速度。

RabbitMQ也可以做集群,集群数据会分片效果,从而能堆积更多消息。

8.如何保证消息的可靠性

发送的时候不丢 发送到交换机不丢 发送到队列不丢

保证消息的可靠性可以从三个方面来实现

1.保证消费者向MQ服务器发送的消息可靠性和交换机发给队列的消息可靠性

在消息发送者添加消息确认机制和消息返回机制

JAVA面试总结(初版)_第36张图片

在发送消息的时候创建消息属性对象并且添加重新发送时候的交换机和路由

JAVA面试总结(初版)_第37张图片

创建消息回调配置类

当消息发送交换机和队列失败则会触发配置中的相应confirm方法和returnedMessage方法进行重试

如果重试多次(一般三次)还是未成功则,将其记录到日志进行人工干预(补偿)

JAVA面试总结(初版)_第38张图片

2.保证消息在交换机和队列中不丢失(持久化)

交换机持久化

return new DirectExchange("direct_jiaohuanji",true,false,null); 第二个参数为true

队列持久化

return new Queue("direct_que1",true,false,false,null);第二个参数为true

消息持久化

messageProperties.setDeliveryMode(MessageDeliveryMode.PERSISTENT);  // 默认

3.确保消息消费成功

在消费者项目中添加手动应答机制和重试机制

spring:
 application:
   name: springboot_rabbitmq44
 rabbitmq:
   host: 192.168.52.133
   port: 5672
   username: guest
   password: guest
   virtual-host: myvirtualhosts
   listener:
     simple:
       acknowledge-mode: manual    # 手动应答
       default-requeue-rejected: false # 不直接丢到死信队列
       retry:   # 重试策略
         enabled: true  # 允许重试
         initial-interval: 3000ms   # 第一次重试的间隔时间
         max-attempts: 3  # 最大重试次数[加上原来那一次]
         max-interval: 20000ms  # 最大间隔时间
         multiplier: 2   # 重试因子   3    6      12    20

3.1如果消费没有问题则直接应答

channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);

3.2如果消费有问题则直接拒绝

catch (Exception e) {
      
//            如果程序异常直接拒绝
           channel.basicReject(message.getMessageProperties().getDeliveryTag(),false);
       } finally {
      
       }

3.3如果返回出现异常则去重试

重试三次之后

方案1 失败之后 记录到日志 让以后人工对账等 然后拒绝

方案2失败之后 发送到死信交换机中去,死信交换机发送到补偿队列

​ 建立补偿系统 监控补偿队列 是生成相对应的报表 方便人工补偿

4.如何防止消息重复消费(消息幂等)

用Redis的setNX加锁 为消息的ID设置一个状态,并且加个时间(防止消息死在里面)

如果消息消费成功则改变状态,当重试的消息再到消费者这里来的时候,如果能进入则证明没有消费成功

如果不能进入再次判断状态,如果状态改变了则证明消费成功了然后就可以应答

@RabbitListener(queues = "cs2004_direct_q1")
public void ttt(String msg, Channel channel, Message message) throws IOException {
      

   String messageId = message.getMessageProperties().getMessageId();
   
   if(redisTemplate.opsForValue().setIfAbsent(messageId,"0",10, TimeUnit.SECONDS)){
      
       try {
      
           System.out.println("对列1:" + msg);
           // 不给mq 服务器一个应答
           // 如果正常销毁掉 要给应答
           // int i = 1/0;
           redisTemplate.opsForValue().set(messageId,"1",10,TimeUnit.SECONDS);
           channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
       } catch (IOException e) {
      
           // 重试3次之后 拒绝 消息去死信交换机
           // 日志 记账  人工小姐姐对账
           channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
       } catch(Exception ex){
      
           channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
       }
   }else{
      
       if("1".equals(redisTemplate.opsForValue().get(messageId))){
      
           channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
       }
   }
   
}

9.如何防止MQ消息的重复消费?

https://blog.csdn.net/weixin_51291483/article/details/109230657?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522161786360216780265484579%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=161786360216780265484579&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_v2~rank_v29-4-109230657.pc_search_result_no_baidu_js&utm_term=.%E9%A1%B9%E7%9B%AE%E4%B8%AD%E5%93%AA%E4%BA%9B%E5%9C%B0%E6%96%B9%E7%94%A8%E5%88%B0mq++

8.分布式

JAVA面试总结(初版)_第39张图片

1.分布式基础

1.1系统之间的调用问题 mq、rpc、和http区别

mq:是异步调用

rpc和http是同步调用

SpringCloud框架底层走的是http协议传输的是json格式数据

dubbo:底层走的是dubbo协议是rpc框架的产物 通过二进制传输性能强,但是缺点是只能在java之间的服务传递数据

JAVA面试总结(初版)_第40张图片

1.2服务治理的问题

nacos

1.3、分布式事务怎样产生的?

什么是分布式事务:将一次大的操作分为很多小的操作,这些小的操作位于各自的服务器上,分布式事物需要保证这些小的操作要么全部成功,要么全部失败。

产生:对各个服务之间进行访问,需要保证全部成功

1.4、怎样使用rabbitMQ解决弱一致性的分布式问题

保证消息可靠性即可(发送到交换机、持久、消费可靠)

强一致性:系统中的某个数据被成功更新后,后续任何对该数据的读取操作都将得到更新后的值;

弱一致性:系统中的某个数据被更新后,后续对该数据的读取操作可能得到更新后的值,也可能是更改前的值。但经过“不一致时间窗口”这段时间后,后续对该数据的读取都是更新后的值;

最终一致性:是弱一致性的特殊形式,存储系统保证在没有新的更新的条件下,最终所有的访问都是最后更新的值

1.5、dubbo和springCloud的区别

dubbo是阿里巴巴微服务的核心框架

SpringCloud是Spring公司开源的微服务框架

生态环境:SpringCloud是依托于Spring平台具有强大的生态体系,dubbo注重于RPC远程调用和服务组成服务监控、生态比较匮乏

调用方式:虽然都是同步调用 但是springcloud基于http调用、是restFull风格传输的是json格式。dubbo基于rpc以二进制传输性能较好但是只在JAVA服务之间进行传输

JAVA面试总结(初版)_第41张图片

dubbo和Feign远程调用的差异

Dubbo采用自定义的Dubbo协议实现远程通信,是一种典型的RPC调用方案,而SpringCloud中使用的Feign是基于RestFul风格的调用方式。

1.6、什么是横向切分、什么是纵向切分

横向:一个银行有多个取款机干一样的活

纵向:一个银行有取款机和机器人做不同的事

1.7、什么是SpringCloud、SpringCloud和SpringBoot的关系是什么

1.Spring Cloud就是微服务系统架构的一站式解决方案,是各个微服务架构落地技术的集合体,俗称微服务全家桶
2.在平时我们构建微服务的过程中需要做如服务发现注册、配置中心、负载均衡、断路器、数据监控等操作,
而Spring Cloud 为我们提供了一套简易的编程模型,使我们能在 Spring Boot 的基础上轻松地实现微服务项目的构建

SpringBoot专注于快速、方便的开发单个微服务个体,SpringCloud关注全局的服务治理框架。

//区别:SpringBoot可以离开SpringCloud独立使用开发项目,但是SpringCloud离不开SpringBoot,属于依赖的关系.

1.8、springcloud的优势是什么?

优点:

1、服务拆分粒度更细,有利于资源重复利用,有利于提高开发效率

2、可以更精准的制定优化服务方案,提高系统的可维护性

3、微服务架构采用去中心化思想,服务之间采用Restful等轻量级通讯,比ESB更轻量

4、适于互联网时代,产品迭代周期更短

缺点:

1、微服务过多,治理成本高,不利于维护系统

2、分布式系统开发的成本高(容错,分布式事务等)对团队挑战大

1.9、什么叫做cap定律

C:一致性

C:Consistency

即一致性,访问所有的节点得到的数据应该是一样的。注意,这里的一致性指的是强一致性,也就是数据更新完,访问任何节点看到的数据完全一致,要和弱一致性,最终一致性区分开来。

A:可用性

A:Availability

即可用性,所有的节点都保持高可用性。注意,这里的高可用还包括不能出现延迟,比如如果节点B由于等待数据同步而阻塞请求,那么节点B就不满足高可用性。

也就是说,任何没有发生故障的服务必须在有限的时间内返回合理的结果集。

P:分区容错性

P:Partiton tolerance

即分区容忍性,这里的分区是指网络意义上的分区。由于网络是不可靠的,所有节点之间很可能出现无法通讯的情况,在节点不能通信时,要保证系统可以继续正常服务。

一般p一定需要保证:C和A选择一个

1.10、你们公司里面使用的springboot springcloud springcloudalibaba 的版本是什么

JAVA面试总结(初版)_第42张图片

1.11、什么叫做服务治理、用什么组件实现服务治理

服务治理是主要针对分布式服务框架的微服务,处理服务调用之间的关系、服务发布和发现、故障监控与处理,服务的参数配置、服务降级和熔断、服务使用率监控等。

对于微服务的治理而言,核心就是服务的注册和发现。所以选择哪个组件,很大程度上要看它对于服务注册与发现的解决方案。在这个领域,开源架构很多,最常见的是Zookeeper,但这并不是一个最佳选择。还可以使用nacos、eureke

1.12、zookeeper和eureka作为注册中心的区别

zookeeper保证CP有主节点的,如果主节点挂掉了的话所有服务都不可用,需要选举,在选举的过程中整个服务都是不可用的

eureke保证AP

nasoc先保证AP后保证cp用新的算法让类似zookeeper的选主的过程非常快

JAVA面试总结(初版)_第43张图片

1.13、zookeeper和eureka和nacos作为注册中心的区别

1)springcloud eureka是注册中心,负责微服务的注册与发现,起到承上启下的作用,在微服务架构中相当于人体的 大脑,很重要,nacos是阿里巴巴出的,功能类似eureka,区别不再啰嗦了。

(2)nacos的部署方式与springcloud eureka不太一样,euraka是需要创建springboot项目,然后将euraka服务端通过gav的方式加载进来,然后部署项目。

(3)nacos是直接从阿里巴巴nacos的官网下载jar包,启动服务。

优点:
1)开箱即用,适用于dubbo,spring cloud等

2)AP模型,数据最终一致性

3)注册中心,配置中心二合一(二合一也不一定是优点),提供控制台管理

4)纯国产,各种有中文文档,久经双十一考验

缺点:
1)刚刚开源不久,社区热度不够,依然存在bug

Spring Cloud Eureka:
优点:
1)Spring Cloud 官方推荐

2)AP模型,数据最终一致性

3)开箱即用,具有控制台管理

缺点:
1)客户端注册服务上报所有信息,节点多的情况下,网络,服务端压力过大,且浪费内存

2)客户端更新服务信息通过简单的轮询机制,当服务数量巨大时,服务器压力过大。

3)集群伸缩性不强,服务端集群通过广播式的复制,增加服务器压力

4)Eureka2.0 闭源(Spring Cloud最新版本还是使用的1.X版本的Eureka)

2.SpringCloud

2.1、什么是springCloud

1.Spring Cloud就是微服务系统架构的一站式解决方案,是各个微服务架构落地技术的集合体,俗称微服务全家桶

2.2、什么是SpringCloud、SpringCloud和SpringBoot的关系是什么

1.Spring Cloud就是微服务系统架构的一站式解决方案,是各个微服务架构落地技术的集合体,俗称微服务全家桶
2.在平时我们构建微服务的过程中需要做如服务发现注册、配置中心、负载均衡、断路器、数据监控等操作,
而Spring Cloud 为我们提供了一套简易的编程模型,使我们能在 Spring Boot 的基础上轻松地实现微服务项目的构建

SpringBoot专注于快速、方便的开发单个微服务个体,SpringCloud关注全局的服务治理框架。

//区别:SpringBoot可以离开SpringCloud独立使用开发项目,但是SpringCloud离不开SpringBoot,属于依赖的关系.

2.3、springcloud的优势是什么?

优点:

1、服务拆分粒度更细,有利于资源重复利用,有利于提高开发效率

2、可以更精准的制定优化服务方案,提高系统的可维护性

3、微服务架构采用去中心化思想,服务之间采用Restful等轻量级通讯,比ESB更轻量

4、适于互联网时代,产品迭代周期更短

缺点:

1、微服务过多,治理成本高,不利于维护系统

2、分布式系统开发的成本高(容错,分布式事务等)对团队挑战大


使用 Spring Boot 开发分布式微服务时,我们面临以下问题

1、与分布式系统相关的复杂性-这种开销包括网络问题,延迟开销,带宽问题,安全问题。

2、服务发现-服务发现工具管理群集中的流程和服务如何查找和互相交谈。它涉及一个服务目录,在该目录中注册服务,然后能够查找并连接到该目录中的服务。

3、冗余-分布式系统中的冗余问题。

4、负载平衡 --负载平衡改善跨多个计算资源的工作负荷,诸如计算机,计算机集群,网络链路,中央处理单元,或磁盘驱动器的分布。

5、性能-问题 由于各种运营开销导致的性能问题。

6、部署复杂性-Devops 技能的要求。

2.4、你们公司里面使用的springboot springcloud springcloudalibaba 的版本是什么

JAVA面试总结(初版)_第44张图片

2.5、服务注册和发现是什么意思?Spring Cloud 如何实现?

当我们开始一个项目时,我们通常在属性文件中进行所有的配置。随着越来越多的服务开发和部署,添加和修改这些属性变得更加复杂。有些服务可能会下降,而某些位置可能会发生变化。手动更改属性可能会产生问题。 Eureka 服务注册和发现可以在这种情况下提供帮助。由于所有服务都在 Eureka 服务器上注册并通过调用 Eureka 服务器完成查找,因此无需处理服务地点的任何更改和处理。

常见的服务注册组件

nacos

zookpeeper

eureka

3.Ribbon

3.1.什么是ribbon,ribbon 内置的负载均衡规则有哪些

JAVA面试总结(初版)_第45张图片

ribbon 不属于 alibaba 也不属于netflex

JAVA面试总结(初版)_第46张图片

3.2.说出ribbon 配置中 以下配置的意思?

image-20210412204715988

3.3.使用Ribbon调用远程服务的接口,怎样防止接口被重复消费
3.4.使用feign 或者 ribbon 远程调用服务的时候 会有些什么异常 怎么处理的

如果所有的重试完成 还是失败 要抛出 feign.RetryableException 异常

4.Feign

1.什么是feign 起什么作用

image-20210412205450303

2.说出@SpringQueryMap 注解的作用

@SpringQuertMap是在使用Feign调用其他服务的时候、如果传输的是对象且,使用的是get方法则参数需要加上
@SpringQuertMap

如果传对象使用的是get方式则被调用的服务方和使用feign的调用方都需要加上@RquestBody

3.为什么使用feign

FEIGN 集成ribbon 和 resttemplate

简化 服务之间的调用

4.feign异常处理

JAVA面试总结(初版)_第47张图片

5.feign参数的传递

JAVA面试总结(初版)_第48张图片

6.负载平衡的意义是什么

JAVA面试总结(初版)_第49张图片

5.nacos

1.什么是nacos

JAVA面试总结(初版)_第50张图片

2.注册中心挂了 ,我们还能调用远程服务吗

本地如果有注册列表信息的话__还能访问远程服务_

6.setinel

1.什么是setinel

Sentinel (分布式系统的流量防卫兵) 是阿里开源的一套用于服务容错的综合性解决方案。

它以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来保护服务的稳定性。

2.setinel的组成

核心库(Java 客户端):不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo /Spring Cloud 等框架也有较好的支持。

控制台(Dashboard):基于 Spring Boot 开发,打包后可以直接运行,用来配置容错方案 【运维人员】

3.什么叫服务雪崩

在微服务架构中、各个服务都可能有联系,调用等关系

服务雪崩就是一个或者几个服务出现问题,然后被别人调用导致其他服务也用不了,一个接一个大面积瘫痪

4.常见的容错策略有哪些

隔离

限流

熔断降级

超时

缓存预热

横向扩展

5.什么叫做QPS RT

QPS:每秒请求的次数

RT:处理请求的平均时间

6.SpringCloud中的hystrix的熔断和降级的区别及作用

熔断:不可用走备用

sentinel只有降级,而hystrix有降级和熔断

熔断(断开上层服务,保护下层服务):当某服务出现不可用或响应超时,为防止服务雪崩,暂时停止对该服务的调用
降级:将不重要或不紧急的服务 延迟或暂停这种现象叫做服务降级
从整个系统的负荷情况出发和考虑的,对某些负荷会比较高的情况,为了预防某些功能(业务场景)出现负荷过载或者响应慢的情况,在其内部暂时舍弃对一些非核心的接口和数据的请求,而直接返回一个提前准备好的fallback(退路)错误处理信息。这样,虽然提供的是一个有损的服务,但却保证了整个系统的稳定性和可用性。
区别:触发原因不同 服务熔断一般是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑;

7.setinel中抛出的容错相关的异常,怎么处理

可以做一个类作为bean来处理抛出的异常,但是需要实现UrlBlockHandler接口,注意:不能用正常的controllerAdvice来处理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8K7MnDeP-1618290493064)(https://gitee.com/qc1085951619/image/raw/master/img/image-20210413090143120.png)]

8.hystrix中 断路器的3个状态是什么

熔断关闭

熔断半开

熔断全开

9.hystrix与sentinel的区别

1. hystrix具有的功能

  • 线程池隔离/信号量隔离 Sentinel 不支持线程池隔离;信号量隔离对应 Sentinel 中的线程数限流。

  • 熔断器 Sentinel 支持按平均响应时间、异常比率、异常数来进行熔断降级。

  • Command 创建 直接使用 Sentinel SphU API 定义资源即可,资源定义与规则配置分离。

  • 规则配置 在 Sentinel 中可通过 API 硬编码配置规则,也支持多种动态规则源

  • 注解支持 Sentinel 也提供注解支持

  • 开源框架支持 Sentinel 提供 Servlet、Dubbo、Spring Cloud、gRPC 的适配模块,开箱即用;若之前使用 Spring Cloud Netflix,可迁移至 Spring Cloud Alibaba

JAVA面试总结(初版)_第51张图片

10.服务器性能指标解释:QPS、TPS、RT、Load、PV、UV

https://blog.csdn.net/qq_39416311/article/details/84892625

7.getWay(网关)

作用 路由 过滤 同样产品:网飞的zuul

1.

1618290493018)]

1.13、zookeeper和eureka和nacos作为注册中心的区别

1)springcloud eureka是注册中心,负责微服务的注册与发现,起到承上启下的作用,在微服务架构中相当于人体的 大脑,很重要,nacos是阿里巴巴出的,功能类似eureka,区别不再啰嗦了。

(2)nacos的部署方式与springcloud eureka不太一样,euraka是需要创建springboot项目,然后将euraka服务端通过gav的方式加载进来,然后部署项目。

(3)nacos是直接从阿里巴巴nacos的官网下载jar包,启动服务。

优点:
1)开箱即用,适用于dubbo,spring cloud等

2)AP模型,数据最终一致性

3)注册中心,配置中心二合一(二合一也不一定是优点),提供控制台管理

4)纯国产,各种有中文文档,久经双十一考验

缺点:
1)刚刚开源不久,社区热度不够,依然存在bug

Spring Cloud Eureka:
优点:
1)Spring Cloud 官方推荐

2)AP模型,数据最终一致性

3)开箱即用,具有控制台管理

缺点:
1)客户端注册服务上报所有信息,节点多的情况下,网络,服务端压力过大,且浪费内存

2)客户端更新服务信息通过简单的轮询机制,当服务数量巨大时,服务器压力过大。

3)集群伸缩性不强,服务端集群通过广播式的复制,增加服务器压力

4)Eureka2.0 闭源(Spring Cloud最新版本还是使用的1.X版本的Eureka)

2.SpringCloud

2.1、什么是springCloud

1.Spring Cloud就是微服务系统架构的一站式解决方案,是各个微服务架构落地技术的集合体,俗称微服务全家桶

2.2、什么是SpringCloud、SpringCloud和SpringBoot的关系是什么

1.Spring Cloud就是微服务系统架构的一站式解决方案,是各个微服务架构落地技术的集合体,俗称微服务全家桶
2.在平时我们构建微服务的过程中需要做如服务发现注册、配置中心、负载均衡、断路器、数据监控等操作,
而Spring Cloud 为我们提供了一套简易的编程模型,使我们能在 Spring Boot 的基础上轻松地实现微服务项目的构建

SpringBoot专注于快速、方便的开发单个微服务个体,SpringCloud关注全局的服务治理框架。

//区别:SpringBoot可以离开SpringCloud独立使用开发项目,但是SpringCloud离不开SpringBoot,属于依赖的关系.

2.3、springcloud的优势是什么?

优点:

1、服务拆分粒度更细,有利于资源重复利用,有利于提高开发效率

2、可以更精准的制定优化服务方案,提高系统的可维护性

3、微服务架构采用去中心化思想,服务之间采用Restful等轻量级通讯,比ESB更轻量

4、适于互联网时代,产品迭代周期更短

缺点:

1、微服务过多,治理成本高,不利于维护系统

2、分布式系统开发的成本高(容错,分布式事务等)对团队挑战大


使用 Spring Boot 开发分布式微服务时,我们面临以下问题

1、与分布式系统相关的复杂性-这种开销包括网络问题,延迟开销,带宽问题,安全问题。

2、服务发现-服务发现工具管理群集中的流程和服务如何查找和互相交谈。它涉及一个服务目录,在该目录中注册服务,然后能够查找并连接到该目录中的服务。

3、冗余-分布式系统中的冗余问题。

4、负载平衡 --负载平衡改善跨多个计算资源的工作负荷,诸如计算机,计算机集群,网络链路,中央处理单元,或磁盘驱动器的分布。

5、性能-问题 由于各种运营开销导致的性能问题。

6、部署复杂性-Devops 技能的要求。

2.4、你们公司里面使用的springboot springcloud springcloudalibaba 的版本是什么

[外链图片转存中…(img-cRnBDvDf-1618290493020)]

2.5、服务注册和发现是什么意思?Spring Cloud 如何实现?

当我们开始一个项目时,我们通常在属性文件中进行所有的配置。随着越来越多的服务开发和部署,添加和修改这些属性变得更加复杂。有些服务可能会下降,而某些位置可能会发生变化。手动更改属性可能会产生问题。 Eureka 服务注册和发现可以在这种情况下提供帮助。由于所有服务都在 Eureka 服务器上注册并通过调用 Eureka 服务器完成查找,因此无需处理服务地点的任何更改和处理。

常见的服务注册组件

nacos

zookpeeper

eureka

3.Ribbon

3.1.什么是ribbon,ribbon 内置的负载均衡规则有哪些

[外链图片转存中…(img-85ekZtz9-1618290493027)]

ribbon 不属于 alibaba 也不属于netflex

[外链图片转存中…(img-WqZ4o80Z-1618290493038)]

3.2.说出ribbon 配置中 以下配置的意思?

[外链图片转存中…(img-Cvf3ZxBB-1618290493043)]

3.3.使用Ribbon调用远程服务的接口,怎样防止接口被重复消费
3.4.使用feign 或者 ribbon 远程调用服务的时候 会有些什么异常 怎么处理的

如果所有的重试完成 还是失败 要抛出 feign.RetryableException 异常

4.Feign

1.什么是feign 起什么作用

[外链图片转存中…(img-WcP6xtWi-1618290493046)]

2.说出@SpringQueryMap 注解的作用

@SpringQuertMap是在使用Feign调用其他服务的时候、如果传输的是对象且,使用的是get方法则参数需要加上
@SpringQuertMap

如果传对象使用的是get方式则被调用的服务方和使用feign的调用方都需要加上@RquestBody

3.为什么使用feign

FEIGN 集成ribbon 和 resttemplate

简化 服务之间的调用

4.feign异常处理

[外链图片转存中…(img-29kYaWvk-1618290493049)]

5.feign参数的传递

[外链图片转存中…(img-Ck21kJkq-1618290493051)]

6.负载平衡的意义是什么

[外链图片转存中…(img-hJRpLgQJ-1618290493054)]

5.nacos

1.什么是nacos

[外链图片转存中…(img-UUmxr4uT-1618290493061)]

2.注册中心挂了 ,我们还能调用远程服务吗

本地如果有注册列表信息的话__还能访问远程服务_

6.setinel

1.什么是setinel

Sentinel (分布式系统的流量防卫兵) 是阿里开源的一套用于服务容错的综合性解决方案。

它以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来保护服务的稳定性。

2.setinel的组成

核心库(Java 客户端):不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo /Spring Cloud 等框架也有较好的支持。

控制台(Dashboard):基于 Spring Boot 开发,打包后可以直接运行,用来配置容错方案 【运维人员】

3.什么叫服务雪崩

在微服务架构中、各个服务都可能有联系,调用等关系

服务雪崩就是一个或者几个服务出现问题,然后被别人调用导致其他服务也用不了,一个接一个大面积瘫痪

4.常见的容错策略有哪些

隔离

限流

熔断降级

超时

缓存预热

横向扩展

5.什么叫做QPS RT

QPS:每秒请求的次数

RT:处理请求的平均时间

6.SpringCloud中的hystrix的熔断和降级的区别及作用

熔断:不可用走备用

sentinel只有降级,而hystrix有降级和熔断

熔断(断开上层服务,保护下层服务):当某服务出现不可用或响应超时,为防止服务雪崩,暂时停止对该服务的调用
降级:将不重要或不紧急的服务 延迟或暂停这种现象叫做服务降级
从整个系统的负荷情况出发和考虑的,对某些负荷会比较高的情况,为了预防某些功能(业务场景)出现负荷过载或者响应慢的情况,在其内部暂时舍弃对一些非核心的接口和数据的请求,而直接返回一个提前准备好的fallback(退路)错误处理信息。这样,虽然提供的是一个有损的服务,但却保证了整个系统的稳定性和可用性。
区别:触发原因不同 服务熔断一般是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑;

7.setinel中抛出的容错相关的异常,怎么处理

可以做一个类作为bean来处理抛出的异常,但是需要实现UrlBlockHandler接口,注意:不能用正常的controllerAdvice来处理

[外链图片转存中…(img-8K7MnDeP-1618290493064)]

8.hystrix中 断路器的3个状态是什么

熔断关闭

熔断半开

熔断全开

9.hystrix与sentinel的区别

1. hystrix具有的功能

  • 线程池隔离/信号量隔离 Sentinel 不支持线程池隔离;信号量隔离对应 Sentinel 中的线程数限流。

  • 熔断器 Sentinel 支持按平均响应时间、异常比率、异常数来进行熔断降级。

  • Command 创建 直接使用 Sentinel SphU API 定义资源即可,资源定义与规则配置分离。

  • 规则配置 在 Sentinel 中可通过 API 硬编码配置规则,也支持多种动态规则源

  • 注解支持 Sentinel 也提供注解支持

  • 开源框架支持 Sentinel 提供 Servlet、Dubbo、Spring Cloud、gRPC 的适配模块,开箱即用;若之前使用 Spring Cloud Netflix,可迁移至 Spring Cloud Alibaba

[外链图片转存中…(img-zzg4Vu36-1618290493071)]

10.服务器性能指标解释:QPS、TPS、RT、Load、PV、UV

https://blog.csdn.net/qq_39416311/article/details/84892625

7.getWay(网关)

作用 路由 过滤 同样产品:网飞的zuul

1.

你可能感兴趣的:(面试)