面试题抽答(补充)

面试题抽答

2.1.String 和 StringBuilder 的区别? ,为什么会有这个区别?使用有什么注意

String 和 StringBuffer、StringBuilder 的区别在于 String 声明的是不可变的对象(final修饰),每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象,而 StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,注意:在经常改变字符串内容的情况下最好不要使用 String。

2.2.StringBuffer 和 StringBuilder 的区别,为什么有那个区别?使用有什么注意

StringBuffer (加了锁,多线程使用)和 StringBuilder 最大的区别在于,StringBuffer 是线程安全的,而 StringBuilder 是非线程安全的,但 StringBuilder 的性能却高于 StringBuffer,所以在单线程环境下推荐使用 StringBuilder,多线程环境下推荐使用 StringBuffer。

2.4.HashMap底层用到什么哪些数据结构,为什么会用到这些数据结构,初始长度是多少,什么情况扩容
hashmap数据结构由数组+链表组成,一个长度为16的数组中,每个元素存储的是一个链表的头结点

什么是Hash碰撞:(两个输入串的hash函数的值一样,则称这两个串是一个碰撞(Collision)。既然是把任意长度的字符串变成固定长度的字符串,所以必有一个输出串对应无穷多个输入串,碰撞是必然存在的。)

处理碰撞:开放寻址(Open Addressing)法和链接(Chaining)法

HashMap长度是默认的16
在容量不大于最大值的情况下,HashMap是以2倍的容量进行扩容的

2.5.HashMap和HashTable的区别,为什么有这个区别

HashMap 和 Hashtable 有什么区别?
存储:HashMap 允许 key 和 value 为 null,而 Hashtable 不允许。
线程安全:HashMap 线程不安全,Hashtable 线程安全
推荐使用:在 Hashtable 的类注释可以看到,Hashtable 是保留类不建议使用,推荐在单线程环境下使用 HashMap 替代,如果需要多线程使用则用 ConcurrentHashMap 替代。

HashMap和ConcurrentHashMap有什么区别?

ConcurrentHashMap线程安全,hashMap线程不安全,
因为ConcurrentHashMap它引入了一个“分段锁”的概念,对整个桶数组进行了分段,把一个大的Map拆分成N个小的HashTable,根据key.hashCode()来决定把key放到哪个HashTable中。
2、ConcurrentHashMap在每一个分段上都用锁进行保护,从而让锁的粒度更精细一些,并发性能更好,而HashMap没有锁机制,是线程不安全的
3.ConcurrentHashMap使用读写锁

如何决定使用 HashMap 还是 TreeMap?
对于在 Map 中插入、删除、定位一个元素这类操作,HashMap 是最好的选择,因为相对而言 HashMap 的插入会更快,但如果你要对一个 key 集合进行有序的遍历,那 TreeMap 是更好的选择。

说一下 HashMap 的实现原理?
HashMap 基于 Hash 算法实现的,我们通过 put(key,value)存储,get(key)来获取。当传入 key 时,HashMap 会根据 key. hashCode() 计算出 hash 值,根据 hash 值将 value 保存在 bucket 里。当计算出的 hash 值相同时,我们称之为 hash 冲突,HashMap 的做法是用链表和红黑树存储相同 hash 值的 value。当 hash 冲突的个数比较少时,使用链表否则使用红黑树。

说一下 HashSet 的实现原理?
HashSet 是基于 HashMap 实现的,HashSet 底层使用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,相关 HashSet 的操作,基本上都是直接调用底层 HashMap 的相关方法来完成,HashSet 不允许重复的值。

2.3.ArryList的底层结构是什么?初始长度是多少?扩容机制是什么?

ArrayList初始大小为10,每次1.5倍进行扩容;它的底层是用数组实现的,所以查询速度相对LinkedList要快

ArrayList和LinkedList的区别,查询谁快,修改谁快?

ArrayList的底层是用数组实现的,所以查询速度相对LinkedList要快

1.ArrayList使用了数组的实现,可以认为ArrayList封装了对内部数组的操作,比如向数组中添加,删除,插入新的元素或者数据的扩展和重定向。

LinkedList使用了循环双向链表数据结构,不需要维护容量的大小。与基于数组ArrayList相比,这是两种截然不同的实现技术,这也决定了它们将适用于完全不同的工作场景。
LinkedList链表由一系列 表项 连接而成。一个表项总是包含3个部分:元素内容,前驱表和后驱表

2.ArrayList 的查询效率比较高,增删动作的效率比较差,适用于查询比较频繁,增删动作较少的元素管理的集合。
LinkedList 的查询效率低,但是增删效率很高。适用于增删动作的比较频繁,查询次数较少的元素管理集合。

3.ArrayList ,LinkedList 都是线程不安全的

说一下"=="和equals方法究竟有什么区别?

1.操作符专门用来比较两个变量的值是否相同. 如果比较的是基本数据类型,那么比较的是变量的值,如果比较的是引用数据类型,那么比较的是地址值(两个对象是否指向同一块内存),要比较两个 基本类型的数据或两个引用变量是否相等只能用操作符

2.equals:用来比较两个独立对象的内容是否相同,如果没有重写equals方法比较的是两个对象的地址值。 如果重写了equals方法比较的是对象中的属性的内容

1.讲一下线程的几种实现方式?
继承thread 执行run方法
实现runnable接口和callable接口

