本博客是本人纯手打然后去网上百度的图片,转发请注明出处
按照自己的理解适合给初级程序员找工作用的

顺便给自己回顾一下,都是按照自己的理解来写的,有的地方不通顺或者不理解可以问我,有写不对的地方或者不同的见解可以写在下方

java基础

java

jdk,JRE,JVM 区别?关系?

jdk是java程序开发的工具包,开发环境
jre是java程序运行时所需的运行环境
jvm是虚拟机,包含类解释器和类加载器等等
jdk包含jre,jre包含jvm

== 和 equals 的区别是什么?

==是比较的引用地址,来判断是否相等
equals是比较值中的数据来判断是否相等

谈谈面向对象

 1·面向对象我的理解就是将所有的事务都看作一个对象,那么一个对象就有他的属性和行为,在java编程中就是将一个事务抽取出他的属性与方法成为我们所定义的一个类,通过new 实例来调用对象,避免重复造轮子2·面向对象的三大特性封装:将属性给私有化,公开对属性的访问方法,就是将实现的细节给隐藏了继承在以及有的类上去在派生出一个新的类,这个新的类继承了原有的类的所有公开的属性和方法多态就是同一个引用对象指向了不一样的实例,然后指向同样的方法,但是最后的结果不一样,这就是多态性

final finally 和 finalize的区别

final定义在类或者属性或者方法上定义类:该类不能被继承定义属性:该属性为常量,常量注意(基本数据类型不能被改变,对象是可以改变对象里面的东西,但是不能
改变所指向的这个对象)定义方法:该方法不能被重写
finally是和try catch 一起使用的不管try代码块中是否出现异常,finally代码块中的代码都会去执行
finalize是ojbect的方法,是gc判断是否能回收的最后判断

String 类常用的方法

equals()
indexof();
length();
trim();
subsring();
等...

基本的数据类型以及占用字节

整型:byte 1 ,shor 2,int 4,lang 8
浮点型: float 4, double 8
字符:char 2
boolean:1 bit
bit与字节 1/8 比如byte就是1个字节 8个bit

基本数据类型的封装类

String、StringBuffet、StringBuder 区别

*String*是用来定义字符串的,但是String不能改变字符串的值,只能去改
变在内存中的地址,这个时候如果业务需求需要对一个字符串经常性的
进行修改那么我们就可以选择使用*StringBuder 或StringBuffet*,可以使用
‘+’进行字符串的连接或者append方法进行字符串的追加,那么如果业务
中需要考虑到*线程安全我们可以选择StringBuffet*,如果不考虑线程问题
我们就可以选择StringBuder,效率会更高

重载与重写的区别?

方法的重载是在本类当中进行的,方法要同名,参数不一致,和访问修饰符返回值无关
方发的重写是在子类或实现类中进行的,方法同名,参数一致,访问修饰符不能比父类的小,返回值要和父类一样或是其子类

四种引用类型

 强引用:java中默认的就是强引用,比如User user=new User();只要user指向这个new User();的实例就不会
被gc回收,如果想要jvm进行回收可以选择将user=null软引用:只会在内存不够的时候进行回收,如果回收完还是内存不够则会抛出异常,一般用来实现缓存技术弱引用:只要jvm进行垃圾回收的时候就会回收虚引用:随时都可能被回收

jvm内存模型

其实就是堆、栈、方法区
堆中存放new的实例或则数组,可以被线程共享
栈中存放的引用对象,就是new对象等于的前面那一块
方法区用于存储已经被虚拟机加载的类信息,常量,静态变量等,可以被线程共享

类加载过程,双亲委托机制

jvm将类加载分为3步
1、装载:查找并加载二进制数据
2、链接:

  • 验证:为了确保加载的类正确
  • 准备:为类的静态变量分配内存,并初始化默认值
  • 解析:把类中的符号引用转换为直接引用

3、初始化:为类的静态变量赋予初始化值


其实就是优先从缓存中去看有没有这个要加载的类,如果没有则向上让上级去找,找到了就向下去加载类,作用就是为了保护java的类不会被应用程序覆盖,比如你自己写了个java.lang.String的类如果没有双亲委托岂不是就把java中的String给覆盖了

集合

Collection和Map的关系

依赖关系
Collection常用子接口1、List实现类:ArrayList、Vector、LinkedList2、Set实现类:HashSet
Map的常用实现类1、HashMap2、Hashtable(t是小写)

List Set Map的区别

List 值不唯一,有序,可以插入多个null值
Set 值唯一,无需,只能插入一个null值
Map 键值对的存储方式,映射关系可以一对一或多对一List  有基于数组、链表实现两种方式
Set与Map 基于哈希存储和红黑树两种方式实现

ArrayList与LinkedList、HashMap区别

ArrayList:使用动态数组的存储方式,所以检索速度快初始容量是10,通过rosize()进行扩容,扩容1.5倍新增时容量不够则进行扩容LinkedList:使用的是双向链表的存储方式,所以插入数据删除数据更快双向链表就一直在头和尾插入、删除,所以没有初始化大小,也没有扩容的机制
HashMap:数组+链表的去实现的,可以存储null键与null值,键唯一初始容量是16,在0.75的时候扩容,扩容的是2倍,比如集合容量到了12的时候进行扩容,那么容量就是32

HashMap与Hashtable的区别?

HashMap:键值可以为null,键唯一,线程不安全初始容量是16,在0.75的时候扩容,扩容的是2倍,比如集合容量到了12的时候进行扩容,那么容量就是32Hashtable:键值不能为null,键唯一,线程安全初始容量为11

谈谈ConcurrentHashMap?

前面说到HashMap线程不安全,Hashtable线程安全,那么为什么我们还要
一个ConcurrentHashMap呢?因为ConcurrentHashMap融合了hashtable和hashmap二者的优势ConcurrentHashMap与Hashtable同样都是线程安全,应对并发场景
的,那么ConcurrentHashMap的好处在哪里呢?(别的博主那截图的)Hashtable是直接将这整合集合加锁,当有一个线程去访问hashtable的集
合的时候其他线程要等到访问的这个的线程出来后才能访问ConcurrentHashMap是将数据一段一段的去加锁,ConcurrentHashMap
存储方式就是将数据一段一段往内存中存储,然后每一段都加上锁在jdk1.8之前使用没有红黑树,所有的集合都是一样的,在jdk1.8之后
ConcurrentHashMap上锁的方式改变成了synchronized

