java基础面试题

线程池创建    ThreadPoolExecutor

核心线程数,    最大线程数,    空闲线程存活时间,    时间单位,    任务队列( 用来保存等待执行任务的队列 )   线程工厂类( 创建线程设置优先级
饱和策略 ( 当提交的任务过多而不能及时处理时,我们可以定制策略来处理任务 )

公平锁和非公平锁的区别

公平锁:    多个线程按照申请锁的顺序去获得锁,线程会直接进入队列排队    优点:    所有线程都能得到资源,不会饿死在队列中
            缺点:    吞吐量下降很多,可能会造成其他线程阻塞
非公平锁:     多个线程去获取锁的时候,会直接去尝试获取,获取不到,再去进入队列,如果获取到就直接获取锁
优点:        可以减少cpu唤醒线程的开销,
缺点:    可能会导致队列中间的线程一直获取不到锁或者长时间获取不到锁
线程锁
主要用来给方法,代码块加锁,当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或代码,    比如synchronized    lock等
进程锁
为了控制桶一操作系统中多个子进程访问某个共享资源,因为进程具有独享性,各个进程无法访问其他进程的资源

分布式锁应该具备哪些条件

1.一个方法在同一时间只能被一个机器的一个线程执行
2.高可用高性能的获取与释放锁
3.具备锁失效机制,防止死锁

分布式锁三种实现方式

基于数据库实现分布式锁
基于缓存(redis)实现分布式锁    
基于zookeeper实现分布式锁

分布式锁的特点

互斥性    任意时刻,只能有一个客户端获取锁,
安全性      锁只能被持有该锁的客户端删除,不能被其他客户端删除
死锁        获取锁的客户端因为某种原因而未释放锁
容错    当部分节点宕机    客户端仍能获取锁或释放锁

redis如何实现分布式锁

SETNX key value     此命令具有原子性,只有在key不存在情况下,才能set成功
    1.加锁最简单的方法就是setnx命令,key是锁的唯一标识,按业务决定命名,
2.解锁,有加锁就有解锁,释放锁的最简单方法就是执行del指令,

synchronized和lock的区别

sunchronized是jvm层面实现的,java提供的关键字
lock是api层面的锁
synchronized不需要手动释放锁,lock需要手动释放锁
sunchronized锁适合代码少量的同步问题    lock锁适合大量代码同步问题

hashMap底层原理

底层:    分为jdk1.7和jdk1.8,    1.7之前是数组+链表,使用的是头插法    1.8之后是数组+链表或红黑树采用的是尾插法    当单链表大于等于8并且hash桶大于等于64的时候, 单链表会转换成红黑树 在红黑树中的节点小于等于6的时候它会重新转换成单链表    
扩容机制 :    hashMap初始长度默认是16负载因子是0.75    它的扩容机制是使用懒扩容    就是说在首次调用 put 的时候才会进行判断然后扩容,
1.将数组长度扩容为原来的2倍
2.将原来数组中的元素进行重新放到新的数组中
什么时候进行扩容
1. 在首次调用put方法的扩容
2 . 当HashMap中的元素个数超过数组大小 (数组长度*负载因子)就会进行扩容因为数组默认大小是16也就是说当HashMap中的元素个数超过16*0.75=12的时候就把数组的大小扩展到2*16=32然后重新计算每个元素在数组的位置,
3. 当HashMap中的其中一个链表的对象个数如果达到了8个,此时如果数组长度没有达到64, 那么HashMap会先扩容解决,如果已经达到了64那么这个链表会变成红黑树,    节点类型Node变成TreeNode类型    如果映射关系被移除后,下次执行resize方法的时候判断树的节点个数低于6个,也会再把树转为链表

HashMap是线程不安全的    

为什么HashMap不是线程安全的

HashMap在并发执行put操作时会引起死循环,导致cpu利用率100%
因为多线程会导致HashMap的Node链表形成环形数据结构,一旦形成环形数据结构,Node的next节点永远不为空,就会在获取Node时产成死循环

如何让HashMap的线程安全

1.替换成Hahtable,    Hashtable通过对整个表上锁实现线程安全,因此效率低
2.使用synchronizeMap方法包装一下比如
public staticMapsynchronizeMap(MapM)返回指定映射支持的同步
3. 使用ConcurentHashMap    它使用分段锁来保证线程安全

加载因子为啥是0.75呢(泊松分布)

1. 加载因子过高 ,虽然减少了开销提高了空间利用率,但同时也增加了时间成本
2. 加载因子过低 ,虽然减少了查询时间成本,但是空间利用率很低,同时提高了rehash操作的次数,   
选择0.75作为默认的加载因子,完全是时间和空间成本上寻求的一种折中选择 

hashmap和hashtable的区别

底层数据结构不同    hashMap1.7之前是数组+链表1.8之后加入了红黑树    HashTable是数组+链表
扩容机制不同    HashMap扩容规则是当前容量翻倍,Hasntable扩容规则为当前容量翻倍+1
实现方式不同    HashMap继承的是AbstractMap类,Hashtable继承的是Dictionary类
初始容量    HashMap初始容量的16,    Hashtable初始容量是11
添加key-value的hash值算法不同    HashMap添加元素是使用自定义的哈希算法,    而Hashtable是直接采用key的hashCode()
Hashtable的健或值,不支持null,    Hashmap的健值则支持null

重写equals方法为啥要重写hashcode方法

1.使用hashcode方法提取校验,避免每一次比对都调用equals方法,提高效率
2.保证是同一个对象,如果重写了equals方法而没有重写hashcode方法会出现equals相等hashcode不相等的情况
hashcode方法就是为了避免这种情况的出现

深拷贝和浅拷贝的区别

浅拷贝是指向被复制的内存地址,而深拷贝是创建新的内存地址用于存放复制的对象
浅拷贝对于引用类型的属性只是引用原对象的内存地址,而深拷贝是所有属性都创建新的对象
冒泡排序两层循环    依次比较相邻的两个元素,如果顺序错误就交换位置
如果有n个元素,需要比较n-1轮,
每一轮需要比较n-i次,i表示第几轮
数组中有length()方法吗,String中有length()方法吗
数组中没有length()方法,有length()属性,String中有length()方法

int和Integer有什么区别

Integer 是int的包装类, int 是基本数据类型
Integer变量必须实例化后,才能使用,int不需要
Integer实际对象的引用,指向此new的Integer对象,int是直接存储数据值的
Integer默认值是null,int的默认值是0

数组和ArrayList的区别

数组是类型安全的,ArrayList是类型非安全的
ArrayList长度可变,数组长度不可变
数组存储的是数据类型,ArrayList存储的是对象,

Arrray和ArrayList的区别

Array可以包含基本数据类型和对象类型,ArrayList只能包含对象类型
Array的大小是固定的,ArrayList的大小是动态的
ArrayList提供了添加,插入或移除,    而Array只能一次获取或设置一个元素值

ArrayList和LinkedList的区别

1. 底层结构     ArrayList是实现了基于动态数组的数据结构,而LinkedList是基于链表的数据结构;
2 .初始长度     Arraylist的初始化默认是10,而LinkedList默认初始化为空
3. 扩容机制    ArrayList实现了List接口,继承了AbstractList抽象类,底层是基于数组实现的并实现的动态扩容    LinkedList是一个继承自AbstractSequentialList的双向链表,因此它也可以被当作堆栈,队列或双端队列进行操作
4. 使用场景    ArrayList使用在查询比较多,但是插入和删除比较少的情况,而LinkedList用在查询比较少而插入删除比较多的情况
  • 抽象类和接口有什么区别

抽象类 :    可以定义构造器,可以有抽象方法和具体方法,可以定义成员变量,可以包含静态方法,一个类只能继承一个抽象类,抽象类是不能实例化的类
接口 :不能定义构造器,方法全部是抽象方法,不能有静态方法,接口中定义的成员变量实际上都是常量,一个类可以实现多个接口
相同 :都不能实例化,可以将抽象类和接口类型作为引用类型

阐述静态变量和实例变量的区别

存储区域不同:    静态变量存储在静态存储区,普通变量存储在堆中
静态变量与类有关,实例变量与实例有关
内存分配方式不同
生命周期不同

Error和Exception有什么区别

首先他们都是继承了Throwable类,在Java中只有Throwable类型的实例才可以被抛出或捕获,
EXception:     是程序正常运行中可以预见的意外情况,可以被捕获并处理,
Exception又分为可检查异常(checked)和不检查异常(unchecked)
Error:    表示系统错误,不能通过程序来进行错误处理,
表示恢复不是不可能但很困难的情况下的一种严重问题
try{}里面有个return语句,那么紧跟在这个后面try后的finally{}里面的代码会不会被执行
会执行,在return中间执行,
如果finally中也有return,则会直接返回并终止程序,函数栈中的retrun不会被完成
如果finally中没有return,则在执行完finally中的代码之后,会将函数栈中的try中retrun内容返回并终止程序;

常用的集合

List,Set,Map是否都继承Collection接口
java基础面试题_第1张图片
List:有序可重复,
Set:无序,唯一
Map,基于hash表,key不可以重复,

Thread类的sleep()方法和对象的wait()方法都可以让线程暂停,它们有什么区别

相同点:一旦执行,都可以让当前线程进入阻塞状态,
不同点:     两个方法所属类型不同,sleep()属于Thread
    wait()属于Objiect,
调用的要求不同:     sleep可以在任何需求的场景下调用,wait()必须在同步代码块或者同步方法中调用.
sleep必须捕获异常,而wait,不需要捕获异常
关于是否释放同步锁对象,如果两个方法都使用在同步代码块(同步方法)中,sleep()不会释放同步锁对,而wait()会释放同步锁对象.

==和equals的区别是什么?

区别就是==是运算符,equals是方法
如果比较的是基本数据类型的对象,==比较的是数值是否相等,如果是引用数据类型,比较的是对象地址值是否相等
equals()用来比较方法两个对象的内容相等,且不能比较基本数据类型

什么是反射机制?

在运行状态中对于任意一个类(class)文件都能够知道这个类的属性和方法,
动态获取类中的信息就是java反射机制
反射应用场景
1.用JDBC连接数据库时使用Class,forName通过反射加载数据库的驱动程序
2.Spring框架的IOC创建对象以及AOP功能
3.动态配置实例的属性

什么是代理模式.为啥要用代理模式(也叫做AOP代理)

代理模式是一种设计模式,提供了对目标对象另外的访问方式,即通过代理对象访问目标对象,
好处:可以在目标对象实现的基础上增强额外的功能操作,即扩展目标对象的功能
静态代理:   在使用时需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或继承父类
动态代理 :    代理对象,不需要实现接口,代理对象的生成是利用jdk的api,在内存中构建代理对象,动态代理也叫jdk代理接口代理
cglib代理:    也叫做子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展
  • JDK代理和CGLIB的区别

java*动态代理是利用反射机制生成一个实现代理接口的匿名类
而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来
如果目标对象实现了接口,默认情况下会采用JDK的动态代理也 可以强制使用CGLIB实现AOP
如果目标对象没有实现了接口,必须采用CGLIB库
short s1=1,s1=s1+1 有错吗,short s1=1,s1+=1有错吗
对于short s1=1,s1=s1+1由于1是int类型,因此s1+1运算结果是int类型需要强制转换类型才能赋予给short类型,
而short s1=1,s1+=1可以正常编译,因此s1+=1相当于s1=(short)(s1+1)其中隐含了强制类型转换

Spring和SpringBoot有什么不同

Spring:     是一个开源框架,可以接管web层,业务层,dao层,持久层的组件
SpringBoot :    是一个微服务框架,延续了spring框架的核心思想Ioc和Aop,简化了应用的开发和部署,创建了独立的spring应用,尽可能自动配置spring应用,没有代码生成和xml配置要求
+-
java基础面试题_第2张图片
  • 常见Exception
  • RuntimeException
  • IOException (Io异常)
  • SQlException (SQL异常)
RuntimeException下的常见异常
NullPointerException ( 空指针异常 )
ClassCastException -强制类型转换异常
IIegalArgumentException传递非法参数异常
ArithmeticException-算术运算异常
IndexOutofBoundsException- 下标异常
  • 谈谈对Dubbo的理解

Dubbo是一个分布式,高性能透明化的RPC服务框架,提供服务自动注册,自动发现等高效服务治理方案,    可以和Spring框架无缝集成,    但是Dubbo使用的是缺省协议,不适合传送大数据量的服务,比如传文件,传视频等
  • Dubbo的主要应用场景

透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需要简单配置,没有任何api侵入
服务自动注册与发现,不再需要写死服务提供方地址,注册中心
  
基于接口查询服务提供者的ip地址,并且能够平滑添加或删除服务提供者
软负载均衡及容错机制,可在内网替代f5等硬件负载均衡器,降低成本,减少单点
  • DUbbo超时时间怎么设置

设置超时时间有两种,
1.在服务提供端设置超时时间:    在Dubbo的用户文档中推荐如果能在服务端多配置就尽量多配置,因为服务提供者比消费者更清楚自己提供的服务特性
2. 服务消费者端,设置超时时间,    如果在消费者端设置了超时时间,以消费者端为主,即优先级更高,因为服务调用方设置超时时间控制性更灵活,如果消费方超时,服务端线程不会停止,会产生警告
  • Dubbo的核心功能

Remoting:    网络通信框架,    提供了对多种NIo框架抽象封装,包括同步转异步和请求-响应模式的信息交换方式
Cluster:    服务框架,    提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持,
Registry:    服务注册,基于注册中心目录服务,使消费方能动态的查找服务提供者,使地址透明,使提供方可以平滑添加或减少机器
  • Dubbo有哪些注册中心

  • Multicatst注册中心: 不需要任何节点只需要广播地址,就能进行服务注册和发现,基于网络中组播传输实现
  • zookeeper注册中心 :基于分布式协调系统Zookeeper实现采用watch机制实现数据
  • redis注册中心 :基于redis实现,采用key/map存储
  • simple注册中心
  • 默认采用Zookeeper注册中心
  • Zookeeper是什么

  • 是一个分布式协调服务的开源框架,主要用来解决分布式集群中应用系统一致性问题,本质上是一个分布式的小文件存储系统,提供基于类似文件存储目录树方式的数据存储.

Zookeeper的数据模型

是一个树形结构,类似于前端开发中tree.js组件
每个节点称之为znode,它可以有子节点也可以有数据
每个节点分为临时节点和永久节点,
每个zk节点都有各自的版本号,可以通过命令行来显示节点信息
每个节点数据发生变化,那么节点的版本号会累加(乐观锁)
每个节点存储的数据不宜过大,几k即可

    Zookeeper应用场景

1.数据发布和订阅,     主要应用于配置中心,将相关数据发布到配置中心然后由应用服务去订阅
2.负载均衡     基于域名服务,进行相应的负载,从而达到请求负载到各个应用中  
3.命名服务    主要应用于Rpc服务,比如Dubbo等框架
4.分布式锁:     分布式锁是控制分布式系统同步访问共享资源的一种方式,
5.分布式协调/通知

注册中心为啥用nacos,不用Eureka

1.nacos在自动或手动下线服务,使用消息机制通知客户端,服务实例的修改很快响应    Eureka只能通过定时任务剔除无效的服务
2.nacos可以根据namespace命名空间,Datald,Group分组,来区分不同环境    不同配置

    MongoDb是什么

是属于文档类型的非关系型数据库包括开源.高性能高可用.可扩展的数据逻辑层次关系

数据类型

null,    false和true    数值     数组    
日期    正则表达式       嵌套文档    对象
业务场景
网站数据:    非常适合实时的插入.更新与查询
物流场景    使用Mongo存储订单信息订单在运送过程中不断跟新
游戏场景    使用Mongo存储游戏用户信息,用户的转变积分等
也可用于JSON数据的存储:    非常时候文档化格式的存储和查询
NGinx是什么    是一个高性能的HTTP和泛型代理服务器,及电子邮件代理服务器    同时也是一个非常高效的反向代理    负载均衡
作用:   
 反向代理:    将多态服务器代理成一台服务器
负载均衡:    将多个请求均匀的分配到多台服务器上,减轻服务器的压力,提高服务的吞吐量
动静分离:    nginx可以用作静态文件的缓存服务器,提高访问速度
  • Redis存储哪几种数据类型

String:     最基本的数据类型,二进制安全的字符串,最大512M
list:     按照添加顺序保存顺序的字符串列表
set:    无序的字符集合,不存在重复的元素
hash:    key_value对的一种集合,和java中hashmap类似
zset  :    已排序的字符串集合
  • 应用常场景

缓存,热点数据,分布式,session,分布式锁,
计数器,文章的阅读量,微博点赞数等,允许一定的延迟,先写Redis再定时同步到数据库
  • Redis的数据怎么持久化

Redis提供了两种持久化的方式,分别是RDB,和AOF
RDB:    简而言之,就是在不同的时间点,将redsi缓存的数据生成快照存储到磁盘等介质上
AOF:     则是换个角度来实现持久化,就是将redis执行过的所有写指令记录下来,  在下次redsi重新启动时只要把这些写指令从前到后在重复执行一遍,就可以实现数据恢复了
RDB和AOF也可以同时使用,在这种情况下,如果redsi重启的话则会优先采用AOf方式来进行数据恢复,这是应为AOF方式的数据恢复完整度更高

redis 过期键的删除策略(默认采用定期删除+惰性删除策略)

1.定时任务删除,    在设置健的过期时间的同时创建一个定时器,    让定时器在健的过期时间来临时立即执行对健的删除操作
2.惰性删除,放任健过期不管,但是每次从健空间中获取健时,都检查取得的健是否过期,如果过期就删除该健,如果没有就返回该健
3.定期删除,每隔一段时间就对数据库进行一次检查,删除里面的过期健,
定期删除+惰性删除是如何工作的呢
1.定期删除,redis默认每个100ms检查是否有过期的key,有过期的key则删除,    需要说明的是    redis不是每个100ms将所有的key检查异常,而是随机抽取进行检查,因此如果只采用定期删除策略,会导致很多key的时间没有删除
2.于是,惰性删除派上用场了,也就是说在你获取某个key的时候,redsi会检查一次,这个key如果设置了过期时间那么是否过期,如果过期就删除

为什么不采用定时删除策略呢

定时删除用一个定时器来负责监视key,过期则自动删除,虽然内存及时释放,但是十分消耗cpu资源,在大并发请求下,cpu要将时间应用在处理请求,而不是删除key
采用定期删除+惰性删除就没有其他问题吗?
不是的,如果定期删除没删除key,然后你也没及时请求key,    也就是说惰性删除也没生效,这样redis的内存会越来越高,那么就应该采用内存淘汰机制在redis.conf中有一行配置
  • 使用redis的常见问题

缓存和数据库双写不一致问题    :请求先是从redis中查询,如果redis中不存在数据就不会走数据库,如果不能保证缓存跟数据库的一致性就会导致请求获取的数据不是最新数据
缓存雪崩问题    即缓存同一时间大面积的失效,这个时候又来一大波请求,结果请求都怼到数据库上,从而导致数据库连接异常
缓存穿透问题:    缓存穿透,即黑客故意去查询缓存中不存在的数据,导致所有的请求怼到数据库上,从而数据库连接异常
缓存高并发问题:    指同时有多个子系统,set同一个key值
  • 相应问题解决方案

缓存和数据库双写不一致:    1. 编写删除缓存的接口,在更新数据库的同时调用删除缓存的接口删除缓存中的数据
2.消息队列:Amq,消息通知
缓存雪崩:    给缓存的失效时间加一个随机值,避免集体失效,
使用互斥锁,或者搭建redsi集群
缓存穿透:    利用互斥锁,缓存失效的时候先去获得锁,得到锁了再去请求数据库,没得到锁,则休眠一段时间重试     或者采用异步更新策略,无论key是否取到值,都直接返回
缓存高并发 :     准备一个分布式锁,让请求都去抢锁,抢到锁就去做set操作
  • redis有哪些安全机制

持久化机制
内存淘汰机制与缓存过期处理    清除最少用的旧内存,然后保存新的内存 
主从机制    也叫读写分离模式,
哨兵机制    master挂了,继续保证可用性,实现继续试写

redids集群三种方式

1.主从模式       读写分离,负载均衡,故障恢复,数据冗余(实现数据热备份,)    高可用基石(基于主从复制,构建哨兵模式与集群,实现redis的高可用方案)
2.哨兵模式    监控master存活检测,自动故障转移,
3.Cluster模式    主要是集群通信,数据迁移,定时任务等等,

redis内存溢出怎么处理

1.加内存,   
2.搭建集群    
3.给key设置超时时间,利用内存淘汰机制    
  • mq有哪些优点

1.应用解耦,    生产者只与mq有关系,生产者和消费者之间耦合性是最低的
2.异步提速,     生产者只需要发送消息给mq,不需要等待消费者业务来    完成
3.肖峰填谷 ,    峰值降低,低估能让服务继续消费消息
  • RabbitMQ的使用场景

1.单发送单接受:    使用场景,简单的发送和接受 , 没有特别的处理
2.单发送多接受:    一个发送端,多个接收端,如分布式的任务发布,为了保证消息发送的可靠性,不丢失消息,使消息持久化,同时为了防止接收端在处理消息时down掉,只有在消息处理完成后才发烧ack消息
3.发布订阅模式:    发送端发送广播消息,多个接受端接收
4.按topic发送接受   :    发送端不只按固定的routing key发送消息,而按照字符串"匹配"发送,接收端同样如此
  • Rabbitmq如何保证消息不丢失

生产者提交给消息服务器时,使用确认机制
消息服务器给对应的队列,交换机等都持久化,保证数据的不丢失
消费者采用消息确认机制,保证数据的不丢失

Rabbitmq如何防止消息堆积

1.排查消费者的消费性能瓶颈
2.增加消费的多线程处理
3.部署增加多个消费者  或新增消息队列
  • 如何保证消息有序

1.rabbitmq拆分多个queue,每个queue由一个consumer消费,但是会造成吞吐量降低
2.或者就一个queue但是对应一个consumer,然后这个consumer内部用内存队列做排队,然后分发给底层不同的worker来处理

mq重复消费解决方式

利用数据库的唯一约束,给这个消息做一个唯一主键,避免导致主键冲突,避免数据库出现脏读数据
redis设置全局唯一id    给消息分配一个全局id,并存放在redis里,在消费接口上先在redis中查看是否存在全局id,如果存在,调用消费者并删除全局id,如果不存在,不做后续操作
多版本(乐观锁)机制    给业务数据添加一个版本号,每次更新数据前,比如当前版本和消息中的版本是否一致,如果一致就更新数据并且版本号+1,如果不一致就不更新

kafka消息丢失的场景和解决方案    kafka默认是同步方法

场景    acks=0时,不和kafka集群进行消息接受确认,则当网络异常或者缓存区满了等    消息可能丢失
acks=1时    在同步模式下,只有leader确认接受成功后但挂掉了,副本没有同步,消息可能丢失
解决方案    对于消息丢失,    
同步模式下,确认机制设置为-1,即让消息写入leader和Follower之后再确认消息发送成功 
异步模式下,为防止缓冲区满,可以在配置文件设置不限制阻塞
对于消息重复    将消息的唯一标识保存到外部介质中,每次消息时判断是否处理过即可
 
  • 拦截器和过滤器的区别

1.拦截器是基于java的反射机制的,而过滤器是基于函数回调的
2.拦截器不依赖与servlet容器,过滤器依赖servlet容器
3.拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用
4.拦截器可以获取IOC容器中的各个bean,而过滤器不行,在拦截器里注入一个service,可以调用业务逻辑
5.拦截器可以访问action上下文,值栈里的对象,而过滤器不能访问
  • Spring boot常用注解及其功能

全局注解:
@SpringBootApplication:    标识一个SpringBootg工程,是启动类,     组合注解包括@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan
@Value:    简单属性的依赖注入
@Autowired:     对象属性注入 
@ComponentScan:    组件扫描
@Bean:    表在方法上,用于将方法返回值对象存入容器
@ Resoure:    按照属性名称依赖注入
@ Transactional:    此注解可以标在类上,也可标在方法上,表示当前类中的方法具有事物管理功能
@Autowired和@Resource的区别
@Autowired默认按类型装配,默认情况下要求依赖对象必须存在
@Resource的默认按照名称进行装配,名称可以通过name属性进行指定
  • Spring MVC常用注解

RestController   是@ResponseBody和@Controller的组合注解,用于标注控制层组件,返回json格式
@Controller:    标记控制层组件
@RequestMapping:    明确请求路径,衍生出来的有@GetMapping,@postMapping,@PutMapping,@DeleMapping,@PatchMapping
@RequestBody:    允许reques的参数在request体中,常常结合前端post请求进行前后端交互
@ResponseBody:    支持将参数放在reques体中,通常返回json格式
@PathVariable :    用来接受参数,此主解放在参数前

SpringBoot执行流程

1.首先新建一个SpringApplication对象
2.执行对象的Run方法
3.通过对配置的启动类所在包及子包中的类进行扫描,对于Spring相关注解的类,通过反射为其创建代理对象,并交由Spring容器管理
  • Spring中@Bean生命周期

1.实例化一个 Bean ,也就是常说的 new 一个对象
2.B按照上下文对实例化的 Bean 进行配置,也就是IOC注入
3.如果 Bean 实现了 BeanNameAware 接口的话,会调用 setDeabName ()方法,此处传递是是Spring配置文件中的Bean的id值
4.如果Bean实现了 BeanFactoryAware 接口的话,Spring会调用 setBeanFactory ()方法,将 BeanFctory 容器实例传入
5.如果Bean实现了 ApplicationContextAware 接口的话,Spring将调用Bean的 setApplicationContext ()方法,将Bean所在应用上下文引用传入进来
6.如果Bean实现了 BeanPostProcess 接口,Spring就将调用它们的 postProcessBeforeInitialization ()前置方法
7.如果Bean在Spring配置文件中配置了 init - method ,属性会自动调用其配置文件的初始化方法
8.如果Bean实现了 BeanPostProcess 接口,Spring就将调用它们的postProcessAfterInitialization()后置方法
9.此时,Beean已经准备就绪,可以被应用程序使用,当Bean不再需要时,会经过清理阶段,
10,如果bean实现了DisposableBean接口,Spring将调用它们的destory()接口方法,同样,如果bean使用了destory-method生命销毁方法,该方法也会被调用
  • 简单回答
  • 1.通过构造方法实例化Bean对象, 如果有多个构造方法,则要推断构造方法
  • 2.通过setter方法设置对象的属性
  • 3.通过Aware( BeanNameAware )接口,调用Bean的setBeanName()方法传递Bean的id
  • 4.如果Bean实现了BeanFctoryAware 那么String会调用setBeanFactory
  •  5.把Bean的实例传递给BeanPostProcessor 中的postProcessBeforeInitialzation的 前置方法
  • 6完成Bean的初始化
  • 7.如果这个Bean在Spring配置文件中配置了init-method属性也会自动调用其他初始化方法
    8.此时Bean已经能够正常使用,在最后的时候调用DisposableBean中的destroy方法进行销毁处理

MyBatis中当实体类中的属性名和表中的字段名不一样时怎么办

1.写sql语句时起别名
2.在MyBatis的全局配置文件中开启驼峰命名规则
3.在Mapper映射文件中使用resultMap来自定义映射规则

Mybatis中#和$的区别

#是占位符,$是sql拼接符号
#可以防止sql注入,替换成?
$会替换成变量的值

MyBatis都有哪些动态sql标签

    标签: 是为了判断传入的值是否符合某种规则         
标签 where标签可以用来做动态拼接查询
foreach标签可以把传入的集合对象进行遍历,然后把每一项的内容作为参数传到sql语句中
适用于更新中,当某个匹配条件后,才会对该字段进行更新操作

Mybatis是如何将sql执行结果封装为目标对象并返回的? 都有哪些映射形式

第一种是使用映射标签,逐一定义数据库列名和对象属性名之间的映射关系
第二中就是使用sql列的别名功能,Mybatis通过反射创建对象,同时使用反射给对象的属性值逐一赋值并返回,那些找不到映射关系的属性是无法完成赋值的
比如在搭建mybatis时,读取不到mybatis-config配置问件时,这时候有什么办法吗
1.根据錯誤信息查找原因
  • cookies和session的区别

cookies是存放在客户浏览器上的,    seeeion的数据是存放在服务器上的
单个cookies保存的数据<=4kb,一个站点最多保存20个cookie
对于session没有上限,但处于对服务器端的性能考虑,session内不要存放过多的东西
cookie中只能保管Ascll字符串,并通过编码方式存储为Unicode字符串或二进制数据
session中能够存储任何类型的数据,包括但不限于String,list map等
  • Ajax最大的特点,谈谈对Ajax的理解
Ajax是一种创建交互式,网页应用的开发技术,改善用户体验,实现无刷效果
它的优点:     通过异步模式,提升了用户体验
 不需要插件支持,提高了web程序的性能,减轻服务器和带宽的负担
 缺点:    对搜索引擎的支持不足
实现一个算法,判断一个英文单词的所有字母是否全都不同
  public boolean isUnique(String astr) {
         Set set = new HashSet<>();
        for (int j = 0; j < astr.length(); j++) {
            if (!set.add(astr.charAt(j))) {
                return false;
            }
            
        }
        
        return true;
        }
项目中哪些用到了线程池
1.
创建线程的四种方式
1.继承Thread类
2.实现Runnable接口创建线程
3.使用Callable和Future创建线程
4.使用线程池
线程死锁产生原因
1.互斥使用    即当前资源被一个线程占用,别的线程抢占不了
2.不可抢占    资源请求者不能强制从资源占有者手中抢占资源
3.请求和保存    即当资源请求者在请求其他的资源的同时保存对 原有资源的占有
4.循环等待    即存在一个等待队列,    p1占有p2,p2占有p3
线程如何避免死锁的方式
1.加锁顺序    线程按照一定的顺序加锁
2.加锁时限    线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁
3.死锁检测    对资源的分配加以适当限制可防止或避免死锁发生,
线程池参数如何合理设置
没有统一标准,
 一般建议
如果是Cpu密集型应用,线程池大小设置为N+1
如果是IO密集型应用,则线程池大小设置为2N+1
N是cup核数
线程的生命周期(线程有几种状态)
创建,就绪,运行,阻塞,和死亡状态
1.新建状态:     新建一个线程对象
2.就绪状态:线程对象创建后,其他线程调用了该对象的start方法,该线程处于可运行线程池中,等待获取CPU的使用权
3.运行状态,    就绪状态的线程获取了CPU,执行程序代码
4.阻塞状态,阻塞状态是线程因为某种原因放弃了cpu的使用权,暂时停止,直到线程进入就绪状态, (等待阻塞,    同步阻塞    其他阻塞 )
5.死亡状态:线程执行完了或者因异常退出了run方法,该线程结束生命周期
什么是双亲委派,它的优点是什么
简单来说就是当类加载器试图加载某个类型的时候除非父类加载器找不到相应类型,    否则尽量将这个任务代理给当前加载器的父加载器去做,
优点:    避免Java类型的重复加载,防止Java核心api被篡改
  • Java类加载器有哪些
jdk自带三个类加载:
Bootstrap ClassLoader 是ExtClassLoader的父类加载器,默认负责  JAVA_HOME lib下的jar包和 class文件
ExtClassLoader    是AppClassLOader的父类加载器,负责加载lib/ext文件夹下的jar包和class类
AppClassLoader是自定义加载器的父类,
  • Spring 的 两大核心介绍一下
IOC就是控制反转,意思是控制反转指控制权的转移 将创建对象的控制和依赖权转移到Spring容器中    是一种设计模式
AOP:面向切面编程,是一种编程思想,OOP的延续    将系统中非核心的业务提取出来,进行单独处理,比如事物,日志等
  • 如何实现一个IOC容器
1.配置文件配置扫描包路径
2.递归包扫描获取.class文件
3.反射,确定需要交给IOC管理的类
4.对需要注入的类进行依赖注入
Spring框架都用到了哪些设计模式
1.工厂模式:    BeanFactory就是简单的工厂模式的体现,用来创建对象的实例
2.单例模式:Bean默认就是单例模式
3.代理模式:    Spring的AOP功能用到了Jdk的动态代理模式和CGLib字节码生成技术
4.模板方法:   可以将相同的代码放入父类,不同的代码放入子类中 用来解决代码重复问题
5: 观察者模式:    Spring事件驱动模型就是观察者模式的一个经典应用
6.适配器模式:    Spring的Aop的增强或通知使用到了适配器模式
什么是事务传播Spring支持几种事务传播
当事务方法被另一个事务方法调用时,被调用的方法就会将事务传播给调用方,
Propation.REQUIRED    如果不存在事务就主动创建事务,否则使用外层事务
SUPPORTS 如果不存在外层事务,就不开启事务,否则使用外层事务
MANDATORY 如果不存在外层事务,就抛出异常,否则使用外层事务
REQUIRES_NEW    总是主动开启事务,如果存在外层事务就将外层事务挂起
NOT-SUPPORTED    总是不开启事务,如果存在外层事务就将外层事务挂起
NEVER    总是不开启事务,如果存在外层事务,则抛出异常
NESTED    如果不存在外层事务,就主动创建事务,否则创建嵌套的子事务
  • SpringCloud有哪些核心组
Eureka :注册中心,服务注册与发现
Ribbon :负载均衡,实现服务调用的负载均衡
hystrix:    熔断器    是对雪崩效应的一种微服务链路保护机制    服务降级
Feign:     远程调用    类似于dubbo
Zuul    微服务 网关    类似于服务器端的nginx
SpringCloudCongfig    配置中心
SpringCloud和Dubbo的区别
SpringCloud是阿帕奇下的Spring体系下的微服务治理方案,Dubbo是阿里系统中分布式微服务治理框架
SpringCloud基于HTTp协议,Dubbo基于TCP协议,
SpringCloud注册中心是Eureka    Dubbo使用的是zookeper
SpringCloud是将一个应用定义为一个服务,Dubbo将接口定义一个服务
什么是字节码,采用字节码的好处
在Java中,这种可供虚拟机理解的代码叫做字节码即扩展名为.class的文件
它不面向任何特定的处理器,只面向虚拟机
好处    在一定程度上解决了传统解释型语言执行效率低的问题
    同时又保留了可移植的特点,所以Java程序运行时比较高效,
  • 数据库事务特征有哪些
原子性:     即不可分割,要么全部被执行,要么全部不被执行
一致性:    事务 的执行使数据库从一种正确状态转化到另一种正确状态
隔离性:     在事务正确提交之前,不允许把该事务对数据库的任何改变提供给其他事务
持久性:    事务正确提交之后,其结果会永久保存在数据库中即使在事务提交后有其他故障,事务的处理结果也会得到保存
  • 数据库的锁包括什么
1.共享锁(也叫死锁):    表示对数据镜像读操作
2.排他锁(行锁):    表示对数据库进行写操作
3.行锁:    对一行记录加锁
4意向锁:    为了在一个事务中解释下一行将要被请求锁的类型
数据库设计三大范式
第一范式:    实体属性的原子性
第二范式:    每个实体(表)必须有主健,    所有属性必须完全依赖于主键
第三范式:    每个关系模式中不能有属性传递依赖
Spring 开启了事务后,哪些情况会导致事务仍然不生效为啥
1.数据库引擎是否支持事务(MyISAM引擎不支持事务)
2.是否发生了自调用的问题
3数据源没有配置事务管理器
4.方法不是Public
  • 事务隔离级别
1.读未提交:    在该隔离级别中    所有事务都可以读取到别的事务中未提交的数据,    会产生脏读问题,在项目中基本不怎么使用,安全性太差
2.读已提交:    这是大多数数据库默认的隔离级别,但不是mysql的默认隔离级别,这个隔离级别满足了坚定的隔离要求,一个事务只能看见已经提交事务所做的改变,所以会产生 不可重复读或幻读 问题
3.可重复读:    这是mysql默认隔离级别,它确保了一个事务中多个实例在并发读取数据的时候会读取到一样的数据,   但是会产生幻读
4.可串行化:    事务最高级别,它通过 强制事务排序 ,使之不可能相互冲突,从而解决幻读问题,    
mysql的四种存储引擎
1.myISAM存储引擎    不支持事务,也不支持外键,但是访问速度特别快,,支持3中不同的存储格式,分别是静态表,动态表,压缩表
2.InnoDB存储引擎:    具有提交回滚和崩溃恢复能力的事务安全,    支持自动增长列,外键约束和行级锁
3.MEMORY存储引擎:      支持的数据类型有限制,支持的锁粒度为表级锁,默认使用hash索引   
4.MERGE存储引擎:    是一组myIsam表的组合,这些myIsam表必须结构完全相同,merge本身是没有数据的
多台服务器间redis如何数据同步
主从同步:    1.从服务器连接主服务器发送sync命令
2.主服务器接受到命令后,开始执行bgsave命令,生成RDB文件并使用缓冲区记录此后执行的所有写命令
3.主服务器bgsave执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令
4.从服务器收到快照文件后丢失旧文件,载入收到的快照
5.主服务器快照发送完毕后开始从服务器发送到缓冲区中的写命令
6.从服务器完成快照的载入,开始接受命令请求,并执行来着主服务器缓存区的命令
或增量同步
redis增量负责是指slave初始化后开始正常工作时主服务器发生的写操作同步到从服务器的过程
mysql索引最多设置几个
最多设置16个索引,最大索引长度256z字节
  • mysql索引的数据结构是什么?
B+树,即可以做到快速查询,也能做到范围查询
  • 为啥用到B+树,不用B树
B+树父子节点存放的值子节点中最大或者最小和B树最大的区别叶子结点中包含所有的数据,快速做到范围查询
  • mysql索引的分类
1.普通索引;    最基本的索引,它没有任何限制
2.唯一索引:    与普通索引类似,不同的就是索引列的值必须唯一,但允许有空值,如果是组合索引,则列值的组合必须唯一
3.主键索引:    它是一种特殊的唯一索引
4.联合索引(又叫复合索引):    多个字段上建立的索引,能够加速复合查询条件的检索
5.全文索引: 老版本Mysql自带的全文索引只能用于数据库引擎为MyISAM的数据库表
mysql索引创建原则
1.对查询频率高的字段创建索引
2.对排序,分组联合查询频率高的字段创建索引
3.对索引的数目不宜太多
4.尽量选择唯一索引
5.尽量使用数据量少的索引或者前缀来索引
6.删除不再使用或者很少使用的索引
mysql
内连接    inner join
左(左外)连接    left    join
右(右外)连接    right    outer    join
mysql常用函数
1.聚合函数    avg,count,max
2.字符串函数    concat,insert,left
3.日期和时间函数    curdate(),current_date
4..条件判断函数    if,ifnull,
mysql索引失效场景
1 .like以%开头,索引无效,
2 .or语句前后没有同时使用索引,    当or左右查询只有一个是索引,该索引失效
3 .组合索引,不是使用第一列索引,索引失效
4. 数据类型出现隐式转换,比如varchar不加单引号,可能会自动转换成int类型,使索引无效     产生全盘扫描
5. 在索引字段上使用is  null,或is  not null操作
6 .对索引字段进行计算操作,字段上使用函数等等
  • (如何进行数据库优化)你们项目怎么做 数据库优化 的?
1.根据服务层面.配置mysql性能优化参数
2.从系统层面增强mysql性能,优化数据库表结构,字段类型,字段索引,分库分表,读写分离等
3.从数据库层面增强性能,优化sql语句,合理使用字段索引
4.从代码层面增强性能,使用缓存或非关系数据库如MongonDB/Redis来缓解高并发数据库查询的压力
5.提升数据库服务器硬件配置,或者搭建数据库集群
  • SQL如何优化
  • 1.对查询进行优化,要尽量避免全表扫描,首先应该考虑where及order bys涉及的列上建立索引
  • 2.应尽量避免在where子句中对字段进行null值判断, 或者 进行函数操作,这将导致引擎放弃使用索引而进行全盘扫描
  • 3..尽量避免大事务操作,提高系统并发能力
  • 4..尽量不要给数据库留null,尽可能的使用NOT null填充数据库
JAVA中如何防止sql注入
1.前端表单进行参数格式化控制
2.后台进行参数格式化,过滤所有涉及sql的非法字符
3..使用预编译语句和参数化查询
多次使用$进行拼接,会导致sql安全性降低,会存在sql注入问题
谈谈Vue的优点
轻量级,简单易学,双向数据绑定,低耦合,可重用性,独立开发
vue有哪几种属性
1.state,Getter,Mutation,Action,Module
如何提高代码的可读性,一致性
1.注释和文档    
2.一致的缩进
3.避免冗余的注释
4.代码分组
5.一致的命名方案
秒杀系统优化
主要需要解决的问题有两个     1.高并发对数据库产生的压力
                                            2.竞争状态下如何解决库存的正确减少
优化思路:    尽量将请求拦截在系统上游
                    读多写少轻量多使用缓存
                redis缓存+RabbitMQ+mysql批量入库
处理高并发的方法
1.系统拆分,将一个系统拆分成多个子系统
2.redis进行缓存处理, 大部分高并发场景都是读多写少的,读的时候大量走缓存,redis单机可以并发几万
3.mq(消息队列)必须用mq(应用解耦+削峰填谷+异步提速) 通过消息中间件dubbo服务间的调用进行解耦
4.采用分布式开发(搭建服务器集群,利用nginx进行负载均衡)
5.数据库分库分表(读写分离)
new对象那一下,对象在内存中是如何运转的
1.当虚拟机遇到一条new指令的时候,首先会去检查这个指令的参数是否能中常量池中能否定位到一个类的符号引用即验证说否是第一次使用该类
2.在类加载检查通过后,接下来虚拟机为新生的对象分配内存,    根据使用的垃圾回收器的不同机制有两种分配方式(指针碰撞,空闲列表)
3.内存分配完后,虚拟机需要将分配的内存空间中的数据类型都初始化为零值不包括对象头
4.虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例等
5.调用对象的init()方法,根据闯入的属性值给对象属性赋值
6.在线程栈中新建对象引用,并指向堆中刚刚新建的对象实例
如何防止用户恶意注册登录
1对单个手机号请求限制,对真实手机号进行校验
2.增加前端验证码,设计足够复杂的验证码
3.对单个ip请求限制
用户登录系统
我们考虑的前后端分离架构,    我们采用JWT生成token的方式来给用户进行身份识别,当我们登录成功后会根据用户的id和手机号生成一个token返回给用户并保存到redsi中,这样用户再访问受保护的资源的时候,我们会在后台进行校验客户
在这里会考虑三个问题
1.是token续签,
在解决token续签的问题,我们这里采取的是在请求头获取token时判断token是否存在,如果不存在就创建token并保存redis中,    如果存在我们就重新从redsi中获取token并进行续签
2.token的安全性
在安全问题上是采用md5加密的方式解决,为了实现token统一校验,我们这里采用的是Springmvc拦截机制+Threadlocal局部线程的方式来解决
3.如何统一处理token
3.这里我们i定义一个拦截器,实现prehandIe()方法,这样的话就可以在用户请求进入controller层之前进行拦截,通过token获取了用户对象
这样就实现了token统一校验的功能
用户在完成登录操作之后,如果是第一次登录,用户会跳到完善个人信息页面,这块我们就输入用户信息,其中头像数据需要图片上传,用的宿舍第三方阿里云oss服务作为图片存储服务器,    并且对头像做人脸识别
项目描述
名刊会app,是类似小说的app,    技术栈有SpringBoot    SpringCloud    MyBatis    nacos    gateway    Zookeeper    Mysql    redis    mongoDB    等 ,    负责模块,有用户登录和用户圈子发布    用户登录使用验证码进行注册登录,首次登录完善用户信息,    然后进行头像校验,    头像校验是第三方技术百度人脸识别,oss存储,验证码是阿里短信服务,    用户圈子发布的话,就是读多写少嘛,所以数据存储的话就用的MongoDB数据库,    然后通过消息中间件将数据异步写入MongoDB中,
哪里够商城的话,主要是写es搜索服务,和Redis的不同场景问题的优化,还有,gewt网关,nginx实现负载均衡啊等等    
 ES 实现商品的搜索服务
1.关键字去特殊符号    根据正则表达式留取中文,数字,字母
2.关键字分词    根据词库进行分词(商品的分类,品牌,及同义词)
3.查词库    根据分词去词库精确匹配,得到对应该词结果分类,如品牌,关键字,等
4..es搜索条件拼接     根据分词后的条件,筛选条件进行条件DSL匹配处理
项目中哪里用到了多线程
用户登录和用户朋友圈上传,以及es搜索,用到了多线程
用户朋友圈上传,里面的数据需要定时去采集,定时生成统计信息,定时清理上传的垃圾文件等
JWT失效了怎么办
1.token过期设置为15分钟
2.前端发起请求,后端验证token是否过期,如果过期通知前端发起刷新token请求,后端设置已再次授权标记为true,请求成功
3.前端发起请求,后端验证再次授权标记,如果已经再次授权,则拒绝刷新token,请求,请求成功
4.如果前端超过,72小时,必须重新登录,后端检查用户最后一次登录日期,如超过72小时,则拒绝token的请求,请求失败,授权token加上刷新token
用户仅登录异常,用户改变密码,则废除token,重新登录
谈谈我在项目中是如何解决分布式事务的
背景:    我们项目使用的SpringCloud微服务架构,因为微服务架构所设计的系统是分布式系统,而分布式系统有一个著名的理论叫做cap理论,即分布式同时满足一致性,可用性,
主要是两段式提交方案
第一阶段,服务a发起一个分布式事务,交给事务协调器处理,事务协调器向a和b发送事务的准备操作,a和b执行事物的准备操作,将Undo和Redo信息写到日志文件中,最好向事务协调器发送是否准备成功的信息
第二阶段,事务协调器收集a和b返回的信息,如果都成功,则通知a和b执行提交的操作,如果有一个失败,则通知执行回滚操作
也可加个三段式提交;    主要是二段式提交的改进,是为了解决二段式提交长时间阻塞的问题,主要就是加入一个预提交阶段

你在项目开发中遇到过哪些问题

 
  • 你在项目中担任什么角色?
我是项目中的开发人员,根据项目组长的分配任务,和需求文档编写代码,然后进行测试,测试完根据测试报告bug记录修订bug完成相应的功能模块的开发
(尽量自己总结)
项目大致流程
自己总结

你可能感兴趣的:(java,jvm,面试)