2.线程池的作用,如何创建线程池,可以创建几种线程池?
newCachedThreadPool创建一个可缓存线程池
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池

作用:第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
  第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
  第三:提高线程的可管理性。

线程的状态:
NEW 尚未启动
RUNNABLE 正在执行中
BLOCKED 阻塞的(被同步锁或者IO锁阻塞)
WAITING 永久等待状态
TIMED_WAITING 等待指定的时间重新被唤醒的状态
TERMINATED 执行完成

sleep() 和 wait() 有什么区别?
类的不同:sleep() 来自 Thread,wait() 来自 Object。
释放锁:sleep() 不释放锁;wait() 释放锁。
用法不同:sleep() 时间到会自动恢复;wait() 可以使用 notify()/notifyAll()直接唤醒。

notify()和 notifyAll()有什么区别?
notifyAll()会唤醒所有的线程,notify()只会唤醒一个线程。notifyAll() 调用后,会将全部线程由等待池移到锁池,然后参与锁的竞争,竞争成功则继续执行,如果不成功则留在锁池等待锁被释放后再次参与竞争。而 notify()只会唤醒一个线程,具体唤醒哪一个线程由虚拟机控制。

线程的 run() 和 start() 有什么区别?
start() 方法用于启动线程,run() 方法用于执行线程的运行时代码。
run() 可以重复调用,而 start() 只能调用一次

线程池都有哪些状态?
RUNNING:这是最正常的状态,接受新的任务,处理等待队列中的任务。
SHUTDOWN:不接受新的任务提交,但是会继续处理等待队列中的任务。
STOP:不接受新的任务提交,不再处理等待队列中的任务,中断正在执行任务的线程。
TIDYING:所有的任务都销毁了,workCount 为 0,线程池的状态在转换为 TIDYING 状态时,会执行钩子方法 terminated()。
TERMINATED:terminated()方法结束后,线程池的状态就会变成这个。

线程池中 submit() 和 execute() 方法有什么区别?
execute():只能执行 Runnable 类型的任务。
submit():可以执行 Runnable 和 Callable 类型的任务。
Callable 类型的任务可以获取执行的返回值,而 Runnable 执行无返回值。

在 Java 程序中怎么保证多线程的运行安全?
方法一:使用安全类,比如 Java. util. concurrent 下的类。
方法二:使用自动锁 synchronized。
方法三:使用手动锁 Lock。

synchronized 和 Lock 有什么区别?
1.synchronized 可以给类、方法、代码块加锁;而 lock 只能给代码块加锁。
2.synchronized 不需要手动获取锁和释放锁,使用简单,发生异常会自动释放锁,不会造成死锁;
lock 需要自己加锁和释放锁,如果使用不当没有 unLock()去释放锁就会造成死锁。
3.通过 Lock 可以知道有没有成功获取锁,而 synchronized 却无法办到。

什么是死锁?
当线程 A 持有独占锁a,并尝试去获取独占锁 b 的同时,线程 B 持有独占锁 b,并尝试获取独占锁 a 的情况下,就会发生 AB 两个线程由于互相持有对方需要的锁,而发生的阻塞现象,我们称为死锁。

怎么防止死锁?
尽量使用 tryLock(long timeout, TimeUnit unit)的方法(ReentrantLock、ReentrantReadWriteLock),设置超时时间,超时可以退出防止死锁。
尽量使用 Java. util. concurrent 并发类代替自己手写锁。
尽量降低锁的使用粒度,尽量不要几个功能用同一把锁。
尽量减少同步的代码块。

Interceptor
主要作用:拦截用户请求,进行处理,比如判断用户登录情况、权限验证,只要针对Controller请求进行处理,是通过HandlerInterceptor

Filter
主要作用:过滤字符编码、做一些业务逻辑判断,主要用于对用户请求进行预处理,同时也可进行逻辑判断。

Filter和Interceptor的区别

1、Filter是基于函数回调(doFilter()方法)的,而Interceptor则是基于Java反射的(AOP思想)。

2、Filter依赖于Servlet容器,而Interceptor不依赖于Servlet容器。

3、Filter对几乎所有的请求起作用,而Interceptor只能对action请求起作用。

4、Interceptor可以访问Action的上下文,值栈里的对象,而Filter不能。

6、Filter在过滤是只能对request和response进行操作,而interceptor可以对request、response、handler、modelAndView、exception进行操作。

3.常用的设计模式有那些,你用过的框架中哪个地方用到了这些设计模式?
单例模式:保证被创建一次,节省系统开销,
1.构造方法私有化,
2.在自己的类中创建一个单实例(饿汉模式是一出来就创建单实例,懒汉模式的话是需要的时候才创建单实例)
3.提供一个方法来获取到实例对象

工厂模式:Spring IOC就是使用了工厂模式.
对象的创建交给一个工厂去创建。解耦代码

观察者模式:对象之间的一对多的依赖,当一个对象改变时,它的所有的依赖者都会收到通知并自动更新

代理模式:Spring AOP就是使用的动态代理,对代码进行解耦,提高代码的维护性

模版方法模式:定义了一个算法的骨架,而将一些步骤延迟到子类中,模版方法使得子类可以在不改变算法结构的情况下,重新定义算法的步骤

状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类

1.Mysql的执行流程
1.客户端和mysql服务器建立连接
2.mysql服务器执行查询缓存,判断sql是否已经被执行,如果sql被命中,返回给客户端,如果没有命中就,将sql交给分析器
3.分析器分析sql语句功能
4.通过优化器对sql语句进行优化
5.选择最好的优化方案之后调用执行器
6.执行器判断权限,如果没有权限就直接报错,如果有权限就调用mysql存储引擎,返回接口执行的结果

