JavaWEB部分
请描述转发和重定向的区别?
1、请求次数: 转发一次,重定向两次
2、浏览器地址:转发不变,重定向改变
3、使用request域共享数据:转发是一次请求可以共享数据,重定向浏览器发起两次请求,不能共享数据
4、相对路径: 转发地址不变会造成转发后的页面中的相对位置发生改变引起相对路径失效,重定向不会
5、效率:转发浏览器一次请求效率高,重定向效率低
6、WEB-INF下资源:转发可以访问,重定向不可以
==和===的区别?
1、== 只判断值是否相等,不考虑其数据类型是否相等
2、===既判断值相等,又判断数据类型相等
Http 常见的状态码有哪些?
200 OK //客户端请求成功
301 Moved Permanently(永久移除),请求的 URL 已移走。Response 中应该包含一个 Location URL, 说明资源现在所处的位置
302 found 重定向
400 Bad Request //客户端请求有语法错误,不能被服务器所理解
401 Unauthorized //请求未经授权,这个状态代码必须和 WWW-Authenticate 报头域一起使用
403 Forbidden //服务器收到请求,但是拒绝提供服务
404 Not Found //请求资源不存在,eg:输入了错误的 URL
500 Internal Server Error //服务器发生不可预期的错误
503 Server Unavailable //服务器当前不能处理客户端的请求,一段时间后可能恢复正常
Servlet生命周期
Servlet 加载—>实例化—>服务—>销毁。
生命周期详解:
init():
在Servlet的生命周期中,仅执行一次init()方法。它是在服务器装入Servlet时执行的,负责初始化Servlet对象。可以配置服务器,以在启动服务器或客户机首次访问Servlet时装入Servlet。无论有多少客户机访问Servlet,都不会重复执行init()。
service():
它是Servlet的核心,负责响应客户的请求。每当一个客户请求一个HttpServlet对象,该对象的Service()方法就要调用,而且传递给这个方法一个“请求”(ServletRequest)对象和一个“响应”(ServletResponse)对象作为参数。在HttpServlet中已存在Service()方法。默认的服务功能是调用与HTTP请求的方法相应的do功能。
destroy():
仅执行一次,在服务器端停止且卸载Servlet时执行该方法。当Servlet对象退出生命周期时,负责释放占用的资源。一个Servlet在运行service()方法时可能会产生其他的线程,因此需要确认在调用destroy()方法时,这些线程已经终止或完成。
如何与Tomcat 结合工作步骤:
(1)Web Client 向Servlet容器(Tomcat)发出Http请求
(2)Servlet容器接收Web Client的请求
(3)Servlet容器创建一个HttpRequest对象,将Web Client请求的信息封装到这个对象中。
(4)Servlet容器创建一个HttpResponse对象
(5)Servlet容器调用HttpServlet对象的service方法,把HttpRequest对象与HttpResponse对象作为参数传给HttpServlet 对象。
(6)HttpServlet调用HttpRequest对象的有关方法,获取Http请求信息。
(7)HttpServlet调用HttpResponse对象的有关方法,生成响应数据。
Servlet是单实例的吗?
servlet是单实例的[单例多线程]
service是多线程方法
Servlet是线程安全的吗?为什么?
Servlet对象并不是一个线程安全的对象。
Servlet第一次被调用的时候,init()方法会被调用,然后调用service() 方法,从第二次被请求开始,就直接调用service()方法。
因为servlet是单实例的,所以后面再次请求同一个Servlet的时候都不会创建Servlet实例,
而且web容器会针对每个请求创建一个独立的线程,这样多个并发请求会导致多个线程同时调用 service() 方法,这样就会存在线程不安全的问题。
如何解决Servlet线程不安全的问题?
(1)不要在servlet中使用成员变量。
(2)可以给servlet中的方法添加同步锁,Synchronized,但是不提倡,数据并发访问会造成阻塞等待。
(3)可以实现 SingleThreadModel 接口,如下。这样可以避免使用成员变量的问题,但是也不提倡,原因同上。
Public class Servlet1 extends HttpServlet implements SingleThreadModel{
……
}
谈谈过滤器的作用?
过滤器,是在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,
然后再传入servlet或者struts的 action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,
如果用户没有登陆都过滤掉),或者在传入servlet或者 struts的action前统一设置字符集,或者去除掉一些非法字符
Request对象的主要方法有哪些?
Request对象的主要方法:
setAttribute(String name,Object):设置名字为name的request 的参数值
getAttribute(String name):返回由name指定的属性值
getAttributeNames():返回request 对象所有属性的名字集合,结果是一个枚举的实例
getCookies():返回客户端的所有 Cookie 对象,结果是一个Cookie 数组
getCharacterEncoding() :返回请求中的字符编码方式
getContentLength() :返回请求的 Body的长度
getHeader(String name) :获得HTTP协议定义的文件头信息
getHeaders(String name) :返回指定名字的request Header 的所有值,结果是一个枚举的实例
getHeaderNames() :返回所以request Header 的名字,结果是一个枚举的实例
getInputStream() :返回请求的输入流,用于获得请求中的数据
getMethod() :获得客户端向服务器端传送数据的方法
getParameter(String name) :获得客户端传送给服务器端的有 name指定的参数值
getParameterNames() :获得客户端传送给服务器端的所有参数的名字,结果是一个枚举的实
request.getAttribute()和 request.getParameter()有何区别?
getParameter 得到的都是 String 类型的。或者是 http://a.jsp?id=123 中的 123,或者是某个表单提交过去的数据。
getAttribute 则可以是对象。
getParameter()是获取 POST/GET 传递的参数值;
getAttribute()是获取对象容器中的数据值;
getParameter:用于客户端重定向时,即点击了链接或提交按扭时传值用,即用于在用表单或 url 重定向传值时接收数据用。
getAttribute:用于服务器端重定向时,即在 sevlet 中使用了 forward 函数,或 struts 中使用了
mapping.findForward。 getAttribute 只能收到程序用 setAttribute 传过来的值。
getParameter()是获取 POST/GET 传递的参数值;
getAttribute()是获取 SESSION 的值;
另外,可以用 setAttribute,getAttribute 发送接收对象.而 getParameter 显然只能传字符串。
setAttribute 是应用服务器把这个对象放在该页面所对应的一块内存中去,当你的页面服务器
重定向到另一个页面时,应用服务器会把这块内存拷贝另一个页面所对应的内存中。这样
getAttribute 就能取得你所设下的值,当然这种方法可以传对象。 session 也一样,只是对象在内存中的生命周期不一样而已。 getParameter 只是应用服务器在分析你送上来的 request页面的文本时,取得你设在表单或 url 重定向时的值。
getParameter 返回的是 String, 用于读取提交的表单中的值;
getAttribute 返回的是 Object,需进行转换,可用 setAttribute 设置成任意对象,使用很灵活,可随时用;
什么是Tomcat?
Tomcat简单的说就是一个运行JAVA的网络服务器,底层是Socket的一个程序,它也是JSP和Serlvet的一个容器。
详细描述MVC!
基于java的web应用系统采用MVC设计模型,即用Model(模型)、View(视图)和Controller(控制)分离设计,这是目前web应用服务系统的主流设置方向。
Model:处理业务逻辑的模块。
View:负责页面显示,显示Model的处理结果给用户,主要实现数据到页面的转换过程。
Controller:负责每个请求的分发,把Form数据传递给Model进行处理,处理完成后,把处理结果返回给相应的View显示给用户。
Http请求由哪三部分组成?
http协议报文
1.请求报文(请求行/请求头/请求数据/空行)
请求行
求方法字段、URL字段和HTTP协议版本
例如:GET /index.html HTTP/1.1
get方法将数据拼接在url后面,传递参数受限
请求方法:
GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT
请求头(key value形式)
User-Agent:产生请求的浏览器类型。
Accept:客户端可识别的内容类型列表。
Host:主机地址
请求数据
post方法中,会把数据以key value形式发送请求
空行
发送回车符和换行符,通知服务器以下不再有请求头
2.响应报文(状态行、消息报头、响应正文)
状态行
消息报头
响应正文
请说下在后台Servlet代码中如何获取前端form表单提交的属性?
可以使用request.getParameter(); 也可以使用request.getParameterMap(),在使用beanutils.populate()方法
说说Promise有什么特别?
(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。
只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。
npm常用命令?
1.项目初始化 npm init
2.安装依赖 npm install 包名 或者 npm install 包名@版本号/npm install -g 包名/npm install
3.升级依赖 npm update 包名
4.卸载依赖 npm uninstall 包名
5.查看依赖 npm ls查看项目依赖 npm list -g查看全局依赖
ES6模块化有几种暴露方式,分别作出解释?
1.分别暴露 // 模块想对外导出,添加export关键字即可!
2.统一暴露 // 模块想对外导出,export统一暴露想暴露的内容!
3.默认暴露 // 默认暴露语法 export default sum默认暴露相当于是在暴露的对象中增加了一个名字为default的属性
请描述get请求 和 post请求的区别?
① 浏览器和表单的默认提交方式是get,get请求效率比post高
② get请求参数在url地址后拼接,所以有以下特点:
- 请求报文没有请求体 少了和请求体相关的请求头参数
- 参数在url地址中拼接,上传参数大小有限制,不能用来上传文件,相对post请求不安全
③ post请求参数在请求报文的请求体中携带,有以下特点:
- 请求报文有请求体,相对安全
- 请求头多了和请求体相关的参数 请求体数据没有大小限制可以用来上传文件
async await的基本使用
async 表示这是一个async函数, await只能用在async函数里面,不能单独使用 async 返回的是一个Promise对象,await就是等待这个promise的返回结果后,再继续执行 await 如果右边的是一个Promise对象,后面必须跟一个Promise对象,但是不必写then(),直接就可以得到返回值,如果await右边是一个普通数据 返回的就是普通数据
session 和 cookie 有什么区别?
Cookie:主要用在保存客户端,其值在客户端与服务端之间传送,不安全,存储的数据量有限。 Session:保存在服务端,每一个session在服务端有一个sessionID作一个标识。存储的数据量大,安全性高。占用服务端的内存资源 cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,相当重要的数据,应该使用session保存到服务端。 session会在一定时间内保持在服务器上,但是会占用内存资源,当访问的用户过多,会加重服务器的负载,考虑到减轻服务器的压力,可以将不重要的数据放在cookie中持久的保存。 单个cookie保存的数据不能超过4k,很多浏览器都限制站点最多保存20个cookie。 由于HTTP协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户,这个机制就是Session.典型的场景比如购物车,当你点击下单按钮时,由于HTTP协议无状态,所以并不知道是哪个用户操作的,所以服务端要为特定的用户创建了特定的Session,用用于标识这个用户,并且跟踪用户,这样才知道购物车里面有几本书。 这个Session是保存在服务端的,有一个唯一标识。在服务端保存Session的方法很多,内存、数据库、文件都有。 集群的时候也要考虑Session的转移,在大型的网站,一般会有专门的Session服务器集群,用来保存用户会话,这个时候 Session 信息都是放在内存的,使用一些缓存服务比如Memcached之类的来放 Session。 这个时候Cookie就登场了。每次HTTP请求的时候,客户端都会发送相应的Cookie信息到服务端。实际上大多数的应用都是用 Cookie 来实现Session跟踪的,第一次创建Session的时候,服务端会在HTTP协议中告诉客户端,需要在 Cookie 里面记录一个Session ID,以后每次请求把这个会话ID发送到服务器,我就知道你是谁了。
简述响应式数据和非响应式数据?
响应式: 1. 当Vue组件的实例初始化的时候已有的数据就是响应式数据 2. 响应式属性的值发生改变会触发视图更新 非响应式: 1. 当Vue组件的实例初始化的时候没有,后期添加的属性 2. 非响应式属性的值发生改变不会触发视图更新
请说下Vue 有哪些指令,并简述其作用(5个以上)?
v-html:用于渲染HTML标签 v-show:用于类似双大括号语法渲染数据 v-if:渲染数据的时候,也可以用于条件判断 v-for:遍历集合或者数组,用于页面渲染数据 v-bind:绑定属性,注意冒号后面跟标签的属性,属性后面的等号指向数据,它可以简写为 :class, :href。 V-model:数据双向绑定
简述JS中var let const声明变量的区别?
Let 和 var的区别 1、let 不能重复声明 2、let有块级作用域,非函数的花括号遇见let会有块级作用域,也就是只能在花括号里面访问。 3、let不会预解析进行变量提升 4、let 定义的全局变量不会作为window的属性 const和var的差异 1、新增const和let类似,只是const定义的变量不能修改 2、并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。
框架部分
Maven 构建工具
Maven项目依赖中作用范围scope?
当一个Maven工程添加了对某个jar包的依赖后,这个被依赖的jar包可以对应下面几个可选的范围,默认是compile。
Maven项目之间的三种关系及其特征?
- 依赖关系(兄弟关系、朋友关系):
- 项目A依赖项目B,项目A可以访问项目B中某些依赖,避免重复提供
- 缺点:但是只有范围为compile时可以访问
- 继承关系(父子关系,并列关系):
- 使用继承时,需要定义父项目和子项目
- 继承关系是单向关系:子项目指定父项目,父项目不用指定子项目
- 父项目的所有的依赖(compile、test、provided等)子项目都可以自动使用
- 父项目中可以通过dependencyManagement来管理依赖,子项目如果需要必须手动声明
- 缺点:彼此间是并列关系,父项目、子项目需要分别逐个手动进行clean、compile操作
- 聚合关系(父子关系,包含关系):
- 首先是继承关系,并且比继承关系更进一步
- 在聚合关系中, 子项目明确父项目, 但是父项目明确子项目,是双向关系
- 其实是一个大项目包含多个子项目,对父项目进行clear、compile等命令,
是对所有子项目进行clear、compile命令。但是如果对一个子项目进行maven操作,不影响其他子项目
Maven中A依赖B,B依赖C,那么A可以使用C中的类吗?
此时要看B依赖C时的范围,如果是compile范围则A可以使用C,如果是test或provided范围则A不能使用C。
通过Maven下载jar包,下载失败了怎么办?(提示:分*.lastUpdated和内部损坏两种情况说明)
.lastUpdated情况:将.lastUpdated文件删除,重新下载。如果*.lastUpdated这样的文件很多,则使用专门的批处理脚本统一清理。
内部损坏情况:删除损坏的jar包重新下载。
下面依赖信息对应的jar包在Maven仓库根目录下的路径是什么?
答案:Maven本地库根目录/org/apache/commons/commons-lang3/3.1/commons-lang3-3.1.jar
Maven仓库之间的关系以及优先级?(须简单介绍三个仓库)
Maven仓库是用来存储和管理Maven项目所需依赖和插件的地方。通常情况下,Maven仓库可以分为三个层次:本地仓库、中央仓库和远程仓库。
本地仓库:是位于本地计算机上的一个目录,用于存储Maven项目构建所需的依赖和插件。当第一次构建项目时,Maven会自动从中央仓库下载所需的依赖到本地仓库。本地仓库具有最高的优先级,即当构建项目时,Maven会首先在本地仓库中查找依赖,如果找到则直接使用,否则才会去中央仓库或远程仓库下载。
中央仓库:是Maven官方维护的仓库,包含了大量的开源Java项目依赖和插件。当Maven构建项目时,如果本地仓库没有找到所需的依赖,就会去中央仓库下载。中央仓库具有较高的优先级,因为它包含了许多常用的依赖和插件。
远程仓库:是自定义的仓库,用于存放特定的依赖和插件。远程仓库可以是私有的,也可以是公共的。当本地仓库和中央仓库都没有找到所需的依赖时,Maven会去远程仓库下载。远程仓库具有较低的优先级,因为它是在本地仓库和中央仓库之后才被搜索的。
总之,Maven仓库之间的关系是本地仓库优先于中央仓库和远程仓库,中央仓库优先于远程仓库。这样的优先级规则保证了Maven能够高效地查找和下载所需的依赖和插件。
如何解决Mavan 环境依赖jar包冲突
- 版本排除
com.example example-artifact 1.0.0 conflicting-group conflicting-artifact
Ssm框架
如何理解框架framework?
- 生活案例:不需要自己盖房,直接购买毛坯房即可,自己来装修,质量户型有保证,还节省了建房的时间。
在开发过程中使用的框架就好比毛坯房。
- 框架= jar(大量最佳实践基础上的对特定问题的固定解决方案进行封装并提供相应的API)
+ 配置文件(个性化定制,配置变化的内容,比如数据库连接参数、端口号、接口的具体实现类等)
- 作用1:可以保证减少开发时间、降低开发难度,并且还保证设计质量。好比和世界上最优秀的软件工程师是
一个项目的,并且他们完成的还是基础、全局的工作。想想是不是很嗨的一件事情。
- 作用2:框架还有一个作用是约束,统一了代码流程和风格。同样的技术解决同样的问题会产生不同流程和
风格的解决方案,而采用一种框架其实就是限制用户必须使用其规定的方案来实现,可降低程序员
之间沟通以及日后维护的成本。
- 常用的基于JavaEE的三大开源框架,已经从SSH、SSH2过渡到了SSM:SpringMVC、Spring、MyBatis。
- 总之,框架是一个半成品,已经对基础的代码进行了封装并提供相应的API,开发者在使用框架是直接调用
封装好的API可以省去很多代码编写,从而提高工作效率和开发速度,并统一了风格(这一点不要忽略掉)。
如何理解ORM
- JDBC的缺点:需要手动的完成面向对象的Java语言、面向关系的数据库之间数据的转换,代码繁琐无技术含量,
影响了开发效率(查询时需要手动的将结果集ResultSet的列数据转换为Java对象的属性;
而添加操作时需要手动将Java对象的属性转换为数据库表的列字段)。
- 关于面向对象的Java语言、面向关系的数据库之间数据的转换必须要做,问题在于这个转换是否可以不由开
发者来做。可以的。ORM框架就是专门来做这个问题的,相当于在面向对象语言和关系数据库之间搭建一个桥梁。
- ORM,Object-Relationl Mapping,对象关系映射,它的作用是在关系型数据库和对象之间作一个映射,
这样我们在具体的操作数据库的时候,只要像平时操作对象一样操作它就可以了,
ORM框架会根据映射完成对数据库的操作,就不需要再去和复杂的SQL语句打交道了。
Hibernate是一个全自动的ORM框架。因为Hibernate创建了Java对象和数据库表之间的完整映射,
可以完全以面向对象的思想来操作数据库,程序员不需要手写SQL语句。MyBatis中还需要手写SQL语句,
所以是半自动化的。但是最终MyBatis却战胜了Hibernate,主要还是因为MyBatis可以更加精确的定义SQL,
更加灵活,也便于优化性能。
Mybatis 结果集的映射方式有几种,并分别解释每种映射方式如何使用?
自动映射 ,通过resultType来指定要映射的类型即可。 自定义映射 通过resultMap来完成具体的映射规则,指定将结果集中的哪个列映射到对象的哪个属性。
Mybatis中#{}和${}的区别是什么?
#{}是预编译处理,${}是字符串替换。 Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值; Mybatis在处理${}时,就是把${}替换成变量的值。 使用#{}可以有效的防止SQL注入,提高系统安全性。
Mybatis中当实体类中的属性名和表中的字段名不一样 ,怎么办 ?
第1种: 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。 第2种: 通过
MyBatis如何获取自动生成的(主)键值?如何完成MySQL的批量操作
在
简述MyBatis的单个参数、多个参数如何传递及如何取值
1、MyBatis传递单个参数,如果是普通类型(String+8个基本)的,取值时在#{}中可以任意指定,如果是对象类型的,则在#{}中使用对象的属性名来取值
2、MyBatis传递多个参数,默认情况下,MyBatis会对多个参数进行封装Map. 取值时 在#{}可以使用012 .. 或者是param1 param2.. 3、MyBatis传递多个参数,建议使用命名参数,在Mapper接口的方法的形参前面使用 @Param() 来指定封装Map时用的key. 取值时在#{}中使用@Param指定的key.
方法一:顺序传参
|
|
#{}里面的数字代表你传入参数的顺序。 这种方法不建议使用,sql层表达不直观,且一旦顺序调整容易出错。
方法二:@Param注解传参
|
|
#{}里面的名称对应的是注解 @Param括号里面修饰的名称。 这种方法在参数不多的情况还是比较直观的,推荐使用。
方法三:Map传参
|
|
#{}里面的名称对应的是 Map里面的key名称。 这种方法适合传递多个参数,且参数易变能灵活传递的情况。
讲述下MyBatis多表映射中association与collection区别
在MyBatis多表映射中,association和collection是两种不同的映射类型,用于处理关联关系和一对多的关系。
association: association用于描述两个表之间的一对一关系。它表示一个复杂类型(Java对象)在另一个表中的外键关联。在映射文件中,我们可以使用association来定义关联关系,指定外键列和关联的结果映射。 例如,假设我们有两个表:Order(订单)和User(用户),一个订单只对应一个用户。我们可以在Order的映射文件中使用association来描述订单和用户之间的关联关系:
请写出Mybatis中常用的动态标签,并简单介绍其作用?
if 标签 if 标签通常用于 WHERE 语句、UPDATE 语句、INSERT 语句中,通过判断参数值来决定是否使用某个查询条件、判断是否更新某一个字段、判断是否插入某个字段的值。
foreach 标签 foreach 标签主要用于构建 in 条件,可在 sql 中对集合进行迭代。也常用到批量删除、添加等操作中。
choose 标签 有时候我们并不想应用所有的条件,而只是想从多个选项中选择一个。MyBatis 提供了 choose 元素,按顺序判断 when 中的条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when的条件都不满则时,则执行 otherwise 中的 sql。类似于 Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。
where 标签 当 if 标签较多时,如果标签返回的内容是以 AND 或 OR 开头的,则它会剔除掉. set 标签 使用 set 标签可以将动态的配置 set关键字,和剔除追加到条件末尾的任何不相关的逗号。
trim 标签 格式化输出,也可以通过 trim 标签设定或忽略前后缀来实现. 配置关联关系 collection 标签 配置一对多 association 标签 配置一对一 sql 标签 当多种类型的查询语句的查询字段或者查询条件相同时,可以将其定义为常量,方便调用。为求
描述下Spring Ioc依赖注入,有哪些方式?(IOC和DI)
构造器依赖注入:构造器依赖注入在容器触发构造器的时候完成,该构造器有一系列的参数,每个参数代表注入的对象。
Setter方法依赖注入:首先容器会触发一个无参构造函数或无参静态工厂方法实例化对象,之后容器调用bean中的setter方法完成Setter方法依赖注入。 全局属性注入:
说下对Spring面向切面编程(AOP)的理解?以及常用术语
- 面向切面编程AOP可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。 可以和过滤器进行类比来理解AOP,有很多相似点。 - OOP解决纵向的业务问题,AOP解决横向的问题,比如日志、安全验证、事务、异常等。 相同的代码重复的出现在项目的不同位置,不利于维护。可以将这些功能分别提取出来,由多份变成一份, 然后在编译或者运行时织入到指定的多个位置。 - Spring底层使用了动态代理模式实现AOP。若目标对象实现了若干接口,Spring 使用JDK的动态代理。 若目标没有实现任何接口,Spring 使用 CGLIB 库生成目标类的子类。还可以配置不管是否实现接口, 都是要CGLIB。 面向切面编程(AOP):允许程序员模块化横向业务逻辑,或定义核心部分的功能,例如日志管理和事务管理。 切面(Aspect) :AOP的核心就是切面,它将多个类的通用行为封装为可重用的模块。该模块含有一组API提供 cross-cutting功能。例如,日志模块称为日志的AOP切面。根据需求的不同,一个应用程序可以有若干切面。在Spring AOP中,切面通过带有@Aspect注解的类实现。 通知(Advice):通知表示在方法执行前后需要执行的动作。实际上它是Spring AOP框架在程序执行过程中触发的一些代码。Spring切面可以执行一下五种类型的通知: before(前置通知):在一个方法之前执行的通知。 after(最终通知):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。 after-returning(后置通知):在某连接点正常完成后执行的通知。 after-throwing(异常通知):在方法抛出异常退出时执行的通知。 around(环绕通知):在方法调用前后触发的通知。 切入点(Pointcut):切入点是一个或一组连接点,通知将在这些位置执行。可以通过表达式或匹配的方式指明切入点。 引入:引入允许我们在已有的类上添加新的方法或属性。 目标对象:被一个或者多个切面所通知的对象。它通常是一个代理对象。也被称做被通知(advised)对象。 代理:代理是将通知应用到目标对象后创建的对象。从客户端的角度看,代理对象和目标对象是一样的。有以下几种代理: BeanNameAutoProxyCreator:bean名称自动代理创建器 DefaultAdvisorAutoProxyCreator:默认通知者自动代理创建器 Metadata autoproxying:元数据自动代理织入:将切面和其他应用类型或对象连接起来创建一个通知对象的过程。织入可以在编译、加载或运行时完成。
Spring中常用的设计模式
- 代理模式——Spring 中两种代理方式,若目标对象实现了若干接口,Spring 使用JDK的java.
lang.reflect.Proxy类代理。若目标没有实现任何接口,Spring 使用 CGLIB 库生成目标类的子类。
- 单例模式——在 Spring 的配置文件中设置 bean 默认为单例模式。
- 模板方式模式——用来解决代码重复的问题。比如:RestTemplate、JmsTemplate、JpaTemplate。
- 工厂模式——在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用同一个
接口来指向新创建的对象。Spring 中使用 beanFactory 来创建对象的实例。
简述Spring声明式事务中@Transaction中常用的两种事务传播行为?
通过propagation来执行事务的传播行为 REQUIRED: 使用调用者的事务,如果调用者没有事务,则启动新的事务运行 REQUIRES_NEW: 将调用者的事务挂起,开启新的事务运行。
谈谈你对spring框架的深入理解?
Spring一款容器框架,其核心是IOC和AOP (1)IOC就是控制反转,指创建对象的控制权转移给Spring框架进行管理,并由Spring根据配置文件去创建实例和管理各个实例之间的依赖关系,对象与对象之间松散耦合,也利于功能的复用。DI依赖注入,和控制反转是同一个概念的不同角度的描述,即 应用程序在运行时依赖IoC容器来动态注入对象需要的外部依赖。 (2)最直观的表达就是,以前创建对象的主动权和时机都是由自己把控的,IOC让对象的创建不用去new了,可以由spring自动生产,使用java的反射机制,根据配置文件在运行时动态的去创建对象以及管理对象,并调用对象的方法的。 (3)AOP,一般称为面向切面,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,提高系统的可维护性。可用于权限认证、日志、事务处理。 AOP实现的关键在于 代理模式,AOP代理主要分为静态代理和动态代理。静态代理的代表为AspectJ;动态代理则以Spring AOP为代表。
说一下Spring中支持的bean作用域?
Spring框架支持如下五种不同的作用域: singleton:在Spring IOC容器中仅存在一个Bean实例,Bean以单实例的方式存在。 prototype:一个bean可以定义多个实例。 Web容器 request:每次HTTP请求都会创建一个新的Bean。该作用域仅适用于WebApplicationContext环境。 session:一个HTTP Session定义一个Bean。该作用域仅适用于WebApplicationContext环境。 globalSession:同一个全局HTTP Session定义一个Bean。该作用域同样仅适用于WebApplicationContext环境。bean默认的scope属性是"singleton"。
解释自动装配的各种模式?(扩展)
自动装配提供五种不同的模式供Spring容器用来自动装配beans之间的依赖注入: no:默认的方式是不进行自动装配,通过手工设置ref 属性来进行装配bean。 byName:通过参数名自动装配,Spring容器查找beans的属性,这些beans在XML配置文件中被设置为byName。之后容器试图匹配、装配和该bean的属性具有相同名字的bean。 byType:通过参数的数据类型自动自动装配,Spring容器查找beans的属性,这些beans在XML配置文件中被设置为byType。之后容器试图匹配和装配和该bean的属性类型一样的bean。如果有多个bean符合条件,则抛出错误。 constructor:这个同byType类似,不过是应用于构造函数的参数。如果在BeanFactory中不是恰好有一个bean与构造函数参数相同类型,则抛出一个严重的错误。 autodetect:如果有默认的构造方法,通过 construct的方式自动装配,否则使用 byType的方式自动装配。
解释Spring框架中bean的生命周期?
1.首先容器启动后,会对scope为singleton且非懒加载的bean进行实例化, 2.按照Bean定义信息配置信息,注入所有的属性, 3.如果Bean实现了BeanNameAware接口,会回调该接口的setBeanName()方法,传入该Bean的id,此时该Bean就获得了自己在配置文件中的id, 4.如果Bean实现了BeanFactoryAware接口,会回调该接口的setBeanFactory()方法,传入该Bean的BeanFactory,这样该Bean就获得了自己所在的BeanFactory, 5.如果Bean实现了ApplicationContextAware接口,会回调该接口的setApplicationContext()方法,传入该Bean的ApplicationContext,这样该Bean就获得了自己所在的ApplicationContext, 6.如果有Bean实现了BeanPostProcessor接口,则会回调该接口的postProcessBeforeInitialzation()方法, 7.如果Bean实现了InitializingBean接口,则会回调该接口的afterPropertiesSet()方法, 8.如果Bean配置了init-method方法,则会执行init-method配置的方法, 9.如果有Bean实现了BeanPostProcessor接口,则会回调该接口的postProcessAfterInitialization()方法, 10.经过流程9之后,就可以正式使用该Bean了,对于scope为singleton的Bean,Spring的ioc容器中会缓存一份该bean的实例,而对于scope为prototype的Bean,每次被调用都会new一个新的对象,期生命周期就交给调用方管理了,不再是Spring容器进行管理了 11.容器关闭后,如果Bean实现了DisposableBean接口,则会回调该接口的destroy()方法, 12.如果Bean配置了destroy-method方法,则会执行destroy-method配置的方法,至此,整个Bean的生命周期结束
简述SpringMVC 的工作原理?(处理请求流程)
(1)用户向服务器发送请求,请求被springMVC 前端控制器 DispatchServlet 捕获; (2)DispatcherServle 对请求 URL 进行解析,得到请求资源标识符(URL),然后根据该 URL 调用 HandlerMapping将请求映射到处理器 HandlerExcutionChain; (3)DispatchServlet 根据获得 Handler 选择一个合适的HandlerAdapter 适配器处理; (4)Handler 对数据处理完成以后将返回一个 ModelAndView()对象给 DisPatchServlet; (5)Handler 返回的 ModelAndView() 只是一个逻辑视图并不是一个正式的视图, DispatcherSevlet 通过ViewResolver 试图解析器将逻辑视图转化为真正的视图View; (6)DispatcherServle 通过 model 解析出 ModelAndView()中的参数进行解析最终展现出完整的 view 并返回给客户端;
简述SpringMVC中处理模型数据的两种方式?Handler(Model Map ModelMap ) return ModelAndView
- 使用 2. ModelAndView 作为方法的返回值,将 模型数据 和 视图信息封装到ModelAndView中 3. 使用Map 或者是Model 作为方法的形参. 将模型数据添加到Map或者是Model中.
SpringMVC中如何实现请求域request中传递数据
- 使用原生API request
- 使用Model
- 使用Map
- 使用ModelMap
- 使用ModelAndView
注意:传入的Model、ModelMap、Map类型的数的三种方式其实本质上都是 BindingAwareModelMap 类型的,而四种非原生方式底层都调用了原生的request.setAttribute(name,value)。
简述SpringMVC中如何返回JSON数据?
- 在工程最终加入jackson的jar包 2. 在请求处理方法中,将返回值改为具体返回的数据的类型, 例如 数据的集合类型 List
等。 3. 在请求处理方法上使用@ResponseBody注解
SpringMVC如何快速返回jsp视图
准备jsp页面和依赖 pom.xml依赖
PageHelper插件是如何使用
拦截器:它自己就在 IOC 容器中,所以可以直接从 IOC 容器中装配组件。
\1. pom.xml引入依赖
\2. mybatis-config.xml配置分页插件
在 MyBatis 的配置文件中添加 PageHelper 的插件:
其中,com.github.pagehelper.PageInterceptor
是 PageHelper 插件的名称,dialect
属性用于指定数据库类型(支持多种数据库)
SpringMVC中如何实现Restful风格的数据传输和接收
\1. web.xml中添加过滤器org.springframework.web.filter.HiddenHttpMethodFilter,负责根据表单项的取值情况将POST请求转换为PUT请求或者DELETE。
\2. 视图中页面上使用Restful的地址提交请求(不管是Ajax还是非Ajax请求均可)。
\3. Controller中方法使用@GetMapping/@PostMapping/@PutMapping/@DeleteMapping指定映射路径,如果包含路径变量使用{}来表示,方法参数前使用@PathVariable注解将路径变量和参数绑定。
简单的谈一下SpringMVC的核心API(核心组件)
- DispatcherServlet:总控制器
- HandlerMapping:处理器映射器,建立了请求路径和分控制器方法之间的映射
- HandlerExecutionChain:总控制器调用HandlerMapping组件的返回值,是一个执行链,不仅有要执行的分控制器方法,还有相应的多个拦截器,组成一个执行链
- HandlerAdapter:处理器适配器,调用Handler,不是由总控制直接调用的,而是由HandlerAdapter来调用
- ViewResolver:逻辑视图(result)—–>物理视图(/WEB-INF/templates/result.html)
请解释@Autowired(required =true | false)注解的工作机制及required属性的作用?
首先会使用byType的方式进行自动装配,如果能唯一匹配,则装配成功, 如果匹配到多个兼容类型的bean, 还会尝试使用byName的方式进行唯一确定. 如果能唯一确定,则装配成功,如果不能唯一确定,则装配失败,抛出异常. 默认情况下, 使用@Autowired标注的属性必须被装配,如果装配不了,也会抛出异常. 可以使用required=false来设置不是必须要被装配.
说下ContextLoaderListener的作用
常见使用场景:
- 场景1:使用了Spring但是没有使用SpringMVC的web项目(比如Dubbo服务提供者),如何加载Spring配置文件?可以使用ContextLoaderListener来加载。
- 场景2:使用了SpringMVC但是项目规模大,有多个配置文件,除了使用DispatcherServlet一次性加载,是否有其他方法?可以使用ContextLoaderListener和DispatcherServlet分别加载。
使用及其注意事项:
- public class ContextLoaderListener extends ContextLoader implements ServletContextListener,该类是一个ServletContextListener,在项目启动的时候加载。注意:Servlet、Filter、Listener的加载顺序:Listener、Filter、Servlet。所以会先加载ContextLoaderListener ,再加载DispatcherServlet。
- 使用ContextLoaderListener加载非SpringMVC配置文件创建的IoC容器是父容器,DispatcherServlet加载SpringMVC的的配置文件创建的IoC容器是子容器。子容器优先使用自己的Bean,如果没有,可以使用父容器的Bean。
- 注意事项:同时使用了ContextLoaderListener和DispatcherServlet,如果<context:component-scan >的路径设置不合理,就会重复的创建Bean,甚至导致无法应用业务层事务的问题。
请描述一下Spring的事务管理?
1、声明式事务管理的定义:用在 Spring 配置文件中声明式的处理事务来代替代码式的处理事务。这样的好处是,事务管理不侵入开发的组件,具体来说,业务逻辑对象就不会意识到正在事务管理之中,事实上也应该如此,因为事务管理是属于系统层面的服务,而不是业务逻辑的一部分,如果想要改变事务管理策划的话,也只需要在定义文件中重新配置即可,这样维护起来极其方便。 基于 TransactionInterceptor 的声明式事务管理:两个次要的属性: transactionManager,用来指定一个事务治理器, 并将具体事务相关的操作请托给它; 其他一个是 Properties 类型的transactionAttributes 属性,该属性的每一个键值对中,键指定的是方法名,方法名可以行使通配符, 而值就是表现呼应方法的所运用的事务属性。 2、基于 @Transactional 的声明式事务管理:Spring 2.x 还引入了基于 Annotation 的体式格式,具体次要触及@Transactional 标注。@Transactional 可以浸染于接口、接口方法、类和类方法上。算作用于类上时,该类的一切public 方法将都具有该类型的事务属性。 编程式事物管理的定义:在代码中显式挪用 beginTransaction()、commit()、rollback()等事务治理相关的方法, 这就是编程式事务管理。Spring 对事物的编程式管理有基于底层 API 的编程式管理和基于 TransactionTemplate 的编程式事务管理两种方式。
说一下你对spring框架中通知类型的理解?
(1)前置通知(Before Advice):在连接点(Join point)之前执行的通知。 (2)后置通知(After Advice):当连接点退出的时候执行的通知(不论是正常返回还是异常退出)。 (3)环绕通知(Around Advice):包围一个连接点的通知,这是最强大的一种通知类型。 环绕通知可以在方法调用前后完成自定义的行为。它也可以选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。 (4)返回后通知(AfterReturning Advice):在连接点正常完成后执行的通知(如果连接点抛出异常,则不执行) 抛出异常后通知(AfterThrowing advice):在方法抛出异常退出时执行的通知
请说出SpringMVC和Spring中常用的注解,并阐明其作用?
- @Controller,使用它标记的类就是一个SpringMVC Controller 对象 2. @RequestMapping,处理请求映射地址 3. @PathVariable,用于对应restful风格url中的参数 4. @RequestParam,将请求的参数绑定到方法中的参数上 5. @ResponseBody,将返回类型直接输入到http response body中 6. @RequestBody,方法参数直接被绑定到http request body中 7. @Component:泛指各种组件 8. @Service:业务层 9. @Repository:数据访问层 10.@Controller、@Service、@Repository都可以称为@Component。
@RequestMapping注解用在类上面有什么作用?
它是一个用来处理请求地址映射的注解,可用于类或方法上。 用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
简述一下@RestController注解的作用
如果需要 @ResponseBody 注解作用在类上时,我们可以直接使用 @RestController 注解,这个注解相当于@ResponseBody + @Controller注解,这样我们就不需要写两个注解了,具体如下所示: @Target({ElementType.TYPE})``@Retention(RetentionPolicy.RUNTIME)``@Documented@Controller``@ResponseBodypublic ``@interface RestController { `` @AliasFor( ``annotation = Controller.class `` ) String value() default "";}
@RestController注解的使用后,该类所有控制层方法都以JSON的形式返回。
SpringMVC怎么样设定重定向和转发的?
(1)转发:在返回值前面加"forward:",譬如"forward:user.do?name=method4" (2)重定向:在返回值前面加"redirect:",譬如"redirect:http://www.baidu.com"
如何理解编程式事务与声明式事务?并说出他们的区别
编程式事务和声明式事务是两种常见的事务管理方式。 编程式事务是在代码中显式地编写事务管理逻辑。开发人员需要手动在代码中控制事务的开始、提交或回滚,并处理可能出现的异常。编程式事务通常使用事务管理接口(如JDBC的Connection对象)来实现。 声明式事务是通过配置的方式来管理事务,而不需要在代码中显式地编写事务管理逻辑。开发人员只需在配置文件中声明事务的属性,如事务的传播行为、隔离级别等,由事务管理框架自动管理事务的开始、提交或回滚。 这两种事务管理方式的区别如下: 代码侵入性:编程式事务需要在代码中显式地编写事务管理逻辑,与业务逻辑代码紧密耦合,造成代码的冗余。而声明式事务通过配置方式管理事务,使得业务逻辑与事务管理逻辑解耦。 管理粒度:编程式事务可以灵活地控制事务的开始、提交或回滚,适用于复杂的事务场景。而声明式事务由事务管理框架自动管理事务,粒度较粗,适用于简单的事务场景。 可读性和可维护性:声明式事务通过配置文件来管理事务,代码清晰简洁,易于理解和维护。而编程式事务需要在代码中编写事务管理逻辑,代码复杂,可读性和可维护性较差。 综上所述,编程式事务适用于复杂的事务场景,提供了更高的灵活性和粒度控制;而声明式事务适用于简单的事务场景,使得代码更加清晰简洁。
SpringMVC的返回值类型有哪些,具体说出一个使用场景?
有String, ModelAndView。ModelAndView类把视图和数据都合并的一起的,但一般用String比较好。
SQL题,有以下4张表
请写出以下sql的查询语句
(1)查询Score表中成绩为60或者为80的所有记录
select * from Score where Degree in (60,80)
(2)查询Student表中学生不在C_001的所有记录
select * from Student where Class not in (‘C_001’)
(3)查询Score表中的最底分的学生学号和课程号
select SNO,CNO from Score where Degree=(select MIN(Degree) from Score)
(4)查询Score表中的最高分的学生学号和课程号
select SNO,CNO from Score where Degree=(select MAX(Degree) from Score)
(5)查询成绩高于学号为“109”、课程号为“3-105”的成绩的所有记录
select * from student,Score where student.Sno=Score.Sno and Score.Degree>(select Degree from Score where Cno=‘3-105’ and Sno=‘109’)
(6)查询Student表中不姓“王”的同学记录
select * from student where Sname not like (‘王%’)
(7)以班号和年龄从大到小的顺序查询Student表中的全部记录
select * from student order by Class desc,Sbirthday asc
(8)查询Student表中出生年月不为空的同学记录
select * from student where Sbirthday is not null
(9)以年龄从大到小的顺序查询Student表中的全部记录
select * from student order by Sbirthday asc
Redis 专题
Redis为什么那么快?
- 完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,
HashMap的优势就是查找和操作的时间复杂度都是O(1)。
- 数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的。
- 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,
不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗
(Redis6.0后引入了多线程,但是为了重复利用CPU多核的优势,线程数量取决于CPU核数,
而不是每个请求开启一个新线程)。
- 使用多路I/O复用模型,非阻塞IO。I/O多路复用就是通过一种机制,让一个进程可以监视多个描述符,
一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。
常用的IO多路复用的实现有:select、poll、epoll。多路复用IO 技术最适用的是“高并发”场景。
- 使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了
VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
Redis的五大数据类型,使用场景,底层原理?
Redis有哪些持久化机制?它们分别是如何工作的?
需要注意的是,Redis还支持持久化的混合模式,即同时使用RDB和AOF持久化机制。这样可以在某种程度上兼顾RDB和AOF的优点,并根据实际需求进行配置。 选择合适的持久化机制取决于应用的要求和场景。如果对数据完整性要求较高,可以选择AOF持久化。如果对性能和快速恢复较为重要,可以选择RDB持久化。无持久化模式适用于对数据持久性要求不高但追求最高性能和响应速度的场景。 对于AOF持久化,可以根据需求配置不同的策略,如每个写操作都同步到磁盘(fsync),或根据时间或操作数来定期同步。同步频率的选择可以根据数据的重要性和系统的容忍度来平衡性能和数据安全性。 综上所述,选择适当的持久化机制需要综合考虑应用需求、性能要求和数据安全性,并进行相应的配置和调优。
Redis主从复制集群中配置哨兵能起到什么作用?
通过配置哨兵的主从复制,可以实现Redis集群的高可用性和故障转移能力,提高系统的稳定性和可靠性。
Redis 主从复制原理?(全量复制|增量复制)
主要步骤:假设我们有一个包含一个主节点(Master)和两个从节点(Slave1和Slave2)的Redis集群。下面是Redis主从复制的原理: 1. 配置主节点(Master):我们将其中一个节点配置为主节点,它负责接收写操作并广播数据变更。 2. 配置从节点(Slave):将其他节点配置为从节点,它们复制主节点的数据并提供读服务。 3. 初始连接:从节点通过发送SYNC命令与主节点建立连接。 4. 快照同步:主节点执行BGSAVE命令生成RDB文件(持久化快照),然后将该文件发送给从节点。从节点接收并加载RDB文件,将主节点的数据进行初始化。 5. 命令传播:当主节点接收到写命令时,它会将命令发送给所有从节点。从节点按照相同的顺序执行这些写命令,以保持数据的一致性。 6. 增量复制:主节点将自己执行的写命令及其数据变更发送给从节点。从节点根据接收到的命令进行数据更新。 7. 主从节点通信:主节点和从节点之间通过心跳机制保持连接,并定期交换信息以检测状态和同步数据。 8. 故障恢复:如果主节点发生故障或宕机,从节点会自动选举出一个新的主节点,并进行重新同步。 通过主从复制,Redis实现了数据的备份和读写分离。主节点负责处理写操作,而从节点提供读服务,从而减轻了主节点的压力,并提高了系统的可用性和性能。
Redis是单线程还是多线程?为什么能支持访问量和高并发?
单线程。
\1) 完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)
\2) 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗
\3) 使用多路I/O复用模型,非阻塞IO
你是如何理解redis是单线程,多路I/O复用?
在Redis中,单线程的含义是指Redis服务器在处理客户端请求时,使用单个线程逐个处理命令。这个单线程负责接收客户端连接、解析命令、执行命令和返回结果。因为只有一个线程在处理请求,所以不需要进行线程切换、上下文切换或锁竞争,避免了这些开销和潜在的并发问题。 Redis的多路I/O复用是指它利用操作系统提供的机制,同时监视和处理多个输入/输出通道(如网络套接字),以实现高并发的网络通信。 案例: 假设你是一个餐厅的服务员,你需要同时处理多个桌子上的点菜和结账请求。每个桌子都有不同的客人,他们需要你的服务。 在传统的方式中,你只能一次处理一个桌子的请求,即一次只能为一个桌子点菜或结账。 现在,为了提高效率,你采用了Redis多路I/O复用的方式来处理餐厅的请求。你站在一个中央服务台前,桌子上放置着多个点餐和结账设备。每个设备都连接到中央服务台的Redis服务器,并使用多路I/O复用技术进行管理。 当一个桌子需要点菜或结账时,服务员将其请求输入到相应的设备中,并将设备连接到Redis服务器。你可以同时处理多个桌子的请求,每个请求都在不同的设备上进行操作。 当一个桌子的请求处理完成后,设备会发送信号给Redis服务器,告知请求已经完成。Redis服务器收到信号后,将请求的结果返回给服务员,然后你可以继续处理其他桌子的请求。 通过这种多路I/O复用的方式,你能够高效地处理多个桌子的请求,而不需要一次只处理一个桌子。你可以同时处理多个桌子的点菜和结账,根据需要进行相应的操作。这样,你能够更快地为客人提供服务,提高了工作效率。
为什么尽管redis 是单线程的,但它仍然能够实现高性能和并发的处理能力?
这归功于以下几个因素: 1. 基于内存:Redis将数据存储在内存中,而内存的读写速度远高于磁盘和数据库的访问速度。通过避免磁盘I/O的开销,Redis能够实现非常高的吞吐量和低延迟。 2. 非阻塞I/O:Redis使用了多路I/O复用技术,如epoll、kqueue等,通过监听和处理多个网络连接,实现了非阻塞的I/O操作。这使得Redis能够同时处理多个客户端请求,支持高并发访问。 3. 单线程优化:Redis通过优化算法和数据结构,以及在内存中进行原子操作,最大程度地利用了单线程的优势。它避免了多线程带来的线程同步和资源竞争问题,简化了代码逻辑和维护成本。
说说Redis哈希槽的概念?
Redis集群没有使用一致性hash,而是引入了哈希槽的概念,Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。
Redis 淘汰机制? 满了才有淘汰!
- noeviction 不进行数据淘汰,也是Redis的默认配置。这时,当缓存被写满时,再有写请求进来,Redis不再提供服务,直接返回错误。 2.volatile-random 缓存满了之后,在设置了过期时间的键值对中进行随机删除。 3.volatile-ttl 缓存满了之后,会针对设置了过期时间的键值对中,根据过期时间的先后顺序进行删除,越早过期的越先被删除。 4.volatile-lru 缓存满了之后,针对设置了过期时间的键值对,采用LRU算法进行淘汰,不熟悉LRU的可以看这篇文章。 5.volatile-lfu 缓存满了之后,针对设置了过期时间的键值对,采用LFU的算法进行淘汰。 6.allkeys-random 缓存满了之后,从所有键值对中随机选择并删除数据。 7.allkeys-lru 缓存写满之后,使用LRU算法在所有的数据中进行筛选删除。 8.allkeys-lfu 缓存满了之后,使用LRU算法在所有的数据中进行筛选删除。 在日常使用过程中,主要根据你的数据要求来配置相应的策略,这里我给你三点建议。 1. 我们优先使用allkeys-lru 策略。这样,我们就可以借助LRU算法去淘汰那些不常用的数据,把最近最常用的放在缓存中,从而提高应用的性能。如果你的数据有明显的冷热区分,建议你使用allkeys-lru策略。 2. 如果你的数据的访问频率相差不大,也没有冷热之分,直接使用allkeys-random 策略,随机选择淘汰的数据就行。 3. 如果你的数据有置顶要求,比如置顶新闻等。那么我们就选择volatile-lru策略,同时不给置顶数据设置过期时间,这样一来,置顶的数据永远不会被删除,而其他设置了过期时间的数据,会更加LRU算法进行淘汰
Git专题
Git的分支管理是怎样的? 写出相关分支命令并做出解释
Git的分支管理是非常灵活的,每个分支可以独立开展工作,不同分支之间的内容可以合并。
创建分支:通过命令git branch
切换分支:通过命令git checkout
合并分支:通过命令git merge
删除分支:通过命令git branch -d
查看分支:通过命令git branch可以查看所有分支,当前分支会以特殊符号标识。
Git中的HEAD是什么? 谈谈你对HEAD的理解
HEAD是Git中的一个特殊指针,用来指向当前分支的最新提交。HEAD的指向可以通过切换分支或者执行提交操作来改变。 Git切换版本,底层其实是移动的HEAD指针。
Git中的暂存区(stage/index)是什么?
暂存区是Git中的一个重要概念,它是用来存放待提交的文件 的区域。当我们修改了工作区的文件后,可以通过命令git add
Git中如何撤销操作?你知道的有哪些?
撤销修改:通过命令git checkout –
Git中如何解决合并冲突?
合并冲突是在将分支内容合并时可能遇到的问题,可以通过以下步骤解决: 执行合并操作:通过命令git merge
什么是Git? Git的工作原理是什么?
Git是一个分布式版本控制系统,用于跟踪文件的更改并协调多人协作开发。
Git将代码仓库视为一个存储所有文件历史记录的快照数据库,每次提交会创建一个新的快照,并记录一个指向该快照的指针。Git使用哈希算法来生成每个提交的唯一标识。Git还使用分支来支持并行开发,每个分支都是指向提交的指针。
写出你所知道的Git的相关命令操作并做出解释(写出五个以上)
git init: 作用:将当前目录初始化为一个Git仓库。 解释:通过执行该命令,Git会在当前目录创建一个新的空的Git仓库,用于跟踪管理项目的版本。 git clone [url]: 作用:从远程仓库克隆代码到本地。 解释:该命令用于将远程仓库中的代码完整地复制到本地,创建一个本地的Git仓库副本,并与远程仓库保持同步。 git add [文件/目录]: 作用:将文件添加到Git的暂存区。 解释:执行该命令后,Git会将指定的文件或目录添加到暂存区,以便在后续的提交中包含它们。 git commit -m “提交信息”: 作用:提交暂存区中的文件到本地仓库。 解释:该命令用于将暂存区中的文件提交到本地仓库,同时可以附加一条提交信息,用于描述本次提交的内容。 git push: 作用:将本地仓库的代码推送到远程仓库。 解释:执行该命令后,Git会将本地仓库的代码推送到与之关联的远程仓库,以使得远程仓库与本地仓库保持同步。 git pull: 作用:从远程仓库拉取最新的代码到本地。 解释:该命令用于从与之关联的远程仓库拉取最新的代码,以使得本地仓库与远程仓库保持同步。 git branch: 作用:列出所有分支。 解释:执行该命令后,Git会返回当前仓库中存在的所有分支列表,并且会高亮显示当前所在的分支。 git checkout [分支名]: 作用:切换到指定的分支。 解释:该命令用于从当前分支切换到指定的分支,以便开始在该分支上进行开发或其他操作。 git merge [分支名]: 作用:合并指定分支到当前分支。 解释:执行该命令后,Git会将指定分支的代码合并到当前分支中,以便将两个分支的修改内容合并在一起。 git log: 作用:显示提交日志。 解释:执行该命令后,Git会返回当前分支的所有提交记录,包括每个提交的作者、日期、提交信息等详细信息。
Spring Boot专题
Spring Boot 特性有哪些
快速创建独立 Spring 应用
SSM:导包、写配置、启动运行
- 直接嵌入Tomcat、Jetty or Undertow(无需部署 war 包)【Servlet容器】
- - linux java tomcat mysql: war 放到 tomcat 的 webapps下
- jar: java环境; java -jar
- 重点:提供可选的starter,简化应用整合
- - 场景启动器(starter):web、json、邮件、oss(对象存储)、异步、定时任务、缓存…
- 导包一堆,控制好版本。
- 为每一种场景准备了一个依赖; web-starter。mybatis-starter
- 重点:按需自动配置 Spring 以及 第三方库
- - 如果这些场景我要使用(生效)。这个场景的所有配置都会自动配置好。
- 约定大于配置:每个场景都有很多默认配置。
- 自定义:配置文件中修改几项就可以
- 提供生产级特性:如 监控指标、健康检查、外部化配置等
- - 监控指标、健康检查(k8s)、外部化配置
- 无代码生成、无xml
你如何理解 Spring Boot 中的 Starters?
Starters可以理解为启动器,它包含了一系列可以集成到应用里面的依赖包,你可以一站式集成 Spring 及其他技术,而不需要到处找示例代码和依赖包。如你想使用 Spring JPA 访问数据库,只要加入 spring-boot-starter-data-jpa 启动器依赖就能使用了。
Starters包含了许多项目中需要用到的依赖,它们能快速持续的运行,都是一系列得到支持的管理传递性依赖。具体请看这篇文章《Spring Boot Starters启动器》。
Spring Boot 自动配置原理是什么?
1、导入starter,就会导入autoconfigure包。
2、autoconfigure 包里面 有一个文件 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports,里面指定的所有启动要加载的自动配置类
3、@EnableAutoConfiguration (内部@Import注解)会自动的把上面文件里面写的所有自动配置类都导入进来。xxxAutoConfiguration 是有条件注解进行按需加载
4、xxxAutoConfiguration给容器中导入一堆组件,组件都是从 xxxProperties中提取属性值
5、xxxProperties又是和配置文件进行了绑定
效果:导入starter、修改配置文件,就能修改底层行为。
Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?
启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了以下 3 个注解:
l @SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。
l @EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,
n 如关闭数据源自动配置功能: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })。
l @ComponentScan:Spring组件扫描。
Linux专题
写出Linux根目录下的6个常用目录及其作用
/bin 二进制可执行命令。该目录下存放着普通用户的命令
/dev 系统的设备文件,即设备的驱动程序
/home 存放用户文件的主目录,用户数据
/lib 存放着和系统运行相关的库文件
/mnt 存放临时的映射文件,通常是一些用来安装其他设备的子目录
/boot 存放启动linux的核心文件
/media 存放着可移除的设备,比如软盘,光盘
/proc 存放着用户与内核的交互信息
/sbin 系统的管理命令,这里存放的是系统管理员使用的程序
/srv 系统启动服务时可以访问的数据库目录
/tmp 临时文件,重启后自动清空
/var 存放系统产生的经常变化的文件
/etc 系统所有的配置文件都在这个目录中 (添加环境变量)
/opt (option : 自由选择)主要给源码安装软件时选择的安装目录位置
/root 超级用户的目录
/selinux 主要用来加固操作系统,提高系统的安全性
/sys 管理设备文件
/usr 最大的目录,存放着应用程序和文件
/lost-found 这个目录平时是空的,当系统非正常关机而留下的“无家可归”的文件便会储存
写出Linux常用命令(不少于5个)
一、服务类命令
(1)systemctl start 服务名 - 开启服务
(2)systemctl stop 服务名 - 关闭服务
(3)systemctl restart 服务名 - 重启服务
(4)systemctl status 服务名 - 查看服务
二、文件目录类指令
(1)pwd - 显示当前目录的绝对路径
(2)ls - 显示当前路径下的文件和目录
(3)cd - 切换至指定目录
(4)mkdir - 创建目录
(5)rmdir - 删除目录(空目录)
(6)touch - 创建空文件
(7)cp - 拷贝文件或目录到指定文件或目录
(8)rm - 删除文件或目录
(9)mv - 移动文件与目录或重命名
(10)cat - 查看文件内容
(11)more - 文本过滤器
(12)less - 分屏查看文件内容
(13)echo - 输出内容到控制台
(14)head - 显示文件开头部分
(15)tail - 显示文件尾部的部分
(16)> / » - 输出重定向/追加
(17)ln - 软链接
(18)history - 查看执行过的的历史命令
三、搜索查找类指令
(1)find - 查找文件
(2)locate - 定位文件路径
(3)which - 定位指令路径
(4)grep - 过滤查找
四、压缩解压类指令
(1)gzip - 压缩文件
(2)gunzip - 解压文件
(3)zip - 压缩文件或目录
(4)unzip - 解压文件或目录
(5)tar - 打包
VMWare三种工作模式
- bridged(桥接模式):VMWare虚拟出来的操作系统就像是局域网中的一台独立的主机,它可以访问网内任何一台机器。需要手工为虚拟系统配置IP地址、子网掩码,而且还要和宿主机器处于同一网段,这样虚拟系统才能和宿主机器进行通信。
- NAT(网络地址转换模式):让虚拟系统借助NAT(网络地址转换)功能,通过宿主机器所在的网络来访问公网。虚拟系统无法和本局域网中的其他真实主机进行通讯。
- host-only(主机模式):所有的虚拟系统是可以相互通信的,但虚拟系统和真实的网络是被隔离开的。虚拟系统和宿主机器系统是可以相互通信的。如果想利用VMWare创建一个与网内其他机器相隔离的虚拟系统,进行某些特殊的网络调试工作,可选择host-only模式。