迭代器Iterator

 就是一个对集合进行遍历访问的,可以通过集合对象.Iterator()方法获
得到迭代器对象进行使用 hasNext判断是否还有下一个元素,如果有则返回true,通过next()获
得元素

迭代器ListIterator

 ListIterato继承Iterator只能去遍历List集合,可以进行向前或向后(正序或倒序),Iterator只能向前进行遍历,ListIterator可以在遍历的时候对集合元素进行增加删除操作

Collections 和 Arrays?

 Collections:是工具类,可以对集合进行搜索、排序、Arrays:工具类 ,对数组进行排序,比较

poll()方法和 remove()方法的区别?

都是从队列中取出元素,如果集合没用元素的化remove()方法抛出异常,
poll方法则会返回null

打印数组

通过Arrays.toString()String[] jayArray = {"jay", "boy"};System.out.println(Arrays.toString(jayArray));

HashMap 的扩容过程

    将数组扩容到原来的俩倍,然后将旧数组的元素重新计算hash再插入到新扩容的数组中

ArrayList 和 Vector 的区别是什么?

    Vector 线程安全的ArrayList 线程不安全Vector只要是关键性的操作,方法前面都加了synchronized关键字,来保证线程的安全性。

如何决定使用 HashMap 还是TreeMap?

看集合是否需要排序,需要排序可以使用TreeMap

HashMap是怎么解决哈希冲突的

Hashmap解决hash冲突,使用的是链地址法,即数组+链表的形式来解决。
put执行先判断table[i]位置,如果为空就直接插入,不为空判断和当前值是
否相等,相等就盖,如果不相等的话,判断是否是红黑树节点,如果不是,
就从table[i]位置开始遍历链表,相等覆盖,不相等插入。

IO

java中有几种类型的流?

字符流和字节流
字节流继承inputStreamOutputStream
字符流继承自InputSteamReaderOutputStreamWriter

字符流和字节流有什么区别?

字面意思以字节或字符输入输出,但是字符也可以用字节输出,
要转,使用byBytes(),貌似是这个,忘记了

网络通信

TCP和UDP有什么区别?TCP为什么是三次握手不是俩次?

TCP 是面向连接的可靠的传输层的通信协议,好比是打电话,可靠,点对点的通信,效率低,占用资源多
UDP就是无连接不可靠的传输层通信协议,好比是广播,不需要连接,发送方不管接收方有没有准备就直接发送,不可靠,效率高,占用的资源少

BIO,NIO,AIO

BIO:同步阻塞 ,读写必须阻塞在一个线程内等待完成,可靠性查,吞吐量低,适用于连接少且固定的场景,jdk1.4版本前唯一的选择

NIO:同步非阻塞,线程不断轮询看IO的状态,根据状态来进行下一步操作,可靠性和吞吐量高,适用于连接比较多的场景,比如聊天室,jdk1.4开始执行

AIO:异步非阻塞,就是为了解决异步IO,基于回调机制,可靠性和吞吐量高,适用于连接比较多,且连接比较长,比如相册服务器,jdk1.7版本才支持

NIO的核心组件什么?分别的作用

Channel Buffer Selector

channel每一个channel对应一个buffer缓冲区,channel会注册到selector。
selector会根据channel上发生的读写时间,将请求交给某个空闲的线程处理,selector对应一个或多给线程。
Buffer和Channel都是可读写的。

session和cookie的区别?

cookie因为是存储在客户端的所以可以被客户端禁用,session是存储在服务端的所以无法禁用,session可以存储任意类型,cookie只能存String,一般我们用session的session去配合存储cookie

HTTP和HTTPS的区别?

HTTP:是互联网上应用最广泛的通信协议,基于TCP,可以使用游览器工作更高效,减少网络传输
HTTPS:是HTTP的加强版,在HTTP的基础山增加安全机制,保证数据传输的安全,另一方面对访问者增加了验证机制
主要区别:
1、HTTP的连接是无状态的,HTTPS的数据传输时经过证书加密的,安全性更高
2、HTTP免费,HTTPS需要申请证书,而证书要收费的
3、端口不同,http80,https时443

线程

博主谈线程

初学者可能只是会用线程,但是并不知道在实际项目中应该怎么去用
博主在这里给你们打俩个比方:1、此时博主项目用到poi来将查询出来的数据以Excel表格导出,
那么如果是单线程,且下载一份需要5秒钟的情况,那么我一个用
户下载,另一个用户需要等上一个用户下载完,那如果5个人下载
就需要25秒,但是我创建线程,让线程去下载呢?那就是一个人
一个下载一个线程,是不是大大缩短了时间2、再来比如是查询数据,数据量比较大,要用到6张表,那么我
门也创建线程去执行,一个线程分3张是不是也好很多可以理解为孙悟空一个人打小妖精,一棍一个太慢了,多分几个身
一起打是不是快很多

什么是线程?

线程就是一个程序的最小执行单位,还要想更细一点看上面博主谈线程

线程和进程有什么区别?

线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的
任务。

如何在Java中实现线程?

其实就是问线程的创建方式1、继承Thread 类2、实现Runnable

用Runnable还是Thread?

众所周知java当中只能继承一次,可以实现多个接口,当然是实现
Runnable好一点

Thread 类中的start() 和 run() 方法有什么区别?

start()方法才是真正的创建了一个线程,如果不是start()方法调用到的
run()方法那么run方法就是一个很普通的方法,是没有新的线程的

线程如果问了肯定会问生命周期

线程的启动状态,就是前面说的start()方法的时候启动
就绪状态,就是start()方法执行到run()方法的时候
阻塞状态,阻塞状态里面有休眠,等待,挂起,阻塞
死亡状态,线程执行完就进入了死亡状态

刚刚说到阻塞状态的四个状态,那就肯定会问这几个方法 sleep(),wait(),join(),yield()

首先肯定是sleep()方法和wait()方法的区别
sleep()方法是将线程休眠,Thread类中的静态方法,不会释放锁
wait()方法是将线程等待,Object中的方法,会释放锁
因为这个释放锁的原因所有导致sleep()可以写在任何代码块中,而wait()方法只能定义在同步代码块中
调用wait()方法的线程会进入到等待池中,等待池中的线程不会去抢夺同
步锁,只有调用notify()或notifyAll()方法才会去抢夺线程,这俩个方法看
方法名应该不用多说了吧
join()方法调用的线程执行完了其他线程才执行,理解为谁调用谁老大
yield()方法调用的线程进入阻塞状态,会释放CPU的执行权,然后包括调
用的线程在内所有的线程重新抢夺CPU的资源