数据库索引的优缺点:

优点:
1.创建索引会的列保证了唯一性
2.创建索引增加索引速度,缩短检索时间
3.创建索引可以加快表之间的连接
4.用来排序和分组的索引可加快排序和分组
缺点:
1.创建索引需要时间,空间成本
2.创建索引影响增删改的效率

二:mysql的优化?为什么要优化:处理高并发。单点故障,高可用,大数据

单机
1,创建数据库:
数据库存储引擎选择,A.选择合适的存储引擎,innodb,myisam,memery

三范式:列数据不可以再分,做唯一标识的主键,做外键进行连表查询

和反三范式,B.做反第三范式(添加冗余字段)来优化

字段数据类型:C.选择最适用的字段属性
(了解)
1.char:string的java字符串,长度固定
2.varchar:长度可以改变,一般使用varchar

3.tinyint:1个字节,存状态
4.bigint
5.int:4个字节,10位数字

6.blod:上传比较大的数据,存65k字节
  longblob:可存4gb

7,dicmial:存科学计算小数,价格相关的数据

2,D.sql语句的优化
1.使用索引
索引概念:对数据库的值进行排序的一种存储结构,提高查询效率(空间换时间)
索引分类:聚簇索引(主键索引),非聚簇索引(唯一索引,普通索引,复合索引)
创建索引的规范:
1.如果查询的次数比较多,则使用索引
2.如果表只负责修改操作,不要创建索引,浪费空间
3.一张表不要创建过多的索引(不超过16),经常作为where groupby orderby等条件创建索引
4.不要去创建内容重复的列的索引
索引失效:
1.执行计划:把explain加在查询语句的前面(查看是否通过索引查询)(但是采用连接join代替子查询,用union连接多个查询语句联合查询,查询速度快
2.模糊查询,like,%在前面的时候索引会失效(不通过索引查询,效率低)
3.函数
4.数字转换
5.!=
6.范围查询
2.把多次操作转换为一次操作
DQL(SELECT,orderby使用索引排序,groupby使用索引分组)
DDL(数据库定义语言:INSERT、用在定义或改变表的结构,数据类型,表之间的链接和约束等初始化工作上),
DML(数据库操作语言:UPDATE、INSERT、DELETE)
DCL(数据库控制语言:是用来设置或更改数据库用户或角色权限的语句)
or优化:两个条件都是索引查询,速度快,只要有一个条件不是索引查询就不会走索引查询
limit优化:没有创建索引的列用limit时,查询到需要的数据就返回,速度快

采用事务,要么成功,要么失败
锁定表,正常情况事务会锁定库,多个用户查询时需要等待,解决这种情况就锁定表
使用外键关联查询
避免在查询中让MySQL进行自动类型转换
  
  3.定位慢查询
  4.数据库分表,分库
  5.使用其他缓存 

集群
主从分离
读写分离

2.PreparedStatement相比Statement的好处

大多数我们都使用PreparedStatement代替Statement

1:PreparedStatement是预编译的,比Statement速度快

2:代码的可读性和可维护性
虽然用PreparedStatement来代替Statement会使代码多出几行,但这样的代码无论从可读性还是可维护性上来说.都比直接用Statement的代码高很多档次。

3:安全性
PreparedStatement可以防止SQL注入攻击,而Statement却不能

mysql存储引擎

MySQL 5.7 支持的存储引擎有 InnoDB(支持事务和外键)、MyISAM(不支持事务)、Memory(存放在内存)、Merge、Archive、Federated、CSV、BLACKHOLE 等。

如果要提供提交、回滚和恢复的事务安全(ACID 兼容)能力,并要求实现并发控制,InnoDB 是一个很好的选择。
如果数据表主要用来插入和查询记录,则 MyISAM 引擎提供较高的处理效率。
如果只是临时存放数据,数据量不大,并且不需要较高的数据安全性,可以选择将数据保存在内存的 MEMORY 引擎中,MySQL 中使用该引擎作为临时表,存放查询的中间结果。
如果只有 INSERT 和 SELECT 操作,可以选择Archive 引擎,Archive 存储引擎支持高并发的插入操作,但是本身并不是事务安全的。Archive 存储引擎非常适合存储归档数据,如记录日志信息可以使用 Archive 引擎。

提示:使用哪一种引擎要根据需要灵活选择,一个数据库中多个表可以使用不同的引擎以满足各种性能和实际需求。使用合适的存储引擎将会提高整个数据库的性能。

事务

事务是指是程序中一系列严密的逻辑操作,而且所有操作必须全部成功完成,否则在每个操作中所作的所有更改都会被撤消。可以通俗理解为:就是把多件事情当做一件事情来处理,好比大家同在一条船上,要活一起活,要完一起完

四个特性
1.原子性:事务不可以分割,操作这些指令时,要么全部执行成功,要么全部不执行。只要其中一个指令执行失败,所有的指令都执行失败,数据进行回滚,回到执行指令前的数据状态

2.一致性:事务的执行使数据从一个状态转换为另一个状态,但是对于整个数据的完整性保持稳定。

3.隔离性:隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离

4.持久性(Durability):当事务正确完成后,它对于数据的改变是永久性的

事务隔离级别:

1.Read uncommitted(最低级别,任何情况都无法保证。)
读未提交,顾名思义,就是一个事务可以读取另一个未提交事务的数据
b事务修改:修改前:李四 修改后:张三 但是没有提交事务,A读取到的是张三。 但是B事务回滚了

2.Read committed(可避免脏读的发生。)
读提交,顾名思义,就是一个事务要等另一个事务提交后才能读取数据。

3.Repeatable read(可避免 脏读、不可重复读(针对的是修改) 的发生。)
重复读,就是在开始读取数据(事务开启)时,不再允许修改操作
b事务修改:修改前:李四 修改后:张三 但是没有提交事务,A第一次读取到的是张三。 但是B事务回滚了,A第二次读的就是李四

4.Serializable(可避免脏读、不可重复读、幻读()的发生。) 串行化
Serializable 是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用

redis五种数据结构:

1.string:
set get mset mget setex setnx

2.hash
hset hget hgetall hdel hexists

3.list
lset lpush lpushx lpop rpop

4.set
SADD SINTER SMOVE SPOP

5.zset
ZADD ZCARD ZCOUNT

Redis 提供两种持久化机制 RDB 和 AOF 机制:

1、RDBRedis DataBase)持久化方式: 是指用数据集快照的方式半持久化模式)

