1.#{}和${}的区别
#{}是预编译处理,mybatis在处理#{}的时候会将其换成?,安全性会比较高;${}是占位符,只是进行替换,容易造成sql注入
2.如何解决spring的循环依赖
可以使用三级缓存,如果是A和B创建对象的时候互相依赖,我们在初始化A的时候可以将半成品A提前放到三级缓存中,创建B的时候,可以使用这个半成品,此时B就是一个成品对象;再回来接着创建A对象,这样循环依赖就被打破
3.springboot的启动流程
4.spring的aop的应用
5.mybatis处理一对多的结果
一对一的情况collection标签换成association标签,property写实体类中起的名称,JavaType是实体类的具体类型
一下展示的是一对多
xml语句的返回结果使用resultMap
“一”中的主键:id
其他列:result
使用collection标签进行包裹(多的列)【标签中:property是返回结果类中的结果集属性名,ofType】
property标签 实体类中的属性名
column标签 数据库的列明
6.sql语句处理
如何将一对多,多的那列用逗号进行拼接
7.mysql的事务隔离级别
读未提交
读已提交
可重复度【默认】
串行化
8.mysql的索引
普通索引:和没有索引是一样的
唯一索引:不能重复,可以为空
主键索引:不能重复,不能为空
组合索引:【遵循最左前缀集合】
全文索引:只有在MyISAM引擎上使用,只能用在char、varchar、text字段上
空间索引:对空间类型的数据字段创建索引
9.乐观锁和悲观锁
乐观锁,认为是任何情况下都是最好的情况,共享资源被访问无需加锁也无需等待,只是在数据提交的时候验证一下版本
悲观锁:任何情况下都做最坏的打算,认为共享资源被访问会出现问题,就会加锁,其他线程会被阻塞
如何实现乐观锁:
在数据库中加上一列version字段,每次进行修改操作version值都会加1,例如线程a想要修改数据,在读取数据的同时读取version字段,提交数据的时候读取version字段,如果两次都相同,更新成功
CAS算法三个操作数:更新的变量值,预期值,新值
CAS的全程是比较与交换,是原子操作
10.mysql锁
全局锁:使用了这个锁,整个数据库处于只读状态
表锁:加锁快,不会产生死锁,支持innodb和myisam,加锁快,开销小,并发度低
行锁:粒度最小的锁,加锁慢,开销大,会产生死锁
分为共享锁和排它锁
12.mysql事务的特点
原子性
一致性
持久性
隔离性
13.reentrantLock和synthronized的区别
reentrantLock是lock类,synthronized是java关键字
reentrantLock需要手动释放锁,synthronized自动释放锁
reentrantLock可以实现非公平锁和公平锁,synthronized是非公平锁
reentrantLock可以响应中断,synthronized不能响应中断
14.Linux删除文件的命令、创建文件、创建目录、删除目录、移动文件、复制文件的命令
15.创建线程的两种方式
继承thread类,重写run方法
实现runnable接口,重写run方法
16.冒泡排序
外层循环控制循环的轮数
内层循环控制每轮比较的次数
for(int i = 0;i<a.length - 1;i++)
for(int j = 0;j < a.length - 1 - i ;j++)
17.mybatis的一级缓存和二级缓存
Mybatis的一级缓存是SqlSession级别的,在创建语句的时候需要构造SQLSession对象;在同一个SQLSession中,两次执行同一个语句,第一次查询之后会将结果存到缓存中,第二次查询的时候直接从缓存中取出,就不需要查询数据库了。当一个SQLSession结束之后,SQLSession中的一级缓存也就不复存在
二级缓存是mapper级别的,多个SQLSession去操作同一个mapper中的sql语句,多个SQLSession去查询数据库将结果存到二级缓存,多个SQLSession是可以共用二级缓存的额
18.jdk1.7和jdk1.8的区别
jdk1.8使用lamdba表达式
jdk1.8switch可以定义string类型
jdk1.8接口中可以定义默认和静态方法
try-catch-resource
catch 可以处理多个异常
函数式接口
支持多重注解
19.get请求和post请求
get使用url编码,post支持多种编码方式
post请求比get请求更安全,get请求将数据暴露在url上
get请求通过url传递,post是放在requestbody中传递
20.@RequestBody和@RequestParam适用场景
@RequestBody 适用于接收 POST 请求中的请求体中的数据,而 @RequestParam 适用于接收 HTTP 请求中的 URL 中的参数。
21.mybatisplus怎么使用
mapper层要继承basemapper
service层要继承IService类
serviceimp层要继承ServiceImpl类,实现service接口
后续就可以直接使用mybatis plus中的方法
22.sql语句的执行顺序
from表
on关联
where条件
group by
having
select字段
order by
limit
23.接口和抽象类
接口和抽象类都不能实例化对象
接口使用interface关键字,抽象类使用abstract
接口多实现implement,类是单继承extends
接口中可以有抽象方法和静态方法;抽象类中有抽象方法和普通方法
接口中不能有构造方法,抽象类中可以有构造方法
接口默认是public修饰;抽象类可以被private和protected修饰
接口中的变量默认都是被final修饰的,抽象类变量是可以声明为非final
24.抽象类和普通类
两者都可被继承
抽象类不可以实例化对象,普通类可以实例化对象
抽象类被继承,如果子类实现抽象方法就不是抽象类,反之则继续抽象下去
抽象类不能被final修饰,普通类可以
抽象方法不能被static和final修饰
25.jvm内存模型
程序计数器【私有】:用来选取下一条需要执行的字节码指令
虚拟机栈【私有】:声明周期和线程相同;和线程一起创建,当创建一个线程的时候,就会为该线程申请一个虚拟机栈,用来存储局部变量等信息。每一个方法的调用都是入栈操作,每个方法的返回都是出栈操作
本地方法栈【私有】:和虚拟机栈类似,他是用来管来本地方法的调用
堆【共享】:是jvm内存中最大的一块区域,几乎所有的数组和对象都被分配到堆内存中。堆分为老年代和新生代
【java6中永久代在非堆内存中,java7永久代的静态变量和运行时常量池合并到堆内存中;java8中永久代被元空间取代】
方法区【共享】:用来存储相关的类信息;包含类信息、字符串常量池和运行时常量池
26.抽象类和抽象方法
27.mysql的三大日志:binlog【二进制文件】、redolog【事务重做日志】、undolog【回滚日志】
redolog是物理日志,如果mysql挂了,innodb引擎会使用redolog日志进行数据的恢复
会将每个页面做了什么记录到重做日志缓存中【redolog buffer】,之后再更新到redo log 中
binlog是逻辑日志,记录的内容是语句的原始逻辑,不管用什么存储引擎,只要表数据更新,都会产生binlog日志,binlog主要是用来同步数据【数据备份、主主、主从】
redolog事务执行的时候不断写入,binlog是事务提交的时候才会写入
所有事务的修改都会记录到undolog日志中
28.mysql数据库和orcal数据库的区别
mysql中小型,oracle是大型
mysql免费,oracle收费
mysql是关系型数据库,oracle是对象关系数据库
mysql在Windows系统下大小写不敏感,oracle大小写敏感
oracle可以设置用户权限、访问权限、读写权限,mysql不可以
mysql可以自动提交,oracle需要手动提交
oracle有表空间,mysql没有
29.MyISAM和InnoDB引擎
mysql5.5.5之前默认的引擎是MyISAM,5.5.5之后默认引擎是InnoDB
存储引擎是基于数据表,而不是数据库
两者的区别:
1.MyISAM只支持表级锁,InnoDB支持表级锁和行级锁,默认是行级锁
2.MyISAM不支持事务,InnoDB支持事务
3.MyISAM性能低于InnoDB
4.MyISAM不支持MVCC【多版本并发控制】,InnoDB支持
5.MyISAM不支持外键,InnoDB支持
30.InnoDB存储引擎对MVCC的实现
【MVCC是innodb为提高数据库的并发性能,更好的处理读-写冲突】
一致性非锁定读:如果在读取的时候正在执行delete或者update操作,就不会读,innodb会去读取行的一个快照数据。对于这种读取历史数据的方式,我们称之为快照读【不加锁的非阻塞读,每次读取的不一定是最新数据】
快照读的前提是隔离级别不能是串行级别
锁定读:每次读取的都是最新的数据,称之为当前读【加读锁或者写锁;读锁可以共享,写锁排他】悲观锁的实现
MVCC就是为了解决读写冲突,使用事务id或者时间戳标记当前数据库的状态,读取这个版本的数据,实现读写分离。读写并存的时候,写操作会根据数据库的状态创建一个新的数据库版本,并发度依旧读取数据库的旧版本
30.redis可以做缓存,还可以实现分布式锁
redis的高并发、高性能
redis的分布式锁,多个线程不在同一个JVM进程中,不能使用本地锁,进而可以使用分布式锁来实现共享资源的互斥
31.redis的基本数据类型
string set zset hash list
Redis 还支持 3 种特殊的数据结构 :Bitmap、HyperLogLog、GEO
set用于存放数据不能重复的场景,例如文章点赞、动态点赞;随机获取数据源的【抽奖、随机点名】
购物车信息使用hash存储
使用redis实现一个排行榜,使用zset数据类型
32.redis持久化机制
需要对内存中的数据进行持久化也就是将内存的数据写入硬盘,方面后面数据的重用或者做数据同步
持久化的方式:
快照RDB
只追加文件AOF
RDB和AOF混合持久化(redis4.0新增)
RDB是通过创建快照的方式获得内存中数据在某个时间点上的副本。redis创建快照之后,可以对快照进行备份,可以将快照复制到其他服务器从而创建具有相同数据的服务器副本【redis的主从结构,主要用来提高redis的性能】,还可以将快照留在原地以便重启服务器的时候使用,快照持久化是redis默认的持久化方式。
AOF:redis默认没有开启AOF,开启之后每执行一条会更改redis中数据的命令,redis就会将该命令写入缓冲区,之后再写入AOF文件中,最后在根据持久化方式的配置来决定何时将系统内核缓存区的数据同步到磁盘中。
AOF的工作流程
命令追加
文件写入
文件同步
文件重写
重新加载
33.redis问什么使用单线程
多线程容易产生死锁
redis的性能不在CPU,而在内存和网络
单线程更容易维护
redis6.0之后引入多线程
为了提高网络的IO读写性能
34.三种常用的缓存读写策略
【旁路缓存模式】
写:先更新数据库,再删除缓存
读:先读取缓存,读取到就直接返回,读取不到就去数据库中读取,并将数据放到缓存
【读写穿透】
缓存负责数据读取和写入数据库
写:先查缓存,缓存不存在,直接更新数据库;缓存存在,先更新缓存,然后缓存服务自己更新db(两者值同步更新的)
读:从缓存中读取到直接返回;读取不到先从db加载,写入cache中返回相应
【异步缓存写入】
只是更新缓存,不直接更新数据库,而是改为异步批量的方式来更新数据库
35.http和https
http是超文本传输协议,
https是超文本安全传输协议,进行加密了,更加安全
36.tcp和udp
tcp是面向连接的,udp不是
tcp可靠,udp不可靠
tcp传输快,udp慢
tcp适合传输大量,udp适合少量
37.tcp/ip协议的三次握手和四次挥手
38.垃圾回收算法
标记-清除
标记-整理
拷贝
39.七层结构
物理层
数子链路层
网络层
传输层
会话层
表示层
应用层
http在应用层
tcp udp在传输层
39.@Autowied自动注入
@Autowired按照类型装配
@Resource按照名称装配,按照名称找不到,就按照类型装配
@Qulifier自动按照类型进行注入的基础上,再按照bean的id注入;它不能独立使用,需要配合@Autowied来使用,value属性用于指定bean的id
40.SpringBoot的核心注解
启动类注解@SpringBootApplication
@Mapper @Service @Repository @Controller
@RequestBody @RequestParam
@Configuration
@RestController
@Service与@Controller属于Spring框架的注解,注解在类上,需要被扫描才能创建实例化对象,并将对象放到Spring容器中。
@Mapper注解是Mybatis框架的注解,使用这个注解我们的接口就可以被Mybatis框架加载,然后动态代理生成实体类,然后就将实体类放到了spring容器中。
40.AQS详解
aqs是抽象队列同步器
AQS 核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制 AQS 是基于 CLH 锁 (Craig, Landin, and Hagersten locks) 实现的。
CLH 锁是对自旋锁的一种改进,是一个虚拟的双向队列(虚拟的双向队列即不存在队列实例,仅存在结点之间的关联关系),暂时获取不到锁的线程将被加入到该队列中。AQS 将每条请求共享资源的线程封装成一个 CLH 队列锁的一个结点(Node)来实现锁的分配。在 CLH 队列锁中,一个节点表示一个线程,它保存着线程的引用(thread)、 当前节点在队列中的状态(waitStatus)、前驱节点(prev)、后继节点(next)。
41.线程池的七大参数
(1)corePoolSize:线程池中常驻核心线程数
(2)maximumPoolSize:线程池能够容纳同时执行的最大线程数
(3)keepAliveTime:多余的空闲线程存活时间
(4)unit:keepAliveTime的时间单位
(5)workQueue:任务队列,被提交但尚未执行的任务
(6)threadFactory:表示生成线程池中的工作线程的线程工厂
(7)handler:拒绝策略,表示当队列满了并且工作线程大于等于线程池的最大线程数(maximumPoolSize)时如何拒绝。
42.socket和websocket的区别
1.概念
socket:翻译为套接字,是应用层和传输层之间的抽象层,将TCP/IP复杂的操作抽象整成几个简单的接口,供应用层调用以实现进程网络间的通信
websocket:是基于TCP的一种新的网络协议,它和http一样都属于应用层协议,是一种能让客户端和服务器实现双向实时通信的技术
2.区别
1.socket属于传输控制层协议,websocket属于应用层协议
socket将复杂的tcp/ip协议族隐藏在socket接口后面,利用tcp/ip协议与tcp建立连接
2.websocket更易用,而socket更灵活
3.传输层次不同
socket是传输控制层的接口,用户可以通过tcp/ip与tcp进行通信
websocket是一种在单个tcp连接上进行全双工通信的协议
43.springboot的启动流程
1.首先从main找到run()方法,在执行run()方法之前new一个SpringApplication对象2.进入run()方法,创建应用监听器SpringApplicationRunListeners开始监听3.然后加载SpringBoot配置环境(ConfigurableEnvironment),然后把配置环境(Environment)加入监听对象中4.然后加载应用上下文(ConfigurableApplicationContext),当做run方法的返回对象5.最后创建Spring容器,refreshContext(context),实现starter自动化配置和bean的实例化等工作。
44.RocketMQ特点:
应用解耦,各个系统之间耦合度低,容错性高
例如:微服务中多个系统需要相互调用,如果耦合度高的话,其中一个系统挂了,剩下的系统都会受影响
流量削峰:例如秒杀
数据分发:将数据分发的任务交给mq,让mq进行数据分发
缺点:
系统的可用性降低:使用mq存储消息,如果 mq挂了,就会对业务造成影响
系统复杂度提高:之前是同步远程调用,现在是使用mq进行异步调用。怎么样保证消息不会重复消费、处理消息丢失问题、保证消息传递的顺序性
一致性问题:消息处理失败怎么办