线程安全的理解?

java当中线程安全的定义是对象级别的,所以个人的理解是多个线程同时
操作同一个对象,我们不进行同步控制协同等操作这个对象最后的结果还
是正确的结果我就认为这个线程是安全的,那么如果不是线程安全的我们
怎么去处理呢?我们可以加锁,或者使用线程安全的对象,比如Hashtable等...

Lock接口和synchronized内置锁

synchronized主要确保线程互斥同步代码,保证线程共性变量被修改,其
它线程可以及时可见,解决重排序的问题
原理:加入了指令监视器锁,判断是0还是1来看线程的占有情况lock是一个类,通过lock()方法开启锁,通过unlock()关闭锁
还有tryLock()获取锁的时候如果有占用就返回false,没有占用就返回true
作用范围是代码块俩者的区别:synchronized不会主动释放锁Lock锁可以主动释放锁,想在哪里释放就在哪里释放synchronized就像是悲观锁,感觉自己什么时候都会被别的线程给抢走资源,所以就一直锁着自己Lock锁是乐观锁的一种,通过volatile和CAS操作实现

Threadlocal的原理和使用场景?

 使用Threadlocal创建的变量一个线程访问了,其他线程则无法访问和
修改,每一个线程的Threadlocal的值都不一样,这就是Threadlocal的作
用是一个泛型类,保证可以接受任何类型的对象,因为是弱引用的题
,所以在下一次垃圾回收的时候会被清理使用场景:每个线程都要有自己的一个单独的实例的时候,单又要被
被多个线程所访问的时候使用

串行,并行,并发的区别?

串行:一个大任务被拆分成了多给小任务,但是这些小任务只能一个一个
有顺序的完成
并行:相当于多个小任务要同时完成
并发:某一个时间段多个小任务一起执行,但是不是要一起完成,比如a
任务阻塞了,那么在这阻塞的期间可以操作b任务

并发的三大特性?

原子性:要么全部执行,要么都不执行
可见性:当一个线程修改共享变量的值后对其他线程可见
有序性:任务的执行按先后顺序完成

Volatile

博主所知道的就是防止指令重排,在单例模式中的饿汉式用过,防止类加载的指令重排
还有就是保证不同线程对该变量内存可见

谈对AQS的理解,如何实现重入锁

1、AQC是java线程同步框架
2、AQS中其实就是一个线程队列和一个state,线程队列就是用来给线程排队的,而state就像是一个红绿灯,来控制线程队列中的线程是否放行
3、可重入锁就是用state来表示加锁次数,0表示无锁,没加一次state就加1,释放就-1

java线程锁机制,偏向锁,轻量锁,重量级锁有什么区别?

1、java的锁就是在Markword中记录的锁状态,偏向锁,轻量锁重量锁对应不同的锁状态
2、java的锁机制就是根据抢夺资源的线程的多少来升级的过程,比如:
一个偏向锁就是相当于给资源设置了一个门,一个线程进入后其他线程就进不去,然后等进入的线程出来以后才呢进入
如果线程一多,有一个线程进入了资源后其他线程就会自旋,这个也叫轻量级锁
如果线程再多了,jvm不可能把性能都用来给线程自旋,jvm就会把这个情况直接给操作系统,然后操作系统会让线程排队进入
总结:重量锁效率低,轻量锁性能低

为什么使用线程池?

所有的什么什么池都是一样的原因,都是为了降低消耗,提高利用
率,这个线程池就是创建了线程池后用线程池中的线程去执行任务
对线程统一管理,统一分配资源

java中线程池创建的几种方式

     1、创建使用单个线程的线程池ExecutorService es1 = Executors.newSingleThreadExecutor();2、创建使用固定线程数的线程池ExecutorService es2 = Executors.newFixedThreadPool(3);3、创建一个会根据需要创建新线程的线程池ExecutorService es3 = Executors.newCachedThreadPool();3、创建拥有固定线程数量的定时线程任务的线程池ScheduledExecutorService es4 =Executors.newScheduledThreadPool(2);4、  //创建只有一个线程的定时线程任务的线程池ScheduledExecutorService es5 = Executors.newSingleThreadScheduledExecutor();

线程池处理流程

1、判断核心线程数是否已经满了,如果没满则创建核心线程去执行任务,满了则进入第二步
2、判断任务队列是否满了,如果没满则把任务加到队列中等待执行,满了进入第三步
3、判断最大线程数,如果没满则创建临时线程去执行,临时线程完全闲下来了就会被回收
4、如果都满了则需要使用拒绝策略

创建线程池参数

1、核心线程数
2、最大线程数
3、线程空闲的存货时间
4、存放待执行的任务
5、拒绝策略

什么是死锁?解决死锁的方式

死锁:多个线程同时访问某一个资源都阻塞了,由于循环依赖导致彼此一
直处于等待之中,没有任何线程可以继续前进就死锁了
死锁的解决方法就是上锁,无法获得线程执行的时候就重复去获取或者退出

Web基础面试

servlet的生命周期

就是初始状态和服务状态,服务状态就是调用servlet()的时候,然后就是
关闭servlet()被回收的时候执行

get和post请求的区别?

get请求会将传递的请求信息会在地址栏上显示,然后传递的信息有限
只能传递4到5kb
post请求就不会将请求信息显示,传递的信息没有限制,所以我们一般
上传文件上传图片都是用post请求

转发和重定向的区别

转发请求一次,地址栏不改变
重定向请求俩次,地址栏会改变,可以重定向到项目外的其他项目去

jsp和servlet的区别

如果在用jsp报错的时候自己细心解决找过问题出在哪一行的小伙伴应该
已经知道了,jsp本质就是servlet,出现bug的时候提示哪一行报错如果
找的话找到的式jsp被编译成.java文件,里面是使用一个那个什么waite去
输出成一个页面的,我大概打了一个英文,小伙伴们感兴趣可以百度去看

讲解JSP中的四种作用域