记录 redis 数据库的所有键值对,在某个时间点将数据写入一个临时文件,持久化

结束后,用这个临时文件替换上次持久化的文件,达到数据恢复。

优点:

1、只有一个文件 dump.rdb,方便持久化。

2、容灾性好,一个文件可以保存到安全的磁盘。

3、性能最大化,
4.相对于数据集大时,比 AOF 的启动效率更高。

缺点:

数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化之间 redis 发生

故障,会发生数据丢失

2、AOFAppend-only file)持久化方式: 是指所有的命令行记录以 redis 命令请

求协议的格式完全持久化存储)保存为 aof 文件。

优点:

1、数据安全,aof 持久化可以配置 appendfsync 属性,有 always,每进行一次

命令操作就记录到 aof 文件中一次。

3、AOF 机制的 rewrite 模式。AOF 文件没被 rewrite 之前(文件过大时会对命令

进行合并重写),可以删除其中的某些命令(比如误操作的 flushall))

缺点:

1、AOF 文件比 RDB 文件大,且恢复速度慢。

2、数据集大的时候,比 rdb 启动效率低。

Redis有那些淘汰策略?

设置过期时间:淘汰将要过期的,用的少的以及任意淘汰
没有设置过期时间:淘汰用的少的,任意淘汰
不淘汰

Redis如何模拟队列,如何模拟栈

队列
先进先出,list形式
lpush–》rpop
rpush–》lpop


lpush–》lpop

Redis为什么这么快

1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);

2、数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;

3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;

4、使用多路I/O复用模型,非阻塞IO;

5、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;

缓存穿透

   描述:

   缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。

  解决方案:

接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击

缓存击穿
描述:
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力

  解决方案:

设置热点数据永远不过期。
加互斥锁

缓存雪崩
描述:

  缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。

 解决方案:

缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。
设置热点数据永远不过期。

非关系型数据库
MongoDB:是一个面向文档的开源NoSQL数据库。MongoDB使用JSON之类的文档来存储任何数据。它是用c++写的。
Cassandra:是Facebook为收件箱搜索开发的。Cassandra是一个用于处理大量结构化数据的分布式数据存储系统。
Redis:是最著名的键值存储。Redis是用C语言编写的。
HBase:是谷歌为BigTable数据库设计的分布式非关系数据库。
Neo4j:称为原生图数据库,因为它有效地实现了属性图模型,一直到存储层。
Oracle NoSQL:实现了从用户定义的键到不透明数据项的映射。

orm框架(对象关系映射)
orm框架是为了解决面对象和数据库互不匹配的的现象的一种技术框架
通过ibatis和hibernate来完成

ibatis:将sql和Java代码分离,提供了将结果集自动转化为对象实体的的功能,可以写出复杂的sql语句
hibernate:全自动orm映射工具,可以自动生成sql语句,执行sql语句并返回结果

ibatis和hibernate相同点:
都是orm框架,不使用jdbc api就能完成数据库的持久化操作

ibatis和hibernate不同点:
1、hibernate要比ibatis功能强大很多。因为hibernate自动生成sql语句。
2、ibatis需要我们自己在xml配置文件中写sql语句,hibernate我们无法直接控制该语句,我们就无法去写特定的高效率的sql

webservice是一个SOA(面向服务的编程)的架构,它是不依赖于语言,不依赖于平台,可以实现不同的语言间的相互调用,通过Internet进行基于Http协议的网络应用间的交互。

1、异构系统(不同语言)的整合
2、不同客户端的整合
3、实实在在的列子:
天气预报:可以通过实现webservice客户端调用远程天气服务实现的。
单点登录:一个服务是所有系统的登录

shiro:
可以做认证,授权,加密,会话管理,web集成,缓存支持
shiro组件:
身份验证:authentication
授权: authorization
会话管理:sessionmanager
加密
web支持
缓存
Apache shiro三大核心组件
subject(当前用户的操作),securitymanager(管理所有的subject),realms(权限信息认证)

其他组件:
 sessionmanager(会话管理),cachemanager(缓存管理)

Shiro工作流程(围绕三大核心组件)

1、应用代码通过Subject来进行认证和授权,而Subject又委托给SecurityManager;

2.给SecurityManager注入Realms,从而让SecurityManager能得到合法的用户及其权限进行判断。

instanceof 严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例,用法为:

boolean result = obj instanceof Class
instanceof 运算符的 obj 操作数的类型必须是引用类型或空类型; 否则,会发生编译时错误

页面静态化
1.使用PHP文件读写功能与ob缓存机制生成静态页面
比如某个商品的动态详情页地址是: http://xxx.com?goods.php?gid=112
那么这里我们根据这个地址读取一次这个详情页的内容,然后保存为静态页,下次有人访问这个商品详情页动态地址时,我们可以直接把已生成好的对应静态内容文件输出出来。

2.使用nosql从内存中读取内容(其实这个已经不算静态化了而是缓存);

iterater接口遍历所有的collection接口,我们可以从一个collection接口中通过迭代器方法获取到迭代器实例,迭代器取代了java集合框架中的enumeration,迭代器允许调用者在迭代过程中移除元素,iterater是更加安全的,因为当前遍历元素被更改时抛出异常

listiteration是继承了iteration的,提供了iteration之外的一些功能
iterrator可以遍历list和set集合,单向遍历
listiteration只能遍历list,双向遍历

说一下linux下面的一下常用命令?
常用:
Pwd 获取当前路径
Cd 跳转到目录
Su -u 切换到管理员
Ls ls 列举目录
文件操作命令:
文件
tail 查看
rm -rf
vi
文件夹
mkdir
rm -r

有没有使用过云主机?
没有使用过,但是有所了解。
云主机就是一些云服务运营商(阿里、华为等)提供的远程的服务器功能,我们开发者或者企业只需按需付费就可以租用对应的服务器。
使用ssh和sftp来进行操作

docker
安装docker

yum install docker-ce docker-ce-cli containerd.io

  1. 启动并加入开机启动

systemctl start docker

systemctl enable docker

6.验证是否安装成功

docker version

docker run hello-world

常用命令
1.docker pull [options] NAME[:TAG]
通过此命令可以docker远程仓库拉取镜像到本地

2.docker images [options] [REPOSITORY[:TAG]
当本地镜像非常多的时候要指定查看某一个镜像

3.docker run [options] IMAGE[:TAG] [COMMAND] [ARG…]
IMAGE是镜像的名字
COMMAND是运行起来的时候要执行什么命令.
ARG表示这条命令运行需要的参数.

查看运行的容器:
docker ps

更多关于运行的命令:
docker run --help

8080端口是否开启
netstat -na |grep 8080
是开启的那么访问 主机ip:8080 即可访问到nginx.

2.vue中的路由拦截器的作用?
路由拦截,权限设置
例如:当用户没有登录权限的时候就会跳转到登录页面,用到的字段requireAuth:true

3.axios的作用?
vue中的ajax,用于向后台发起请求
特点:
从浏览器中创建XMLHttpRequests

    从node.js创建http请求

    支持Promise API

    拦截请求和响应

    转换请求数据和响应数据

    取消请求

    自动转换json数据

    客户端支持防御XSRF
promise:
    一个对象用来传递异步操作的信息
    promise的出现主要是解决地狱回调的问题,无需多次嵌套
    本质:分离异步数据获取和业务
拦截器分为请求拦截器和响应拦截器
#请求拦截器
axios.interceptors.request.use(function(config){
    return config;
},function(error){
    return Promise.reject(error);
});
#响应拦截器
axios.interceptors.response.use(function(response){
    return response;
},function(error){
    return Promise.reject(error);
});

4.列举vue的常见指令。

1.文本插值:{{}}

2.DOM属性绑定:v-bind

3.指令绑定一个事件监听器:v-on

4.实现表单输入和应用状态之间的双向绑定:v-model

5.控制切换一个元素的显示:v-if和v-else

6.列表渲染:v-for

vue几种常用的指令
  答:v-for 、 v-if 、v-bind、v-on、v-show、v-else,v-model

5.列举Http请求中常见的请求方式?
get
向特定的路径资源发出请求,数据暴露在url中
post
向指定路径资源提交数据进行处理请求,数据包含在请求体中
options
返回服务器针对特定资源所支持的http请求方法,允许客户端查看,测试服务器性能
head
向服务器与get请求相一致的响应,响应体不会返回,可以不必传输整个响应内容
put
从客户端向服务器端传送的数据取代指定的文档的内容
delete
请求服务器删除指定的页面

6.对于MVVM的理解

MVVM 是 Model-View-ViewModel 的缩写。

Model代表数据模型,在Model中定义数据修改和操作的业务逻辑。
  View 代表UI 组件,将数据模型转化成UI 展现出来。
  ViewModel 同步View 和 Model的对象,连接Model和View。

viewmodel和model实现双向数据绑定

jsP是Servlet技术的扩展,所有的jsp文件都会被翻译为一个继承HttpServlet的类。也就是jsp最终也是一个Servlet.这个Servlet对外提供服务。
Servlet和JSP最主要的不同点在于JSP侧重于视图,Servlet主要用于控制逻辑。
Servlet如果要实现html的功能,必须使用Writer输出对应的html,比较麻烦。而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件,做界面展示比较方便而嵌入逻辑比较复杂。

servlet生命周期:
加载Servlet的class---->实例化Servlet----->调用Servlet的init完成初始化---->响应请求(Servlet的service方法)----->Servlet容器关闭时(Servlet的destory方法)

第一次接收请求,Servlet启动时,开始加载,servlet生命周期开始。Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等,当服务器决定将实例销毁的时候(服务器关闭)调用其destroy方法。

Servlet API中forward() 与redirect()的区别?
1、forward是服务器端的转向而redirect是客户端的跳转。
2、使用forward浏览器的地址不会发生改变。而redirect会发生改变。
3、Forward是一次请求中完成。而redirect是重新发起请求。
Forward是在服务器端完成,而不用客户端重新发起请求,效率较高

7.Vue的生命周期

1.什么是vue生命周期?
    答: Vue 实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为 Vue 的生命周期。

2.vue生命周期的作用是什么?
    答:它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。

3.vue生命周期总共有几个阶段?
    答:它可以总共分为8个阶段:创建前/后, 载入前/后,更新前/后,销毁前/销毁后。

4.第一次页面加载会触发哪几个钩子?
    答:会触发 下面这几个beforeCreate, created, beforeMount, mounted 。(创建前后,挂载前后)

5.DOM 渲染在 哪个周期中就已经完成?
    答:DOM 渲染在 mounted 中就已经完成了。

JavaScript 实现是由以下 3 个不同部分组成的:
核心(ECMAScript)
文档对象模型(DOM,整合js,css,html)
浏览器对象模型(BOM,整合js和浏览器)

简单地说,ECMAScript 描述了JavaScript语言本身的相关内容。

JavaScript 是脚本语言
JavaScript 是一种轻量级的编程语言。

JavaScript 是可插入 HTML 页面的编程代码。

JavaScript 插入 HTML 页面后,可由所有的现代浏览器执行。

为什么要用es?
es是一个高扩展、开源的全文检索和分析引擎,它可以准实时地快速存储、搜索、分析海量的数据

我们课程数据将来会非常多,所以采用以往的模糊查询,模糊查询前置配置,会放弃索引,导致课程查询效率非常低下,而我们使用ES做一个全文索引,我们将经常查询的课程的某些字段,比如说课程名,描述、价格还有id这些字段我们放入我们索引库里,可以提高查询速度

es解决原生Lucene使用的不足(只是一个库,配置及使用非常复杂),优化Lucene的调用方式,并实现了高可用的分布式集群的搜索方案

es流程
索引过程:

1) 有一系列被索引文件