page是代表一个页面相关的对象和属性
request是代表与web客户机发出的一个请求相关的对象和属性
session是代表与用于某个web客户机的一个用户体验相关的对象和属性
application是代表与整个web应用程序相关的对象和属

这个servlet就到这吧,我感觉也不会这么问这个,如果面试公司用这个就赶紧走吧,除非是保险或银行工资开的高,根本学不到技术,只能学逻辑

MySQL数据

数据库

数据库将数据永久保存在内存中,使用SQL语句,查询方便效率高。管理数据方便

事务的ACID

原子性:一个事务是一个不可分割的操作单位;保证原子性是通过undo log来回滚日志保证的
一致性:就是事务更改完数据后的数据要一致,不能每个事务看到同一个东西事务不一样
隔离性:就是多个事务之间的数据不会受到其他事务的干扰;由MVCC主从来保持数据一致
持久性:就是事务执行完后的数据要永久保存;通过redo log来记录操作,如果宕机了还能从redo log中恢复数据

MVCC

MVCC是多版本并发控制,不冲突读写,不同的事务看到i自己的版本数据和版本锁
MVCC只有在rr与rc隔离级别中工作

数据库三大范式是什么

第一范式:每个列都不可以再拆分
第二范式:非主键的列只依赖这个表的一个主键
第三范式:表中的数据都不能再分,比如一个表有学生姓名,教员名称,
所学科目,成绩,那么我们可以将教员和科目拿出来成为一张表然后只
要对学生成绩表提供一个id

MySQL存储引擎MyISAM与InnoDB区别

Innodb支持事务,并且提供锁和外键约束
MyIASM不支持事务锁和外键

索引

什么是索引?

索引就好像字典里面的那个按偏旁和拼音查字查不到,便于我们快速的查
找数据库表中的数据

索引的数据结构?

使用B+树的数据结构,一个节点去存储多个key,然后进行折半查找去查找下一个节点,大大的提高了我们的效率,在叶节点中存储data与key

索引使用场景

首先是经常需要出现在where后的列就可以加索引

mysql聚簇索引与非聚簇索引的区别

1、聚簇索引其实就是数据和索引都放在一起,找到索引就找到了数据,在mysql下的data文件夹下可以看到用的是.ibd文件去存储索引和数据。
其中通过trx_id用来存对聚簇索引记录修改的时候的事务id
roll_pointer每次对对聚簇索引记录修改的将老版本写入到undo log中去,这个roll_pointer就是存了一个指针,指向这个索引记录的上一个版本
2、非聚簇索引是叶节点存索引,然后是储存数据的地址,找到索引后再根据地址去找我们的数据,在data文件夹下面用的是.MYD存数据,MYI去存的索引

使用索引查询一定能提高查询的性能吗?为什么

索引并不是用的越多越好,得考虑到索引也要占用储存控件,也需要定期
维护,对增删改的负担增加了,每次都还得去多付出性能去操作索引

索引分类

唯一索引:保证数据唯一
全文索引:比like “name”这种就可以用全文索引
组合索引:一般索引都是建立在一个字段上的,组合索引可以覆盖多个字段

sql语句的优化