2) 被索引文件经过语法分析和语言处理形成一系列词(Term) 。

3) 经过索引创建形成词典和反向索引表。

4) 通过索引存储将索引写入硬盘。

搜索过程:

a) 用户输入查询语句。

b) 对查询语句经过语法分析和语言分析得到一系列词(Term) 。

c) 通过语法分析得到一个查询树。

d) 通过索引存储将索引读入到内存。

e) 利用查询树搜索索引,从而得到每个词(Term) 的文档链表,对文档链表进行交,差,并得到结果文档。

f) 将搜索到的结果文档对查询的相关性进行排序。

g) 返回查询结果给用户。

rabbitmq流程

在最初状态下,生产者发送消息的时候

(1) 生产者连接到RabbitMQ Broker , 建立一个连接( Connection) ,开启一个信道(Channel)

(2) 生产者声明一个交换器,并设置相关属性,比如交换机类型、是否持久化等

(3) 生产者声明一个队列井设置相关属性,比如是否排他、是否持久化、是否自动删除等

( 4 ) 生产者通过路由键将交换器和队列绑定起来

( 5 ) 生产者发送消息至RabbitMQ Broker,其中包含路由键、交换器等信息

(6) 相应的交换器根据接收到的路由键查找相匹配的队列。

( 7 ) 如果找到,则将从生产者发送过来的消息存入相应的队列中。

(8) 如果没有找到,则根据生产者配置的属性选择丢弃还是回退给生产者

(9) 关闭信道。

(1 0) 关闭连接
消费者接收消息的过程:

(1)消费者连接到RabbitMQ Broker ,建立一个连接(Connection ) ,开启一个信道(Channel) 。

(2) 消费者向RabbitMQ Broker 请求消费相应队列中的消息,可能会设置相应的回调函数,
以及做一些准备工作

(3)等待RabbitMQ Broker 回应并投递相应队列中的消息, 消费者接收消息。

(4) 消费者确认( ack) 接收到的消息。

( 5) RabbitMQ 从队列中删除相应己经被确认的消息。

( 6) 关闭信道。

( 7) 关闭连接。

rabbitmq
如何避免消息重复消费
kafka实际上有个offset的概念,就是每个消息写进去,都有一个offset,代表他的序号,然后consumer消费了数据之后,每隔一段时间,会把自己消费过的消息的offset提交一下,代表我已经消费过了,下次我重启时,从上次消费到的offset消费

幂等性,通俗点说,就一个数据,或者一个请求,给你重复来多次时要确保对应的数据是不会改变不能出错的。

怎么保证消息队列消费的幂等性?

结合业务来思考:

(1)如果数据要写库,先根据唯一条件查一下,如果这数据有了,就不再插入了,更新一下

(2)如果写redis,那没问题了,反正每次都是set,天然幂等性

(3)如果不是上面两个场景,需要让生产者发送每条数据的时候,加一个全局唯一的id,消费拿到了之后,先根据这个id去比如redis里查一下,查询之前是否消费过,如果没有消费过,进行处理,然后这个id写入redis。如果消费过了,就不再处理,保证不重复处理相同的消息。

为什么要用消息队列:削峰,异步,解耦

rabbitMQ消息可能丢失的情况:

1.发送方发出消息但没有进入队列。
2.接收者接到消息,但处理过程出现错误。
3.队列或者交换机宕机。

针对上面的三种情况,rabbitMQ有三种应对措施。

publisher-confirms(发送方确认模式)
将信道设置成confirm模式(发送方确认模式),则所有在信道上发布的消息都会被指派一个唯一的ID。
一旦消息被投递到目的队列后,或者消息被写入磁盘后(可持久化的消息),信道会发送一个确认给生产者(包含消息唯一ID)。
如果RabbitMQ发生内部错误从而导致消息丢失,会发送一条nack未确认的消息。

消息确认机制(ACK)
当消费者获取消息后,会向RabbitMQ发送回执ACK,告知消息已经被接收。不过这种回执ACK分两种情况:
自动ACK:消息一旦被接收,消费者自动发送ACK
– 如果消息不太重要,丢失也没有影响,那么自动ACK会比较方便
手动ACK:消息接收后,不会发送ACK,需要手动调用
– 如果消息非常重要,不容丢失。那么最好在消费完成后手动ACK,否则接收消息后就自动ACK,RabbitMQ就会把消息从队列中删除。如果此时消费者宕机,那么消息就丢失了

持久化
消息持久化,当然前提是队列和交换机必须持久化
RabbitMQ确保持久性消息能从服务器重启中恢复的方式是,将它们写入磁盘上的一个持久化日志文件,当发布一条持久性消息到持久交换器上时,Rabbit会在消息提交到日志文件后才发送响应。
一旦消费者从持久队列中消费了一条持久化消息,RabbitMQ会在持久化日志中把这条消息标记为等待垃圾收集。如果持久化消息在被消费之前RabbitMQ重启,那么Rabbit会自动重建交换器和队列(以及绑定),并重新发布持久化日志文件中的消息到合适的队列。

两种微服务之间的授权方式,
一种是和用户上下文有关的请求,通过Feign的拦截器转发用户请求中的Token的给下游微服务,
二种是微服务之间调用可能和当前用户上下文无关,我们采用在拦截器中采用客户端模式生成一个Token转发给下游服务的方式,Hystrix的隔离策略:原理就是把调用线程A中的请求通过RequestContextHolder获取到,放到新的线程B中的RequestContextHolder中即可

auth2的四种授权模式

密码模式(resource owner password credentials)

授权码模式(authorization code)

简化模式(implicit)

客户端模式(client credentials)

springboot注解
1)@SpringBootConfiguration // 继承了Configuration,表示当前是注解类

2)@EnableAutoConfiguration // 开启springboot的注解功能,springboot的四大神器之一,其借助@import的帮助

3)@ComponentScan(excludeFilters = { // 扫描路径设置(具体使用待确认)

为什么要使用 spring?
spring 提供 ioc 技术,容器会帮你管理依赖的对象,从而不需要自己创建和管理依赖对象了,更轻松的实现了程序的解耦。
spring 提供了事务支持,使得事务操作变的更加方便。
spring 提供了面向切片编程,这样可以更方便的处理某一类的问题。

spring ioc :控制反转,指的是当前对象对内部成员的控制权交给其他(类,第三方容器)来管理
spring aop : 面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术

spring的事务传播机制:
1.如果有事务,支持该事务,如果没有事务
1.开启一个事务
2.执行非事务
3.没有可活动的事务,抛出异常
2.总是开启一个事务,挂起已经存在的事务
3.非事务执行
1.把所有的事务挂起
2.如果有可以活动的事务就抛出异常
4.如果有可以活动的事务,可以进行嵌套,如果没有事务就开启事务

spring注解
1.声明bean的注解

@Component 和spring做关联,交给spring管理
@Service 在业务逻辑层使用(service层)

@Repository 在数据访问层使用(dao层)

@Controller 在展现层使用,控制器的声明(C)
2.注入bean的注解

@Autowired:由Spring提供

@Resource:由JSR-250提供

3.spring 自动装配 bean 方式?
no:默认值,表示没有自动装配,应使用显式 bean 引用进行装配。
byName:它根据 bean 的名称注入对象依赖项。
byType:它根据类型注入对象依赖项。
autodetect:容器先通过构造函数使用 autowire 装配,如果不行,则通过 byType 自动装配

4.spring 事务实现方式
声明式事务:声明式事务也有两种实现方式,xml 配置文件的方式和注解方式(在类上添加 @Transaction 注解)。
编码方式:提供编码的形式管理和维护事务。

5.spring 支持 5 种作用域
singleton:spring ioc 容器中只存在一个 bean 实例,以单例模式存在,是系统默认值;
prototype:每次调用 bean 时都会创建一个新的示例,频繁创建和销毁 bean 会带来很大的性能开销。

Web 环境下的作用域:
request:每次 http 请求都会创建一个 bean;
session:同一个 http session 共享一个 bean 实例;
global-session:globalsession 提供一个全局性的 http session。用于 portlet 容器,因为每个 portlet 有单独的 session

6.spring 有哪些主要模块?
spring core:框架的最基础部分,提供 ioc 和依赖注入特性。
spring context:构建于 core 封装包基础上的 context 封装包,提供了一种框架式的对象访问方法。
spring dao: 提供了JDBC的抽象层。
spring aop:提供了面向切面的编程实现
spring Web:提供了针对 Web 开发的集成特性。
spring Web mvc:spring 中的 mvc 封装包提供了Model-View-Controller(MVC)的实现。

7.spring 常用的注入方式
setter 属性注入
构造方法注入
注解方式注入

8.spring创建Bean的三种方式
第一种方式:使用默认构造函数创建
在spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他属性和标签时
采用的就是默认构造函数创建bean对象,此时如果类中没有默认构造函数,则对象无法创建
第二种方式: 使用普通工厂中的方法创建对象(使用某个类中的方法创建对象,并存入spring容器)

    第三种方式:使用工厂中的静态方法创建对象(使用某个类中的静态方法创建对象,并存入spring容器)

mybatis

mybatis是一个持久层框架
它封装了jdbc操作的很多细节,使开发者只需要关注sql语句本身,不需要关注注册驱动,创建连接等繁杂过程,实现了对结果集的封装。
MyBatis可以使用XML或者注解进行映射和配置,通过将参数映射到配置的SQL,然后解析为执行的SQL语句,查询后将结果集映射成java对象返回,可以编写动态sql等

常用标签,注解
@Insert : 插入sql , 和xml insert sql语法完全一样@Select : 查询sql, 和xml select sql语法完全一样
@Update : 更新sql, 和xml update sql语法完全一样
@Delete : 删除sql, 和xml delete sql语法完全一样
@Param : 入参
@Results : 设置结果集合
@Result : 结果
@ResultMap : 引用结果集合
@SelectKey : 获取最新插入id
@where
@if
@choose

说一下 MyBatis 的一级缓存和二级缓存?
一级缓存:基于 PerpetualCache 的 HashMap 本地缓存,它的生命周期是和 SQLSession 一致的,在有多个 SQLSession 或者分布式的环境中数据库操作,可能会出现脏数据。当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认一级缓存是开启的。

二级缓存:也是基于 PerpetualCache 的 HashMap 本地缓存,不同在于其存储作用域为 Mapper 级别的,如果多个SQLSession之间需要共享缓存,则需要使用到二级缓存,并且二级缓存可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现 Serializable 序列化接口(可用来保存对象的状态)。
开启二级缓存数据查询流程:二级缓存 -> 一级缓存 -> 数据库。
缓存更新机制:当某一个作用域(一级缓存 Session/二级缓存 Mapper)进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。

MyBatis-plus是一款MyBatis的增强工具,在MyBatis 的基础上只做增强不做改变
1)依赖少:仅仅依赖 Mybatis 以及 Mybatis-Spring 。

2)损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作 。