查询的时候避免全盘扫描,这里博主打个比分假如只需要查询一行数据比如登录,那么是不是最后加给limit更好这样只要查到了一行数据就不会在数据库中继续查了
避免使用*,当然count(*)除外   count(")本来就是用来定义查询多少行
数据的,如果你定义的是count(name),如果有一列没有name不就少
了一行吗,本来就是这样定义的,不会影响查询速度的,但是如果要
查询出来一个一个的列,最好是在select 后面写上字段,不管是后期
维护,加字段都会方便很多

事务

什么是数据库事务?

事务时一个不可分割的工作单位,要么都执行成功,要么就都失败,比如
转账是俩个行为,但是我们说这是一个事务

事务的ACID

原子性:上面说到了要么执行都成功要么都失败
一致性:执行事务前后,数据一致
隔离性:并发访问数据库的时候,任务之间不能互相干扰到数据,都是各干各的
持久性:事务提交后在数据库的改变是持久的,永久保存在数据库中

脏读?幻读?不可重复读?

脏读:就是某一个事务还没有提交的事务被另一个事务访问到了,打个比
分就是事务1,a这个时候转账个了b,然后事务2这个时候查看b,确实多
了一个亿,这个时候事务1再回滚了,那么事务2岂不是白高兴一场幻读:继续打比方,比如事务1干了一个查询a表工资大于8000的人,然
后中间还干了其他事情,然后要再查a表工资大于8000的人,然而在a查
了第一次后去干其他的事情的时候事务2把a表中的张三工资涨到了1w,
事务1这个时候才干完中间的事情,再查a表工资大于8000的人的时候
就多了一行,这就好像是出现了幻觉一样,就是幻读不可重复读:就是一个事务重复去读取一个数据,但是中间还么读取的
时候其他事务对数据进行的更改到时读取俩次的结果不一致

事务的隔离级别

事务的四个隔离级别,我推荐看一下spring的那个事务的注解,有
的面试官会要你说spring的事务,其实就是数据库的事务
我发我这的部分代码-在下面这个代码块中
这个@Transactional注解后的这个isolation参数点进去就可以看见
隔离级别,是四个隔离级别,然后spring定义了一个defult,mysql默认
的隔离级别是rc ,我这里定义的是rr然后我教你们这么记就记r开头的 和_后的比如ru就是读未提交,就等于没得事务,什么都处理不了rc读以提交,当然就是处理脏读的了rr重复读,当然就是处理不能重复读的问题啦ser这个什么的太长了,就是序列化,当然就是什么都可以处理但是注意:事务用的越多对多线程的处理就越垃圾

```java//开启重复读事务@Override@Transactional(isolation = Isolation.REPEATABLE_READ)//isolation 中的五个隔离级别public enum Isolation {DEFAULT(-1),READ_UNCOMMITTED(1),READ_COMMITTED(2),REPEATABLE_READ(4),SERIALIZABLE(8);private final int value;private Isolation(int value) {this.value = value;}public int value() {return this.value;}
}

MySQL的锁了解吗? 博主这里就只知道乐观,悲观锁

这里百度帮你们粘贴了几个核心
行级锁 表示只针对当前操作的行进行加锁,开销大,加锁慢;会出现死锁
表级锁 表示对当前操作的整张表加锁,开销小,加锁快;不会出现死锁
页级锁 页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁,开销和加锁时间界于表锁和行锁之间;会出现死锁

数据库的乐观锁和悲观锁是什么?怎么实现的?

悲观锁是什么时候都给自己加锁,查询完后就吧事务锁起来,使用的是数据库中的锁机制
乐观锁:通过version来进行锁定,假如一个事务执行修改,这个时候sql语句定义version=0的
时候再修改,然后修改的时候吧这个version该为1,然后下一个事务也是要version=0的时候再
进行修改,这个时候就做到了乐观锁,详细的可以看mybtisplus官网,mybtisplus可以自动帮
我们做这个乐观锁的操作

Spring

谈谈你对spring的理解

spring我的理解就是轻量级的javaEE开发框架,帮助咱们开发人员实现复杂的网址后端服务
其中核心就是IOC,控制反转和AOP面向切面,极大的降低咱们企业级开发的复杂度

博主洽谈IOC

其实IOC并不是什么新的技术,而是一种设计思想,原始的开发方式是new对象,还需要我们
自己去维护,那么有了IOC之后我们就可以将自己设计好的类统一的交给容器去管理就完事了那么如何去实现呢?通过DI,也就是依赖注入然后在标签中的 autoWired 可以定义自动注入:通过byName,byType注入值的方式有:set方法注入构造方法注入注解注入那么注入到容器当中我们知道了,那么咱们去取容器当中的bean呢?通常我们使用@Resource      注解  优先通过名字再是类型去看容器里面有没有bean,如果没有设置name,那么就会根据我们的属性的名字当作是name去进行查找 @AutoWired       注解  这个是spring的注解,默认按类型查看容器,如果需要以名字查找还需要在下面加应该@Qualifier("容器id")去进行查找,还可以设置那个是主bean,设置了之后如果bytype找到同样属性的bean后会使用主bean,还有bean的优先级和主bean同理,不设置的话如果找到多个spring不知道用哪个则会报错然后spring创建出来的bean默认是单例的,那么可以变成多例吗?当时是可以,就是作用域,我一次面试被问我都傻了,不过也还是通过了面试了呢singleton单例prototype每调用一次new一个request Http协议中,调用一次生成一个session Http协议中一个会话一个

博主洽谈AOP

AOP就是面向切面,在不改变原有代码的情况下去追加新的功能,一般我们都用来做日志,权限等...博主这里也用来做数据在后端的校验,切入我们每一个新增的方法,得到方法后的参数类型再得到校验返回
的异常信息,然后将异常返回到前端就完事了AOP的底层就是用的动态代理的设计模式去实现的又分了jdk原生的动态代理通过invkehedler(单词记不清懒得搜了都是手敲的)去实现同一个接口的这种方式去代理的CjLib的动态代理生成子类去进行功能动态的追加然后就是那几个名词了,我用代码逻辑的方式去讲解________________________________________就拿校验来说,如果我们要做一个校验那么我们肯定是要定义一个 **切面** 然后在切面当中去定义我们的**增强**类型(前置,后置,环绕,异常,最终),还有我们的**切点**用注解的方式其实这完成了**切点**是我们要对那个逻辑进行增加,就是连接点**增强**就是我们追加的功能**连接点**就是我们被增强的那个方法的位置**织入**就是将切点放到外面的增强当中去,让增强知道去增强那个地方

spring的生命周期

1、通过一个类的class通过反射去实例化得到对象,中间还需要推断使用哪个构造方法
2、得到对象后就需要进行属性填充,就是我们的DI依赖注入
3、afterPropertiesSet()这个方法看执行可以不执行,相当于bean的init()方法,在注入属性后就会执行到这个方法,比如当前我们的Userservice类中有一个user的引用没有赋值(注意这个user不是bean),需要每一个用户调用bean的时候去进行赋值得到每一个用户独有的user对象,那么就可以使用这个方法,在这个方法里面进行赋值
4、这个时候就执行到AOP了,会通过得到的这个类的信息去看我们的切面当中有没有和这个类匹配的切点什么的,如果没有的话就直接生成我们需要的bean了,如果有和切点匹配的方法那么就会生成一个代理类,我们最终得到的其实是一个代理类的bean
5、得到这个bean了当然就是进行调用了
6、调用完后就不归我们管理了,我理解的就是不用的时候spring会帮我们销毁掉

spring的循环依赖

A依赖B
B依赖C
A依赖C
这种情况,博主在创建文件操作工具类的时候,依赖了一个工具类去开启文件服务器链接,需要的参数,服务器地址,用户名密码等等又是通过另一个类从配置中心拿,然后在工具类中去使用,就会导致在加载的时候参数那个类还没通过反射住入到容器中,我不知道这个算不算依赖住入,我当时的解决方案是将参数那个类删了,直接在工具类通过@value去配置文件拿这样就解决了,网上的方案说是开启三级缓存解决循环依赖

spring的单例bean是线程安全的吗?

Spring中的单例bean并没有做多线程处理,如果说你某个bean当中有计数的变量则需要自己维护,最简单的办法就是将这个单例的bean改成多例的就完事了

spring中用到了那些设计模式

1、工厂模式,BeanFactory就是其中一个
2、单例模式,保证一个类只有一个实例,提供全局访问
3、适配器模式,每个controller都有对应的适配器,涉及到SpringMVC的执行流程,当请求进到controller的时候会通过headlr映射处理器处理heandler后到适配器找到对应的controller后执行完逻辑再去视图解析器处理返回,最后将视图返回
4、AOP的动态代理

spring事务

就是利用aop去做的事务,去生成代理类去进行事务的处理,这个时候我们从一个事务中去调用另一个事务的时候就涉及到了事务的传播(下面有事务的传播),默认是requied这个默认的,但是我们设置其他的传播机制的时候想要生效就必须要把这个类的bean去注入进来,用这个bean去调用我们的a方法才能去用其他的一个传播机制

Transaction事务的传播机制

spring中的事务的传播它是指a事务调用b事务之间的印象,传播类型一般作用在后面那个
事务
required默认的就是这个,如果a没事务则b就新建事务,如果有则加入这个事务
supports如果a有事务b就加入,a没有那b也不加入事务
mandatory如果a有事务b就加入,如果没有就抛异常
requlres_new让a和b各自处理自己的事务
not_supported不管a有没有事务,b都是按没事务来运行
never a有事务b抛出异常
nested 就和默认的差不多

哪些注解各位小伙伴做一个项目就收悉了,也可以百度一下,我个人懒得记那么多,看临时发挥,都是些简单的

SpringMVC

什么是SpringMVC

是spring针对web开发的一个一站式的解决方案,是基于web的框架,提供一个总的servlet
去收发请求处理结果,解析视图

一般都是问的执行流程,SpringMVC的执行流程

各位小伙伴不要死记硬背,这个东西要理解流程就是用户发送请求给外面的核心servlet,然后我这就用servlet去代替,懒得打字了
servlet收到请求后通过映射的处理器去请求handler得到具体要处理那个controller的处理器的
handler返回给servlet再去找到处理这个handler的处理适配器去处理后返回modelandview给
servlet再去访问视图解析器去解析完再返回到servlet去调用视图解析器再返回视图让servlet去
渲染给用户

解决乱码问题

1、通过在web.xml文件中去设置CharacterEncodingFiter拦截器去拦截,设置encoding为utf-8
2、修改tomcat中的配置config.xml的那个文件里面的标签找到encoding设置为utf-8
3、得到的默认是8859-1,可以通过转byBytes()将88t9-1转换成utf-8

SpringMVC是不是单例模式

是单例的,如果是多线程去访问的时候我们可能会遇到访问同一个对象导致数据问题,我们可
以使用ThreandLock去定义公共访问的变量,ThreandLock专门就是为了应对这种场景的

我百度了一下问题,大部分都是在基本操作的基础上去进行题目的改变来问技术,这些只要熟练使用就不会有问题的

MyBatis

MyBatis基础

谈谈什么是MyBatis?

MyBatis是数据持久层的一个半ORM框架,封装的JDBC的一些基本操作,不需要我们去进行哪些繁琐
我们只需要去关注sql语句就好了,将sql语句都定义的映射文件当中方便我们的管理,可以大大缩短我
们的开发时间,但是因为sql语句是定义在映射文件中,那么我们要从mysql转换使用其他的数据库的
时候会特别不方便

稍微深一点

通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?

MyBatis底层是通过我们映射文件当中定义的namespes的名字,以及写sql标签上的id去对应我
们动态代理去生成dao接口的全限定类名再准确找到方法进行执行,所以方法不能重载,不然不
知道要执行那个

${}与#{}的区别

${}的在定义到sql里面去的时候会先进行运算操作
#{}在定于sql的时候相当于占位符,在sql中相当于‘?’有效防止sql注入问题

动态标签?

set if  trim where schoose foreach 一共9个我就记得这些常用的,别的我也记不得懒得写了

一级、二级缓存

一级缓存默认开启,SqlSession级别的缓存
二级缓存在配置文件中把cacheEnablod设置为ture,在映射文件中的sql上中定义二级缓存
的开启

MyBatis如何进行分页

可以通过插件那个pageh什么p的,麻烦百度一下我不会写哈哈哈
然后要自己定义的话要先求出总行数,得到每页显示数,就可以得到页数,然后通过传入当前页去进行分页查询

传入传出参数

resultmap和resulttype,type底层其实就是用的resultmap,resultmap一般用来对应一对多
或者多对一的场景,使用ass什么tion的进行一对一,使用colltion进行一对多的操作,
传入参数可以传对象,或者使用@prom(“#{}中的name”)或者传入map
传出参数一般是传对象

Springboot

什么是SpringBoot

SpringBoot就是用来简化spring应用开发的复杂度,在ssm的项目中我们需要配置特别多的xml配bean的操作,特别
繁琐,springboot就把之前ssm项目中我们需要初始化配置的哪些xml配bean给砍掉,自动的去帮我们配置

springbootApplication的运行机制

springboot通过根据配置文件自动装配所属依赖的类,再用动态代理的方式注入到容器里面

Spring Boot 的核心注解是哪个?

@SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能,用来标注一个类为配置类
@EnableAutoConfiguration:里面包含俩个注解
@ AutoConfigurationPackage:将主配置类所在的包作为自动配置的包进行管理
@import:导入类到ioc容器中,根据MATA-INFO/spring.factories下的
@ComponentScan:spring组件扫描,将指定需要扫描的包下的组件注册到容器里面去

上一题其实也是自动配置的原理

自动配置的原理其实也很简单,博主打比方时间到
比如要和MyBatis整合,那么MyBatis的依赖会提供一个使用@Configuration+@bean
的一个配置类,然后放到META-INF/spring.factories下去,然后通过spring.spi去扫描,再用@import导入自动配置类

Redis

学习入口:https://blog.csdn.net/weixin_43829443/article/details/112839985?spm=1001.2014.3001.5506

redis主从复制的核心原理

redis主从复制只需要区分全量复制和部分复制;就是从一个服务器复制另一个服务器的数据,主数据库可以进行读写操作,从数据库一般都是进行度数据,并且接受主数据库同步过来的数据,一个主数据可以拥有多个从数据库。
全量复制:(RDB相当于快照复制和AOF复制相当于存储的每一条操作记录)
1、主节点通过命令将进程进行RDB镜像的持久化,该过程非常消耗CUP硬盘IO
2、主节点再通过网络将镜像(RDB)文件发送给从节点,对从节点的宽带都会带来很大的消耗
3、从节点清空老数据,载入新的RDB文件的过程是阻塞的,无法响应客户端的命令;如果从节点执行AOP复制数据也会带来额外的消耗

部分复制:
1、需要复制偏移量,执行复制的双方(主从节点)都要记录一个偏移量好知道同步的进度
2、复制积压缓冲区:主节点维护的一个队列,先进先出的,从偏移量之后的数据开始存到缓冲区,但是缓冲区长度太长了,就会无法执行部分复制,就只能执行全量复制
3、主节点的服务器运行ID,每个redis的节点都有运行id,主节点在同步的时候会将运行id发送给从节点,如果 节点宕机了挂了就只能进行全量复制了,因为无法确认偏移量

redis过期健删除策略

惰性删除,有访问的时候才去删除
定期删除,隔一段时间去删除一定量的key

redis线程模型,单线程快的原因

redis的处理器是文件事件处理器,这个文件事件处理器是单线程的,所有redis才叫做单线程模型
单线程快的原因:纯内存操作,核心是基于非阻塞io的多路复用,单线程反而避免了上下文切换的性能问题

缓存雪崩,缓存穿透,缓存击穿

1、缓存雪崩是指同一时间大面积缓存失效啊,比如重启缓存这种,就会导致请求都到了数据库上,造成数据库短时间承受太多请求导致崩掉
解决方案:
1)缓存的过期时间错开,防止同一时间大量缓存过期
2)缓存预热

2、缓存穿透是指缓存和数据库中都没有数据,导致请求都落到数据库上
解决方案:
1)接口层增加校验
2)都取不到数据库的情况就设置这个key值为null的到redis,缓存时间设置短一点,可以防止反复的请求到同一个key被攻击的情况
3)采用布隆过滤器,将可能存在的数据哈希到bitmap中,一定不存在的数据就会被拦截掉,从而避免对数据库的请求

3、缓存击穿是指缓存中没有数据,当时同事并发量特别大,缓存没读到数据都去读数据库,导致数据库压力瞬间增大,和雪崩不同的是击穿指的是某一条热点数据
解决方案:
1)设置热点数据永不过期
2)增加互斥锁(就是在一个请求进入到这个key的时候就将这个key锁上不让其他请求进入)

(redis缓存问题)图片采用 地址

redis事务实现

redis开启事务,multi(吗体奥)命令,标识开启事务
客户端进入事务状态之后,执行的所有常规 Redis 操作命令(非触发事务执行或放弃和导致入列异常的命令)会依次入列,命令入列成功后会返回 QUEUED
exec命令服务器就会执行事务

mq消息队列

选择使用那个中间件

RocketMQ特有的延迟队列怎么实现的

在发送消息后加个中间层去存要发的消息,存延迟的时间,再返回给要发送的mq队列中,再进行消费

RocketMQ保证事务一致性

在发送消息的时候会变成半发送状态,不会发送给消费者消费,直到检查到本地事务提交或者回滚后才会操作mq发送或者不发送

微服务

谈谈对微服务的理解,微服务有哪些优缺点

微服务就是一种架构风格,将大型的单体应用划分成较小的服务单元,降低系统的复杂度
优点:

  1. 服务部署更灵活:每一个应用都可以时一个独立的项目,解耦
  2. 技术跟新灵活:大型单体应用中,技术要进行跟新非常困难,在微服务可以根据业务的情况,灵活选择技术栈
  3. 代码复用:通过REST API的方式对位提供统一的服务
    缺点:
  4. 服务效用的复杂度提高了,网络并发负载的问题
  5. 分布式事务:尽量不使用微服务事务
  6. 运维的难度提升了,因为微服务多个环境,不管是部署还是什么都增加的工作量和复杂度

SpringCloud


我的理解就是前面说的了单体服务的问题所在,那么用微服务肯定是要搭建集群的,那么客户端服务端的都是集群搭建的,中间怎么去进行调用呢?我们就需要用到Eureka去进行服务的注册与发现;那么服务注册与发现好了,我们可以调用到我们的服务提供者了,但是又会有问题,如果a服务端用户访问的太多,b服务用户访问的少就造成了资源浪费,这个时候就需要用到Ribbon去进行负载均衡,调用服务端的方式还可以使用Feign,一种就好比是接口的形式去调用,一种就直接访问的url;访问没问题了,这个时候又可能会出现服务端炸了啊或者怎么样服务端出现问题了,那么服务消费肯定调用会报错的,这个时候我们不能让错误信息展示给用户,所以又需要Hytrix去做服务熔断和降级;这些问题都处理好了后又有服务端不好管理的问题,因为服务器的地址又不一致,所以这个时候我们就用zuul网关来解决这个问题

SpringCloudAlibaba

1、注册中心使用nacos去注册发现服务,以及服务的健康检测,默认5s发送一次心跳;
2、那么注册中心有了服务直接就可以互相调用了,但是微服务架构中每个服务都是集群的,如果是俩个服务器中有个服务器一直被访问,另一个服务器的访问量又极少,就会造成资源浪费,这个时候就需要用到负载均衡了,而我们的nacos已经集成了Ribbon去做客户端的负载均衡(ribbon做的事情就是发现域名下机器,并且负载均衡的调用),会通过轮询随机权重去调用不同服务器的同一个服务,但是需要加上@LoadBalanced注解将RestTemplate注入到spring中;

2.1)原理:ribbon中有一个拦截器,在调用中会拿到url将域名解析出来,将域名发到注册中心,用服务名将所有注册中心的机器列表都拉到本地缓存中
2.2)openFeign,让我们调用变得更加方便,就像调用本地方法一样,调用端需要在启动类加@EnableFeignClients注解,只需要写调用远端服务的Feign接口即可
2.3.1)原理:在feign接口会被代理,代理方法会将注册中心的服务名拿到再去做负载均衡调用

3、Sentinel做服务熔断降级限流
3.1、降级:(调用端)降级功能需要在feign接口中加fallback属性中加fallback实现类,做折中的降级处理,原理就是动态代理去实现feign接口时用try cath处理 ,感知到报错就在cath中调用fallback实现类
3.2、限流:(被调用端)需要安装Sentinel客户端,并且在服务中配置Sentinel的地址,这样被调用的的请求都会在Sentinel的客户端中的链路追踪中就可以进行流控
3.3、熔断:Sentinel客户端中配置熔断,如果调用链路异常次数超过设置的则就将这个调用链路熔断掉,不再被调用

限流熔断原理:熔断就是多次进行远程调用的失败的时候就会进行屏蔽掉远程服务,就把这个链路直接断掉

4、网关Gatway 做路由转发,权限校验,灰度发布

shiro

什么是shiro

Shiro是一个强大易用的Java安全框架,主要用来认证、授权、加密、会话管理、与Web集成、缓存,相比其他安全框架shiro小的多,安全的多

Shiro的核心概念Subject、=SecurityManager、Realm

1、Subject :当前用户的操作
2、SecurityManager:用于管理所有的Subject
3、Realms:用于进行权限信息的验证

常用的组件

Authentication:身份认证/登录,验证用户是不是拥有相应的身份;

Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限

Session Manager:会话管理,即用户登录后就是一次会话

Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;

Web Support:Web支持,可以非常容易的集成到Web环境;

Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;

Concurrency:shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;

Testing:提供测试支持;

Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;

Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。

Liunx

当前目录

pwd

查看文件

ls

查看文本文件

cat 文件

修改文本文件vi编辑器

在查看文件的使用按下i进入输入模式就可以更改了,更改后按esc然后用wq!进行保存退出

复制文件

cp source dest 复制文件

cp -r sourceFolder targetFolder 递归复制整个文件夹

scp sourecFile romoteUserName@remoteIp:remoteAddr 远程拷贝

创建目录

mkdir

删除目录

rmdir deleteEmptyFolder 删除空目录

rm -rf deleteFile 递归删除目录中所有内容

移动文件

mv /temp/movefile /targetFolder

重命名

mv oldNameFile newNameFile

切换用户

su -username

压缩文件

tar -czf test.tar.gz /test1 /test2

网络检测

ping 网址
telnet

java面试突击-2022最新迭代redis\mq\springCloud-纯手打相关推荐

  1. 互联网寒冬下拿捏大厂面试?2022最新版的Java面试突击班手册流露,果真一分钱一分货

    前言 虽说今年互联网就业形势不太好,但也有很多同学已经成功"拿捏"了今年的面试,那么本着取长补短的原则,我问了问,好多同学给我说,2022最新版的Java面试突击班的内容给自己提供 ...

  2. 拿捏大厂面试,2022最新版的Java面试突击班手册

    前言 最近很多同学已经成功"拿捏"了今年的面试,好多同学给老师说,2022最新版的Java面试突击班的内容给自己提供了很大的帮助,在这里很感谢这些同学对老师的认可,老师会持续奋战在 ...

  3. Java岗:2022最新版的Java面试突击班手册,大厂面试轻松拿捏住!

    前言 最近很多同学已经成功"拿捏"了今年的面试,好多同学给老师说,2022最新版的Java面试突击班的内容给自己提供了很大的帮助,在这里很感谢这些同学对老师的认可,老师会持续奋战在 ...

  4. 相当炸裂!阿里架构师最新产出Java面试突击宝典,直接霸榜Github

    Java作为一门历史悠久的编程语言,仍然是企业级应用开发的首选.然而,随着新兴技术的涌现,Java的地位逐渐被冲淡,同时开发人员数量过剩也给Java行业带来了竞争压力.为了保持竞争力,Java行业需要 ...

  5. 全网首发!马士兵内部共享—1658页《Java面试突击核心讲》

    又是一年一度的 "金九银十" 秋招大热门,为助力广大程序员朋友 "面试造火箭",小编今天给大家分享的便是这份马士兵内部的面试神技--1658页<Java面 ...

  6. 冲刺!这篇 1658 页的《Java 面试突击核心讲》学明白保底年薪 30w

    前言 2022 年已经到了七月中旬了,又快要到一年一度的 "金九银十" 秋招大热门,为助力广大程序员朋友 "面试造火箭",小编今天给大家分享的便是这份--165 ...

  7. 花了148元!买了这份阿里内部面试神技——1658页《Java面试突击核心讲》

    又是一年一度的 "金九银十" 秋招大热门,为助力广大程序员朋友 "面试造火箭",小编今天给大家展示的便是这份阿里内部的面试神技--1658页<Java面试 ...

  8. 马士兵内部共享—1658页《Java面试突击核心讲》,面试神技

    "金九银十" 秋招大热门已经到了末尾,为助力广大程序员朋友 "面试造火箭",小编今天给大家分享的便是这份马士兵内部的面试神技--1658页<Java面试突 ...

  9. 全网首发?蚂蚁金服内部共享—1658页《Java面试突击核心讲》

    又是一年一度的 "金九银十" 秋招大热门,为助力广大程序员朋友 "面试造火箭",小编今天给大家分享的便是这份蚂蚁金服内部的面试神技--1658页<Java ...

最新文章

  1. 为什么做小程序的时候要做定制开发小程序?
  2. weui 弹出 $.toast(“我是文本“,“text“); 总是带有图标
  3. linux 强制刷新文件,vim 如何刷新或重载reload 已打开的文件
  4. 基于mui框架读取nfc数据_基于NFC的数据采集软件系统的设计与实现
  5. 计算机常用编程英语词汇大全,计算机编程及常用术语英语词汇大全
  6. 2016上半年中国云存储排行榜:阿里云居榜首
  7. 【ModelArts-Lab AI实战营】使用Postman测试Modelarts在线服务(图像分类、物体检测)
  8. Node.js的完全卸载与下载安装及各种npm、nvm、nrm配置(保姆式教程---提供全套安装包)---node.js的安装与配置(0)
  9. 处理字典值是把字典放内存还是用sql处理_第二周:MYSQL数据库入门,提升你的数据处理效率...
  10. 异步调用结果的获取(转)
  11. 网络游戏客户端服务器通信协议,有大神懂网络游戏通信协议么
  12. 如何生成每秒百万级别的 HTTP 请求
  13. Extjs GRID表格组件使用小结
  14. 高手常用的15 种 SQL 优化
  15. 台达变频器485通讯接线图_台达变频器RS485通讯设置
  16. ipad mini2降级刷10.3.3系统教程
  17. C 语言之父丹尼斯·里奇逝世十周年
  18. NSIS 简易教程(四)
  19. 教你制作专属个性二维码!将照片制作成二维码图片!给二维码添加背景图片!
  20. CPU使用率查看方法

热门文章

  1. 基于51单片机的水族箱温度水质监测智能宠物金鱼喂食器补氧换水proteus仿真原理图
  2. ThinkSNS团队衍生产品你知道几个?
  3. 类的成员变量 请定义一个交通工具(Vehicle)的类其中有: 属性速度(speed)体积(size)等等 方法移动(move())设置速度(setSpeed(int speed))加速speed
  4. passwd出现不完全匹配登陆成功的情况,问题解决如下
  5. 梦次元poi进不去了_free gv video GV
  6. 弱酸阳离子树脂去除硫酸锂溶液中的钙镁离子技术
  7. sql查询涵盖的时段_涵盖的主题
  8. 移动网络运营商显示无服务器,无线路由器忽然拨不上号,显示网络运营商远端无响应怎么处理...
  9. SpringMVC小白问题一之启动时配置应用程序监听器错误
  10. shell脚本模拟键盘输入完成程序交互(定时重启docker部署的项目样例)