3)预防Sql注入:内置 Sql 注入剥离器,有效预防Sql注入攻击 。

4)支持代码生成:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码(生成自定义文件,避免开发重复代码),支持模板引擎、有超多自定义配置等

5)内置分页插件:基于 Mybatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通List查询。

注解
@TableField
描述:字段注解(非主键)
@TableId
描述:主键注解
@TableName
描述:表名注解

spring,springboot,springMVC的区别?

springboot整合了spring和springMVC,springMVC只是spring处理web层的一个模块

spring 的 ioc 和 aop ioc 提供了依赖注入的容器 aop 解决了面向横切面的编程 然后在此两者的基础上实现了其他延伸产品的高级功能
Spring MVC 呢是基于 Servlet 的一个 MVC 框架 主要解决 WEB 开发的问题
因为 Spring 的配置太复杂了 各种 XML JavaConfig hin 麻烦 于是推出了 Spring boot 约定优于配置 简化了 spring 的配置流程.

动态代理的实现:
java动态代理其实是一种设计模式,是Spring AOP 的核心技术。通俗的解释就是往没有耦合关系但却需要经过同样步骤处理的代码里加上这些“同样步骤”

1.JDK代理使用的是反射机制实现aop的动态代理,CGLIB代理使用字节码处理框架asm,通过修改字节码生成子类。所以jdk动态代理的方式创建代理对象效率较高,执行效率较低,cglib创建效率较低,执行效率高;
2.JDK动态代理机制是委托机制,具体说动态实现接口类,在动态生成的实现类里面委托hanlder去调用原始实现类方法,CGLIB则使用的继承机制,具体说被代理类和代理类是继承关系,所以代理类是可以赋值给被代理类的,如果被代理类有接口,那么代理类也可以赋值给接口。

线程安全: 指多个线程在执行同一段代码的时候采用加锁机制,使每次的执行结果和单线程执行的结果都是一样的,不存在执行程序时出现意外结果。

线程不安全: 是指不提供加锁机制保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。

Feign,Feign集成了Ribbon是一种负载均衡的HTTP客户端, 使用Feign调用API就像调用本地方法一样,从避免了调用目标微服务时,需要不断的解析/封装json 数据的繁琐。Ribbon+eureka是面向微服务编程,而Feign是面向接口编程。

springcloud五大组件
eureka,注册中心
feign,服务之间的调用
rabbin,负载均衡
hystrix,熔断
zuul网关

为什么用注册中心进行服务注册和发现
如果我们没有用注册中心,服务之间通过IP和端口进行联系,当我们的服务崩溃了的时候,换个ip和端口时需要改我们的代码,麻烦,但是有了注册中心之后,我们把服务注册到注册中心,并取名,当服务崩溃的时候我们只需要通过名字去匹配服务(已经注册到eureka保存了),不需要再书写我们的代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值