Java初中级面试题大全

基础篇

1.ES为什么查询效率快

传统的数据库采用的B+数索引,ES中为所有字段默认都建了倒排索引


2.设计模式

设计者模式就是说一种代码设计,一直被多数人使用,他里面有很多好像是23种,之前在博客里看到过,我常用的就是工厂模式、代理模式、单例模式、有很多(享元模式,适配器模式,组合模式)

就工厂模式有
普通工厂模式,就是创建一个工厂类,对实现了同一接口的一些类进行实例的创建

多个工厂模式,他就是普通工厂模式的改进,普通的传递字符串出错,则不能正确创建对象,而多个工厂是提供多个工厂方法,分别创建对象

静态工厂方法模式,将多个工厂的方法模式里面的方法置为静态的,不需要创建实例,直接调用即可

单例第56题

适配器模式
类的适配器:创建一个新类,继承原有的类,实现新的接口
对象的适配器模式:可以创建一个weapper类,持有原类的一个实例,调用实例的方法
接口的适配器模式:不希望实现一个接口所有方法,可以创建一个抽象类,到时候继承抽象类就行


3.通信协议

4.前后端分离,怎么解决跨域

什么是跨域
就是浏览器的同源策略限制,前段和后代在不同服务器(端口和域名不一样),前段js无法请求到后台接口服务。

Nginx代理解决跨域
从浏览器同源策略的限制角度考虑,即浏览器访问前端页面和后端接口的ip主机相同,port接口相同,这样前端页面请求接口就不会出现跨域问题

SSM
通过服务端设置接口响应头Header允许接口被跨域请求,那么服务端即允许接口被跨域访问,不同源的前端页面也就可以调用该接口

使用Spring的注解@CrossOrigin
自定义拦截器,对每个请求response header
Spring自带的cors标签进行xml配置
web.xml中通过fifter设置

或者Ajax中的jsonp js里面搞


5.jdbc怎么调用存储过程

①加载驱动
②获取连接
③设置参数
④执行
⑤释放连接


6.高并发解决方案

传统项目:请求—接收请求—处理业务逻辑—访问数据库—返回给业务层—返回数据给前端(页面渲染)

1.Nginx对请求进行处理:将静态请求转发给文件服务器 动态请求转发给tomcat
2.tomcat集群:
3.把常用的数据缓存起来:Redis缓存中的数据没有的采取数据库查询。
4.数据库集群(主从同步、读写分离、分表分库) 对于一些经常访问的页面 页面静态化

整个项目中对于一些实时性要求不高的业务数据 可以进行异步的操作 消息队列 +多线程(线程池)

image.png

CDN:内容分发网络(就近获取所需内容)


7.jdk1.8新特性

Lambda表达式
比如排序,controller需要对接口方法重写,应用了lambda就可以不带参数直接一句话搞定排序Collections.sort(list, (a,b)->b.compareTo(a)大大简化代码
函数式接口
jdk1.8提供了一个@FunctionalInterface注解来定义函数式接口,如果我们定义的接口不符合函数式的规范便会报错。
方法与构造函数引用
jdk1.8提供了另外一种调用方式::,当 你 需 要使用 方 法 引用时 , 目 标引用 放 在 分隔符::前 ,方法 的 名 称放在 后 面 ,即ClassName :: methodName 。


8.动态代理和静态代理

动态代理:比如以前没有这种思想 ,事务问题,每个方法都要开启提交回滚事务,有动态代理就不虚要,就是在方法的前后动态加一些东西。

实现(jdk实现、cglib实现)原理
如果有接口就用jdk,如果没有就用cglib,也可以强制使用cglib

1.首先实现InvocationHandler接口
2.private传个对象个代理,有参构造


proxy代表的是代理对象、method代表的是你调用的 方法

3.Proxy反射的一个类去点newProxyInstance方法

4.方法里的参数(
①类加载器,就用被代理对象的类加载器
②被代理对象实现接口
③当前对象this

静态代理:
静态代理对客户隐藏了被代理类接口的具体实现类,在一定程度上实现了解耦合,提高安全性
动态代理:实现Invocation接口,实现invoke方法
动态代理实现了只需要将被代理对象作为参数传入代理类就可以获取代理类对象,从而实现类代理
动态代理的服务内容不需要像静态代理一样写在每个代码块中,只需要写在invoke方法中接口

代理:为某个对象提供一个代理,以控制对这个对象的访问。 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代。代理类负责请求的预处理、过滤、将请求分派给委托类处理、以及委托类执行完请求后的后续处理。

相比静态代理,一个非常显著的优点是动态代理可以在自定义调用处理器统一处理委托类的方法,而不必一个个编写。

而动态代理有一个缺点,那就是只能代理基于接口的类,而无法代理没有接口的委托类


9.值传递与引用传递

值传递:只要是基本类型传递都是值传递
引用传递:对基本类型进行封装,对封装对象进行传递


10.cookie被禁用了怎么办

cookie被禁用了,那就是重写url,在请求最后加上session_id
我们一般如果被禁用了 就给出友善的提示


11.cookie和session区别
cookie session
cookie数据存放在客户的浏览器上 session数据放在服务器上

单个cookie保存的数据不能超过4k
session当访问增多,会占用服务器的性能
cookie不是很安全,别人可以分析存放本地的cookie进行cookie欺骗

登录信息等重要信息存放为session
其他信息如果需要保留,可以放在cookie中,比如:购物车


12.#与$的区别

13.thorw和thorws的区别?
thorws thorw
thorws在方法头 thorw一定在方法里
thorws抛出异常对象 thorw是异常类型
thorws被动 thorw主动

14.基本数据类型与引用数据类型
基本数据类型 引用数据类型
byte 数组 array
short 类 class
int 接口 interface
long
float
double
char
boolean

15.构造方法

语法: 类名(形参列表){ 方法体 }
1.构造方法的名字必须和类名完全一致(包括大小写)
2.没有返回值类型,void也不可以
3.每一个类中至少有一个构造方法,一种是看的见的,一种是隐式无参的,同时只有一种
4.必须有方法体
5.目前不能有任何修饰符:static


16.造成死锁的原因有哪些,如何预防?

17.抽象类和接口的区别?

1.就构造函数而言,抽象类可以有构造函数 ,接口不能有
2.就实现数量来说,类可以实现多个接口,但只能继承一个抽象类
3.修饰符也不一样,接口中方法默认使用public修饰,抽象类中方法可以是任意访问修饰符
4.一个类可以被多重实现,抽象类只能被单一继承
5.一个类可以继承多个接口,但是没办法继承多个类

相同点
1)都可以被继承
2)都不能被实例化
3)都可以包含方法声明


18.null与“”的区别

19.单例模式

是一种最常见的设计模式,单例对象就是保证在一个JVM中,该对象只有一个实例存在

public static Singleton getInstance(){
        if(instance == null){
                synchronized(instance){
                        if(instance == null){
                                instance = new Sinfleton();
                        }
                }
        }
}

20.抽象类能使用final修饰吗?

不能
定义抽象类就是为了让其他类继承的,如果final修饰了就不能被继承,这不就矛盾了么。所以final不能修饰抽象类,编辑器会直接提示错误吧


21.普通类和抽象类有哪些区别?

普通类不能包含抽象方法,抽象类可以包含抽象方法
抽象类不能直接实例化,普通类可以直接实例化


22.抽象类必须要有抽象方法吗?

不需要
抽象类不一定非要有抽象方法,写一个普通方法也可以运行


23.

24.String和StringBuffer、StringBuilder区别?

StringStringBufferStringBilder都是操作字符串的类
他们区别在于String声明的是不可变对象,每次操作都会生成新的String对象,指针指向新的String对象

StringBufferStringBuilder可以在原有对象的基础上进行操作,可以改变字符串内容
StringBufferStringBulider的区别在于StringBuffer是线程安全的,StringBuilder是线程不安全的,StringBuilder的性能高于StringBuffer。单线程环境建议StringBuilder,多线程就是StringBuffer


25.final在java中有什么作用?

final修饰的类就叫做最终类了,是不能被继承的,而且final修饰的方法不能被重写。
final修饰的变量叫常量嘛,常量就必须初始化,初始化之后值就是不能被修改的了。


26.Java中都有哪些引用类型?

强引用:发生GC的时候不会被回收
软引用:有用但不是必须的对象,在发生内存溢出之前会被回收
弱引用:有用但不是必须的对象,在下次GC的时候被回收
虚引用:在GC时返回一个通知


27.怎么判断对象时候可以被回收

引用计数器:
为每个对象创建一个引用计数,有对象引用时+1,引用释放时-1,当计数器为0就可以被回收,缺点不能解决循环引用的问题


28.堆栈的区别

功能方面:堆是用来存放对象的,栈使用来执行程序的
共享性:堆是线程共享的,栈是线程私有的
空间大小:堆大小远远大于栈


29.GET、POST、PUT、DELECE请求的区别

GET:会向数据库发索取数据的请求,从而来获取信息,和数据库select一样,不修改增加,不影响资源内容
POST:向服务器端发送数据,会改变资源,就像insert一样。提价请求都用POST请求
PUT:向服务器端发送数据,从而改变信息,和数据库的update一样,用于修改,不增加
DELECE:就是用来删除某一个资源的,像数据库delete操作


30.怎么批量插入百万数据

addBatch批量插入
clearBatch批量清除


31.Linux常用命令

pwd:获取当前路径
cd:跳转到目录
su -u切换到管理员
ls ls:列举目录
tar -zxvf 文件名 --- 解压命令


32.什么是反向代理

通过客户机的配置,实现让一台服务器代理客户机,客户的所有请求都交给代理服务器处理


33.什么情况下 需要 重写hashcode

34.二分算法

首先二分算法的前提就是必须是有序数组,如果无序,就要用冒泡搞成有序的。
每次取中间位置的值与待查关键字比较,如果中间位置的值必待查的关键字打,则在前半部分循环这个查找过程,如果中间位置的值比待查的关键字小,则在后半部分循环这个查找过程。知道查到为止,否则序列中没有待查的关键字。


35.三范式

每一列只存一个值(不能一列又是id又有name)
每一行必须要唯一(不能说两行必须完全一样)
a表不能出现b表的其他字段,只能出爱心那b表的外建


36.byte占几个字节,多少位,取值范围?

Byte占1个字节,8位,取值范围-128-127


37.SSM框架的优点与缺点

首先Spring是轻量级的DI(IOC)和AOP的容器框架,最核心的就是IOC和AOP嘛!
IOC就是可以让我们对象的创建、初始化、销毁交给Spring赖管理。不用我们来控制,实现那个控制反转,让我们diamante低耦合
AOP就是面向切面编程,就是通过xml配置啊或者注解的方式实现 前置通知,后置通知,异常通知,最终通知等,在需要的地方加入逻辑嘛。我在写日志的时候用

SpringMVC就是可以任意使用各种视图技术,而不仅仅局限于jsp。支持各种请求资源映射啊。

MyBatis就是ORM持久框架,对象关系映射,需要自己写sql,这样可以更好的控制SQL语句嘛!以前也接触过Hibernate,不用写sql可以直接调用api搞数据库,比较简单,但是实际效率也不行。现在我用的是MyBatis-puls。就很完美,又可以控制sql语句,还是一些简单的api非常方便,搞起代码生成器,基础sql也不用写了


38.如何实现数组和List之间的转换

数组转List:使用Arrays.asList(array)进行转换



List转数组:使用List自带的toArray()方法



39.如何实现字符串反转

使用StringBuilder或者StringBuffer 的reverse() 方法

// StringBuffer reverse
StringBuffer stringBuffer = new StringBuffer();
stringBuffer. append("abcdefg");
System. out. println(stringBuffer. reverse()); // gfedcba// StringBuilder reverse
StringBuilder stringBuilder = new StringBuilder();
stringBuilder. append("abcdefg");
System. out. println(stringBuilder. reverse()); // gfedcba
40.重载和重写的区别

重写
子类集成父类原有的方法,就是方法名,参数,返回值都相同,但是对方法体进行重写了。这就是重写

重载
就是同一个类中,同名的方法,参数不同,参数个数不同,顺序不同。这就是重载了


41.springmvc 和 springboot有啥区别?

最初spring大家觉得很好用,就以这种模式高出了MVC框架,然后这种每次开发都写很多样板代码,为了简化,油卡发出了springboot

springboot实现了自动配置,降低了项目搭建的复杂度

springmvc是框架,项目中实际运行的代码。springboot是一个配置工具,辅助工具


42.Java中Io流种类

按功能:输入流(input)、输出流(output)
按类型:字节流和字符流
字节流和字符流的区别:
字节流按8位传输,以字节为单位
字符流按16位传输,以字符为单位


43.Files 的常用方法

Files. exists():检测文件路径是否存在。
Files. createFile():创建文件。
Files. createDirectory():创建文件夹。
Files. delete():删除一个文件或目录。
Files. copy():复制文件。
Files. move():移动文件。
Files. size():查看文件个数。
Files. read():读取文件。
Files. write():写入文件。


44.BIO、NIO、AIO的区别

BIO:同步阻塞 ---- 简单使用方便,并发处理能力低
NIO:同步非阻塞 ---- 客户端和服务器端通过 Channel(通道)通讯,实现了多路复用
AIO:NIO升级,异步非阻塞 ---- 异步 IO 的操作基于事件和回调机制


45.Collection和Collections的区别

Collection是一个集合接口,它提供了对集合对象进行操作的通用接口方法
Collections是一个包装类,包含了静态方法,不能被实例化。比如排序方法:Collections.sort(list)


46.TCP三次 握手

第一次握手:建立连接时,客户端发送syn包
第二次握手:服务器收到syn包,自己再发个syn+ack包
第三次握手:客户端收到服务器的syn+ack包,客户端和服务器进入状态。开始传送数据


47.什么是Java序列化?什么情况下需要序列化?什么是反序列化

Java序列化是为了保存各种对象在内存中的状态,并且可以把保存的对象状态再读出来

想把的内存中的对象状态保存到一个文件中或者数据库中的时候;
想用套接字在网络上传送对象的时候;
想通过RMI(远程方法调用)传输对象的时候;

反序列化:就是反着来的(磁盘保存的内存)


48.什么是反射

反射是在运行状态中,对于任意一个类,能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制

IOC控制反转 通过

自定义注解

拿属性、拿构造,拿方法
1.获得class对象(.class 或forName地址值)
2.获得构造(getDeclaredConstyctor)
3.创建student对象(,newInstance())


49.Ajax

50.cookies可以存对象吗?session可以存对象吗

51.过滤器和拦截器 区别 分别做什么事情

过滤器 就是乱码什么的
拦截器 就是阻止 做权限用


52.数据库优化关键字

伊克斯p楞(EXPLAIN)


53.springcloud帮springboot做什么的

54.#与$区别

55.有了基本类型为什么还需要包装类型

Java是一个面向对象的语言,而基本的数据类型,不具备面向对象的特性


56.==和equals的区别

==用来判断两个变量之间的值是否相等,变量可以分为基本数据类型和引用数据类型,如果是基本数据类型就是值比较,如果是引用数据类型就是地址比较
equals用来比较两个对象长得是否一样,判断两各对象的某些特征是否一样


57. mybatis插入数据 如何返回主键

58. hashmap怎么把链表转换成 红黑树的
59.进程和线程

进程:一个应用程序就是一个进程 可以看成一大段代码(计算机分配资源的最小单位)
线程:一个进程比喻成一个包工头,线程就是下面的小兵 。 (最小的执行单位)

一个进程中包含一个或多个线程,一个程序至少有一个进程,
多线程:多个线程同时执行一个任务

Redis是单线程 -- 线程安全的,因为是单线程

多线程的效率不一定比单线程高 需要考虑创建线程时间的开销 线程切换的时间开销


60.如何决定使用HashMap和TreeMap

对于在Map中插入、删除、定位一个元素这类操作,HashMap是最好的选择
如果要对一个key集合进行有序的遍历,那TreeMap是更好的选择


61.HashSet和TreeSet去重标准

62.JVM组成

运行时数据区(方法区、堆、程序计数器、虚拟机栈、本地方法栈)
执行引擎(即时编译器、垃圾收集)
类加载器子系统
本地方法库


63.synchronized和Lock的区别

synchronized和Lock都是属于悲观锁

synchronized可以给类、方法、代码块加锁;而Lock只能给代码块加锁

synchronized不需要手动获取锁和释放锁,使用简单,发生异常会自动释放锁,不会造成死锁
Lock需要自己加锁和释放锁,如果使用不当没有unLock()去释放锁就会造成死锁

通过Lock可以知道有没有成功获取锁,而synchronized没法办到

lock()加锁 unLock()释放锁

性能上面讲的话 Lock效率高一些


64.

65.Runnable和Callable的区别

Runnable没有返回值,Callable可以拿到返回值,Callable可以看做是Runnable的补充


66.线程的run()和start()的区别

start()方法用于启动线程;run()方法用于执行线程的运行时代码
run()可以重复调用,而start()只能调用一次


67.

68.notify和notifyAll的区别

notify() 随机唤醒一个线程(具体哪个线程由虚拟机控制)
notifyAll() 会唤醒所有的线程,


69.并行和并发的区别

并行:多个处理器或多核处理器同时处理多个任务
并发:多个任务在同一个CPU核上,一个处理器处理多个任务



70.什么是死锁

当线程A持有独占锁a,并尝试去获取独占锁b的同事,线程B持有独占锁,并尝试获取独占锁a,就会发生AB两个线程都持有对方需要的锁,而发生的阻塞现象


71.怎么防止死锁

尽量使用java。util。concurrent并发类代替自己手写锁
尽量降低锁的使用粒度,尽量不要几个功能用同一把锁
尽量减少同步的代码块
用个trtLock的一个方法设置超时时间,超时可以退出防止死锁


72.CAS原理 乐观锁 怎么解决

a有5元,b拿走2元,c又放回去2元,这边看到a没有动就觉得有问题
解决:表中价格字段version版本号,每次改动版本号加1,这种就可以察觉

volatile 保证线程和线程之间的可见性与有序性


73.事务的传播机制

74.事务

75.ThreadLocal是什么?使用场景

保证每个线程都访问自己的东西

使用场景:数据库连接和session管理等
ThreadLocal原理
ThreadLocal 是线程的局部变量, 是每一个线程所单独持有的,其他线程不能对其进行访问

就是用来存储实际的变量副本

使用ThreadLocal来写一个工具类,ThreadLocal用来存放线程的变量,每个线程都存成一个副本


76.hi和MyBatis区别

77.锁

可重入锁
自旋锁:
公平锁:一个等十分钟,一个等五分钟,那你说那个有机会得到机会。公平
读写锁:分开,读的时候查询不需要锁。写修改新增改变数据的时候就加锁
乐观锁
悲观锁
独占锁:是一种悲观锁,


78.synchronized和volatile区别

volatile是变量修饰符;synchronized是修饰类、方法、代码段

volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性
volatile不会造成线程的阻塞;synchronized可能会造成线程阻塞


79.分布式锁

Redis实现分布式锁
有工具 给你完成了很多,但是维护很难受

zookeeper实现分布式锁
可以产生临时有序的节点


80.分布式事务

在分布式系统中的事务
强一致性
弱一致性
最终一致性

(CAP)
C 一致性 -----
A 可用性 -----
P 分区容忍性 ------


81.微服务和单体应用的区别 ,优缺点

82.http get和post请求的区别

GET和POST请求都是http的请求方式,用户通过不同的http的请求方式完成对资源(url)的不同操作,GET,POST,PUT,DELETE就对应着资源的查,改,增,删

POST一般用来更新资源信息,GET一般用来获取/查询资源信息

GET PSOST
Get请求提交的数据会在地址栏显示 Post请求不会再地址栏显示出来
Get请求由于浏览器对地址长度的限制,数据传输也有限 Post就没有地址栏的限制
Get数据会呈现在地址中,不安全 Post安全性比Get就高

83.
84.JVM组成

85.双亲委派机制是什么意思?

86.JVM垃圾回收

垃圾回收,就是通过垃圾收集器把内存中没用的对象清理掉


87.JVM优化

88.如何判断你的文件是否是垃圾

89.什么是事务

要么成功,要么失败,不可分割的一组操作。比如:这边你给朋友转钱,你转了你朋友没收到,这是不行的,要回滚


90.事务的特性

(ACID)
原子性:一组操作紧密相连 不能分开
一致性:数据的一致性,总量是不变的
隔离性:相互之间不会有影响
持久性:保存到磁盘上


91.事务的传播机制

92.事务的隔离级别
k k k
ISOLATION_DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别
ISOLATION_READ_UNCOMMITTED 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据 会产生脏读,不可重复读和幻像读。
ISOLATION_READ_COMMITTED 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据
ISOLATION_REPEATABLE_READ 这种事务隔离级别可以防止脏读,不可重复读 但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行 除了防止脏读,不可重复读外,还避免了幻像读。

1.就是默认的
2.第二种是最低的个隔离级别:它允许另一个事务看到这个事务未提交的数据:会产生脏读,幻读,不可重复读
3.保证一个事务修改的数据提交之后才能被另一个事务读取,另一个事务不能读取未提交的数据
4.还有一种就是可以防止脏读和不可重复读的,但是可能会出现幻读



93.脏读、幻读、不可重复读

脏读:就是说一个事务正在访问数据,并且对数据进行修改,修改还没提交到数据库中,另一个事务又读取,并使用了原来数据

幻读:当一个事务执行插入,先查询数据,数据里没有,接下来准备添加,结果出错,再查显示有这条数据了,因为在第一个事务查询完,第二个事务添加了,这就是幻读

不可重复读:一个事务多次读取同一条数据,当第一个事务访问完第一次要访问第二次时,第二个事务进来并修改了数据,导致第一个事务两次读取的数据不一致


94.反向代理

用一台服务器,代理真实的服务器,用户访问的时候,就不再是直接访问真实服务器,而是访问代理服务器。这样就不需要暴露真实的服务器地址。提前在Nginx中配置好反向代理的规则,不同情求,交给不同的真实服务器处理。


95.为什么需要Nginx

前端部署 --- 项目开发完前段项目需要服务器部署
解决访问端口的问题 --- 同一台服务器部署多个项目是,访问需要带端口--这就需要反向代理
后端项目负载均衡器



96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.

实现原理/流程

1.HashSet实现原理

2.HashMap实现原理

3.类加载流程

①加载字节码
②验证字节码(是否有效)看看是不是字节码文件.txt、.js、.jsp....等等
③准备(准备空间)
④解析(替换直接引用,加载到内存中地址)
⑤初始化(对变量赋值)


4.第三方登录实现流程

5.单点登录

单点登录就是,当你在主网址登录之后,他下面的子网站你就可以不用再去登录了

实现
①浏览器发送登录请求
②登录成功,使用UUID生成一个字符串(token)
③使用token把登陆信息放入redis里面
④浏览器每次发送请求都要携带token到服务端
⑤通过zuul拦截判断是否登录,获取到请求中的token去redis中获取登录对象
⑥如果有登录对象,放行


SpringMVC的执行流程

①首先用户这边发送请求,Spring的DisPatcherServlet捕获
②DisPatcherServlet对请求URL进行解析,然后调用HandlerMapper
③HandlerMapper获得Handler配置,执行Handler
④执行完之后DisPatcherServlet返回一个ModelAndView对象
⑤根据ModelAndView选择合适的ViewResolver
⑥ViewResolver结合Model和View来渲染视图
⑦最后将渲染结果返回给客户端


6.注册

图片验证码实现流程
①我们是把图片验证码的值放到redis中的,为了避免大量的图片验证码在redis中产生,我们在前端生成的key是相对唯一,无论你刷多少次,在redis中你的key就那一个,前提是同一个页面。
②后端根据这个key去生成图片验证码的值,然后通过这个key存到redis中
③然后把验证码值搞到图片里面去
④我们是基于使用base64加密把图片验证码变成字符串
⑤前端通过axios拿到这个值,通过标签 就能显示出来了

校验
⑦前端图片验证码用户填的那个值,和图片验证码前端的那个key,一起传到后台
⑧后台根据key去redis中拿到redis里面的图片验证码的值
⑨两者比较校验

手机验证码实现流程
①点击发送手机验证码--判断手机是否为空
②点击发送手机验证码--判断图片验证码是否为空
③点击手机验证码按钮实现按钮的倒计时效果
④使用axios请求后台发送手机验证码--手机号和图片验证码和图片验证码的key作为参数
⑤后台收到请求校验图片验证码(Redis中获取)
⑥后台根基手机号去Redis中获取是否有发送记录
⑦如果有发送记录
  1.判断是否发送频繁(两次发送验证码时间间隔太小)
  2.如果没有频繁就把上一次的验证码发送
  3.刷新redis中的验证码发送时间为当前
⑧如果没有发送记录
  1.随机生成验证码,发送
  2.把验证码保存到redis(key,value)
⑨把验证码发送记录保存到MySQL

注册实现流程
①前台发起注册请求,参数:手机号,手机验证码等等
②后台判断,验证码是否正确/过期(Redis获取)
③后台判断手机号是否被注册
④最后保存登录信息,初始化其他关联表


7.BitSate用户状态

位状态:就是二进制的形式,我们用这个字段来表示看用户绑定那些第三方
比如:
绑定QQ---001
绑定微信---010
绑定微博---100

Long bitState = 0L ; => 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000111


8.ES上下架

客户从不同的维度(关键词,价格,排行)去查询,我们如果不用ES 那我们肯定要用like模糊查询,效率不高,我们优化 肯定就是ES
我们把数据全都搞到数据库里面,用ES保存起来

1.添加到数据库,(页面上不显示—后台显示未上架)

  1. 当点击上架提交按钮之后,从数据库查询到商品信息,上传到ES库里面
    3.用户查询直接从ES中查(不去数据库,这样降低数据库压力,提高查询效率)
    4.删除或者修改(一:下架后在操作 二:同步操作索引库和数据库)
    5.我们就是点击下架 我们会从ES中删除数据,数据库先不删

还是导jar包,doc(页面展示部分,查询需要用到)---feign(调用redis)---做配置和入口 ---- 写接口(设置添加es,删除),搜索条件,价格名字类型 ---搜索完返回 --- controller实现feign
前台上线

点击一行数据(@Row-click),把选中的数据保存起来
点击上线按钮,判断时候有选中数据,如果没有给出提示
发送上线请求到后台,把商品id作为参数
后台上线
从数据库查询上线课程
判断课程的状态为上线
修改数据库状态为上线
把商品对象封装成es的文档对象
调用es的client把文档对象存储到es里面


9.页面静态化

详情页面,店家主业,访问人数比较多,而且在一定时间内不改动的,这种也是降低数据库压力,提高响应速度,增加用户体验的
有的页面访问人数很多,但是在一定时间段内不会改变.页面静态化.

velocity模板技术 --- 就一个工具包引进来,调用他的API就可以
大的说 就是模板技术velocity 加上数据 就是静态页面
我们用Nginx(反向代理)做静态网站部署
freemaker mybatis里面用



1.后台对页面静态化进行了一个管理,name html
2.上传到fastdfs模板
3.商品做了页面静态化 放到redis,在放到页面静态化服务里
4.发送一条消息到mq(html地址,nginx物理路径)
5,每个站点都有不一样的routingkey(肉丁k),指定那个就去那个里面
6.最后拷贝到站点 就可以了

组成部分说明如下:
Broker:消息队列服务进程,此进程包括两个部分:Exchange和Queue。
Exchange:消息队列交换机,按一定的规则将消息路由转发到某个队列,对消息进行过虑。
Queue:消息队列,存储消息的队列,消息到达队列并转发给指定的消费方。
Producer:消息生产者,即生产方客户端,生产方客户端将消息发送到MQ。
Consumer:消息消费者,即消费方客户端,接收MQ转发的消息。

消息发布接收流程:
-----发送消息-----
1、生产者和Broker建立TCP连接。
2、生产者和Broker建立通道。
3、生产者通过通道消息发送给Broker,由Exchange将消息进行转发。
4、Exchange将消息转发到指定的Queue(队列)
----接收消息-----
1、消费者和Broker建立TCP连接
2、消费者和Broker建立通道
3、消费者监听指定的Queue(队列)
4、当有消息到达Queue时Broker默认将消息推送给消费者。
5、消费者接收到消息。


10.面包屑

数据库中专门有两个字段,一个是pid表示当前所属(比如100),第二个就是层级关系(比如:100.101.102)(100.103)


11.MyBatis-Plus

他就是基于MyBatis,进行了更深一步的封装
不用写重复代码,加上模板velocity功能,一键生成daomin、query、mapper接口、xml、server、controller

思路
导依赖 --- 配置类properties(输出路径,数据库连接) --- 配置文件vm(模板【controller、query】)---加上工具类(里面都是固定的)每次使用就是改一下连接配置文件的完全限定名,还有表名。启动即可

1.导依赖(mybatis-plus-boot-starter、 velocity模板、mysql)
2.创建配置类(properties:输出路径、数据库连接)
3.创建代码生成主类(读取的配置类完全限定名、全局配置、数据源配置、生成表、细致配置等等)还controller、query


12.RabbitMQ

RabbitMQ 就是做消息中间件嘛!实现消息队列先进先出的,可以用来提高系统响应速度,提高系统稳定性(如果信息量突然很大,容易把订单搞死,加上消息队列就稳定多了),还有解耦,消除峰值

安装
安装rabbitmq、安装erlang、安装management

  • service-install(安装服务)
  • service-remove(删除服务)
  • service-start(启动)
  • service-stop(停止)

1.下载erlang
2.安装RabbitMQ
3.安装management
4.启动
5.浏览器登录


13.FastDFS文件处理

第一种:把文件交个第三方的文件服务器处理,本地数据库只需要保存图片的网络路径就可以了(比如:阿里云、七牛云)
第二种:我们自己搭建用Fastdfs
导依赖--配置文件yml--工具类--运行出来conf文件--完成controller一系列相关--zuul配置路由--swagger也搞一下

上传
①定时想tracker上传状态信息
②上传连接请求
③查询可用storage
④返回信息(就storage的ip和端口)
⑤上传文件
⑥生成file_id
⑦将上传内容写入磁盘
⑧返回file_id(路径信息和文件名)
⑨存储文件信息

下载
相反

FastJson --- 对象转换为json字符串,json字符串转换为Java对象


14.Synchronized的底层实现原理

Synchronized是由一对monitorenter/monitorexit指令实现的
monitor对象是同步的基本实现单位。java6之后有三种不同的monitor实现,(偏向锁、轻量级锁、重量级锁)


15.Redis

检查Redis中是否有数据 --- 有就直接返回 --- 没有就从数据库中查 --- 把数据放入一份到Redis中缓存起来 --- 返回数据 --- 如果遇到添加/删除/修改 需要做Redis缓存重置

①封装一个RedisUtls工具类(jedis)---- json字符串
②逻辑---service
if(redis捕获) retrun redis获取的
Else
从数据库获取,设置缓存,再返回,下次来了以后直接获取捕获
对缓存所对应的数据做了增删改以后要同步缓存redis中

检查redis中是否有数据,有就直接返回,没有就去数据库中查,数据如果有就返回客户,并放一份在redis中,如果没有就返回没有,如果添加或者删除,需要redis重置

1.导依赖 --- redis.properties(连接数据库,密码) --- 搞枚举工具类(一些配置,获取连接池 设置字符值)---写Redis接口,用AjaxResult (往redis设置值,往redis取值)--- 主配置文件yml -- --- zuul路由 --- swagger

2.feign接口 --- 搞接口redisClient(调用Redis服务的fiegn的客户端接口AjaxResult=get/set) --- RedisClientFallback托底


16.shiro实现流程

17.Spring的生命周期

18.Servlet生命周期

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


19.Bean生命周期
20.SKU属性实现流程
21.秒杀实现流程

秒杀的问题
当时用我们数据库是有个时间的,主机,还有页面上的倒计时,他们之间是有微妙的偏差的,没办法解决,当时我们试过放Redis里面统一了在提出来 ,不行。 最后就是提前了一点点。


22.线程生命周期

新建new -- 等待Cpu -- 运行start-- 阻塞 -- 死亡
阻塞分为三种阻塞
一:同步阻塞:synchronized
二:等待阻塞:wait
三:其他阻塞:


23.

24.SSM框架的优点与缺点

首先Spring是轻量级的DI(IOC)和AOP的容器框架,最核心的就是IOC和AOP嘛!

IOC就是可以让我们对象的创建、初始化、销毁交给Spring赖管理。不用我们来控制,实现那个控制反转,让我们diamante低耦合
AOP就是面向切面编程,就是通过xml配置啊或者注解的方式实现 前置通知,后置通知,异常通知,最终通知等,在需要的地方加入逻辑嘛。我在写日志的时候用

SpringMVC就是可以任意使用各种视图技术,而不仅仅局限于jsp。支持各种请求资源映射啊。

MyBatis就是ORM持久框架,对象关系映射,需要自己写sql,这样可以更好的控制SQL语句嘛!以前也接触过Hibernate,不用写sql可以直接调用api搞数据库,比较简单,但是实际效率也不行。现在我用的是MyBatis-puls。就很完美,又可以控制sql语句,还是一些简单的api非常方便,搞起代码生成器,基础sql也不用写了


25.
26.
27.
28.
29.
30.
31.

MySQL

1.数据库索引会在什么情况下失效

1)like查询是以%开头:索引失效
2)条件中有or。及时其中有条件带索引也不会使用
3)如果列类型式字符串,那一定在条件中将数据引号引起来,否则失效
4)全表扫描比使用索引快,则不用索引


Java开发环境需要什么?

1.适用于我们开发环境的jdk
2.对应开发环境的eclipse、idea
3.web服务器(tomcat)


存储过程?

发一条SQL,有的时候有复杂的sql,还有一些复杂的操作传参返回值,所以一条SQL有时候做不到。所以就是在存储过程里面完成一些复杂业务逻辑处理,我在java代码里面写这些,很少在存储过程中搞。

存储过程 不用把所有都传过去java后台,直接在SQL中都完成了,节省

intout

可以写一些业务逻辑,


关键字

explain关键字用于分析sql语句的执行情况,可以通过他进行sql语句的性能分析。

1、from
2、on
3、 join
4、where
5、group by
6、having
7、select
8、distinct
9、order by
10、limit


数据库索引

普通索引:
唯一索引:id不能重复
复合索引:推荐,能够命中索引的几率更高


ACID是什么?

原子性
一致性
隔离性
持久性


MySQL的内连接、左连接、右连接

内连接:inner join
左连接:left join
右连接:right join
内连接就是把匹配的关联数据显示出来;
左连接是左边的表全部显示出来;右边的表显示出符合条件的数据
右连接是右边的表全部显示出来;左边的表显示出符合条件的数据


数据库的事务隔离级别
MyISAM和INNODB的区别

1.事务安全:MyISAM不支持事务,INNODB支持
2.查询和添加速度:MyISAM速度快,INNODB支持
3.锁机制:MyISAM表锁,INNODB行锁
4.支持全文检索:MyISAM支持,INNODB不支持
5.外建:MyISAM不支持,INNODB支持


事务的传播机制

PROPAGATION_REQUIRED (默认)
支持当前事务,如果当前没有事务,则新建事务
如果当前存在事务,则加入当前事务,合并成一个事务
REQUIRES_NEW
新建事务,如果当前存在事务,则把当前事务挂起
这个方法会独立提交事务,不受调用者的事务影响,父级异常,它也是正常提交
NESTED
如果当前存在事务,它将会成为父级事务的一个子事务,方法结束后并没有提交,只有等父事务结束才提交
如果当前没有事务,则新建事务
如果它异常,父级可以捕获它的异常而不进行回滚,正常提交
但如果父级异常,它必然回滚,这就是和 REQUIRES_NEW 的区别
SUPPORTS
如果当前存在事务,则加入事务
如果当前不存在事务,则以非事务方式运行,这个和不写没区别
NOT_SUPPORTED
以非事务方式运行
如果当前存在事务,则把当前事务挂起
MANDATORY
如果当前存在事务,则运行在当前事务中
如果当前无事务,则抛出异常,也即父级方法必须有事务
NEVER
以非事务方式运行,如果当前存在事务,则抛出异常,即父级方法必须无事务


MySQL数据库的热备份

MySQL的双机热备份是一个异步的复制。
1.主数据库将改变记录到二进制日志中;
2.从数据将主数据的日志拷贝到他自己的日志中;
3.从数据重做日志中的时间,将改变反映他自己的数据

一般用于保证服务正常不间断运行,用两台机器作为服务机器,一台用于实际数据库操作应用,另外一台实时的从前者中获取数据以保持数据一致.如果当前的机器熄火,备份的机器立马取代当前的机器继续提供服务


数据库优化

查询优化,能单表就单表,多表影响性能
查询一条数据的时候 用limit
使用索引
数据库分表,分库
读写分离
主从同步

SQL上
查询的字段避免用*号,指定需要的字段
避免使用%前缀的模糊查询
避免or查询
避免MySQL自带函数
避免使用text类型

要说数据库我肯定是先从SQL上看

发现问题(定位慢查询)找出效率低的SQL

 数据库状态的常用命令
 如何定位慢查询
show status 查询所有配置,然后你想查什么,加like,后面再跟就行,
show status like ‘slow_queries’定位慢查询(默认10s)查询慢查询次数
set global long_query_time = 0.4默认时间太长了 我们设置成想要的时长

分析问题(explain)

解决问题

 单机
  表结构设计
  存储引擎
   myisam和INNODB的区别?使用场景
 索引
  什么是索引
  索引的原理是什么样的
  索引的分类有哪些
  创建索引的原则
 分表
  什么是水平分表?水平分表的策略有哪些
  生产id 的方式有哪些》-----雪花
  什么是垂直分表?垂直分表的原则
 sql优化
  ddl dml(批量插入)
  dql:那些情况会放弃索引进行


Redis

1.什么是Reids

Redis是以键值对(key - value)的形式存储值的非关系型数据库NoSQL。先存在内存中会根据一定的策略持久化到磁盘,即使断电也不会丢失数据,它支持的数据类型有String/list/set/zset 我们经常用的就是String/list/zset。主要就是用做中央缓存的,有点赞和排行榜使用(也可以做消息队列)

把经常需要查询的,很少修改的数据,放到读取速度快的空间里(就是内存),下次访问就直接访问Redis,不访问数据库,减少了访问时间,减轻压力,以空间换时间


2.Redis怎么实现分布式锁

先拿setnx来争抢锁,返回1成功,否则返回0。抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放
set指令有非诚复杂的参数,这个应该是可以同时把setnxexpire合成一条指令来用

SET KEY value [设置键过期时间x秒] [设置键过期时间x毫秒] [键不存在,对其进行设置|键存在对其设置]
RedisService redisService = SpringUtils.getBean(RedisService.class);
String result = redisService.set(lockKey,requestId,SET_IF_NOT_EXIST,SET_WITH_EXPIRE_TIME,expireTime);
if("OK.equals(result)"){
  doOcuppiredWork();
}

3.Redis支持的数据类型

String(字符串)、list(列表)、set(集合)、zset(有序集合)、hash(字典)


4.怎么保存缓存和数据库数据一致性

合理的设置缓存的过期时间
新增、更改、删除数据库操作是同步更新Redis,可以使用事务机制来保证数据的一致性


5.Redis持久化有哪些方式,那种效率高

持久化,就是数据持久保存,不会因为断电或者其他原因影响数据的完整性

RDB:指定的时间间隔能对你的数据进行快照存储
AOF:每一个收到命令都通过write函数追加到文件中

数据恢复:Redis启动时先检查AOF是否存在,如果AOF存在则直接加载AOF,如果不存在,则加载RDB文件


6.Redis集群怎么选择数据库

Redis集群目前无法做到数据库选择,默认在0的数据库


7.Redis淘汰策略

alikeys-lru:从数据中挑选最近最少使用的数据淘汰
volatile-random:从已设置过期时间的数据集中任意选择数据淘汰
volatile-ttl:从已设置过期时间的数据集中选将要过期的数据淘汰
volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰


8.Redis主从同步原理

Redis一般是使用Master节点来进行写操作,若干个Slave节点进行读操作

①Slave发送Sync命令到Master
②Master启动一个后台进程,将Redis中的数据快照保存到文件中
③Master将保存数据快照期间接收到的写命令缓存起来
④Master完成写文件操作后,将该文件发送给Slave
⑤使用新的AOF文件替换掉旧的AOF文件
⑥Master将这期间手机的增量写命令发送给Slave端

哨兵模式


9.Redis集群

当一台服务无法满足要求,可以使用redis集群来处理,类似于MySQL读写分离

通过分片,按照某种规则划分数据,分散存储在多个节点上。通过将数据分到多个Redis服务器上,来减轻单个Redis服务器的压力

将数据进行分片,通常做法就是获取节点的Hash值,然后根据节点数求模


10.为什么使用redis缓存,不适用原生缓存

①和应用共用内存
②不可支持持久化
③默认不支持集群


11.怎么解决缓存雪崩、击穿、穿透问题

缓存击穿
key并发非常高,正好key过期,所有都访问到了数据库。
解决:别让他过期啊!这种情况本来就很极端。。或者搞上锁

缓存雪崩
很多key大批量到期,并发撞进数据库,和击穿很像,击穿是一个key,这个是一推
解决:分散过期时间啊。永不过期啊。随机过期什么的
解决:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。
解决:不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀

缓存穿透
就是缓存和数据库中都没有的数据,用户一直反复访问,就是不存在的数据反复访问
解决:我们在缓存搞一个空字符串,来第一次缓存没有,进数据库,第二次再来直接把空字符串传给他


12.Redis常见性能问题

Redis主从复制的性能问题
为了主从复制的速度和链接稳定性,建议主从库最好在同一个局域网内


13.Redis事务

事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行,事务在执行的过程中,不会被其他客户端发送来的命令请求所打断
事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行


14.Redis事务相关的命令有哪几个

MULTI、EXEC、DISCARD、WATCH


15.Redis如何做内存优化

尽可能的使用散列表(散列表:表里存储的数少,使用的内存小)尽可能的将你的数据模型抽象到一个散列表里面
比如:web系统中有一个用户对象,不要为这个用户的名称、姓氏、邮箱、密码设置单独的key,二十摆这个用户的所有信息存储到一张散列表里面


16.java访问Redis

使用jedis 。java客户端来访问Redis服务器,有点类似通过jdbc访问MySQL一样


17.Redis对象保存方式?

json字符串
设置和获取比较简单,需要把对象转换为json字符串,当做字符串处理。直接使用get、set


18.
19.
20.
21.
22.

集合

1.Java容器、常见集合有哪些

Conllection和Map两大类

List Set HashMap
ArrayList HashSet LinkedHashMap
LinkedList TreeSet TreeMap
LinkedHashSet Hashtable

java中集合分为valuekey-value两种
存储值有分为ListSet
List是有序的,可以重复的。
Set是无序的,不可重复的,
根据equalshashcode判断,如果一个对象要存储在Set中,必须重写equalshashCode方法
存储key-value的为map


2.HashMap和HashTable的区别

相同点:
HashMapHashTable都可以使用来存储key-value的数据

不同点:
HashMap是可以把null作为key或者value的,而HashTable 不可以
HashMap是线程不安全的,效率高。而HashTable是线程安全的,效率低。

如果我们想线程安全但是我又想效率高?------把整个Map分为N个Segment(类似HashTable)


3.List、Set、Map之间的区别

4.ArrayList和LinkedList的区别

5.
6.
7.
8.
9.
10.

线程

1.线程池的作用?

1.限定线程的个数,不会导致由于线程过多导致系统运行缓慢或者崩溃
2.线程池不需要每次都去创建或销毁,节约了资源
3.线程池不需要每次都去创建,响应时间更快。


2.有没有使用过线程并发库?

简单了解过。JDK5之后增加的Doug Lea并发库,给java线程的管理和使用提供很大的便利性。
java.util.current包中提供了对线程优化、管理的各项操作,使得线程的使用变的得心应手。该包提供了线程的运行,线程的创建,线程生命周期的控制


3.讲一下线程的几种实现方式?启动方式?区分方式?

①实现方式
1.通过继承Thread类实现一个线程。(如果一个类继承Thread就不能继承其他的类了。原因继承扩展性不强,支持单继承)
2.通过实现Runnable接口实现一个线程
②怎么启动
Thread thead = new Thread(继承了Thread的对象/实现了Runnable的对象) thread.setName("设置一个线程名称");
thread.start();
启动线程使用start方法,而启动了以后执行的是run方法。
③怎么区分线程
在一个系统中有很多线程,每个线程都会打印日志,想区分的话就要thread.setName("设置一个县城名称");养成一种规范。


4.在Java程序中怎么保证多线程的运行安全

使用自动锁Synchronized,使用手动锁Lock,使用安全类util.concurrent下的类


5.线程通信

6.什么是线程安全;如何解决线程安全问题

7.Thread常用方法

String getname()---返回该线程的名称
static Thread currentThread()---返回当前正在执行的线程对象
run – 执行
start – 开启新线程
sleep() -- 是当前正在执行的线程一指定的毫秒数暂停


8.守护线程是什么

守护线程是运行在后台的一种特殊进程,在Java中垃圾回收线程就是特殊的守护线程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件


9.线程和进程的区别

进程:
线程:
一个程序下至少有一个进程,一个进程下至少有一个线程,一个进程下也可以有多个线程,来增加程序的执行速度


10.sleep()和wait()的区别 【死累普】【喂特】

sleep()来自Thread,wait()来自Object
sleep()不释放锁,wait()释放锁
sleep()时间到会自动恢复;wait()可以使用notify()/notifyAll()直接唤醒


11.线程池的核心参数有哪些?每个表达什么意思?
12.线程拒绝策略有哪些?
13.线程的状态有哪些?
14.
15.

Spring/SpringMVC

Spring

Spring 是一个开源应用框架(轻量级),非常方便,
他的功能
IOC控制反转,创建和管理Bean对象
AOP面向切面编程,通过动态代理实现业务逻辑和系统服务分离,就是高内聚,
Spring的配置文件就是xml

依赖注入:你不必创建对象

Spring的IOC容器:
BeanFactory:BeanFactory就像一个包含Bean集合的工厂类,他会在客户要求时实例化bean
ApplicationContext:ApplicationContext他扩展了BeanFactory接口,并在其基础上额外扩展了功能

AOP的切面就是打上@Aspect

AOP实现就是通过
静态代理:指使用AOP框架提供的命令进行编译,在编译阶段可生成AOP代理类
动态代理:运行时在内存中临时生成AOP动态代理类


BeanFactory和ApplicationContext
BeanFactory ApplicationContext
他使用懒加载 他使用即时加载
他使用语法显示提供资源对象 他自己创建和管理资源对象
不支持国际化 支持国际化
不支持基于依赖的注解 支持基于依赖的注解

什么是SpringBean

他是构成用户应用程序主干的对象
Bean有Spring IOC容器管理
他们由Spring IOC容器实例化,配置,装配和管理‘
Bean是基于用户提供给容器的配置元数据创建

xml里面配置或者注解配置


SpringMVC作用

提供MVC(Model、View、Controller)模型-视图-控制器框架,很灵活很方便


MyBatis/MyBatis-Plus

MyBatis中resultType和resultMap的区别

resultType和resultMap使用MyBatis查询数据记录时,返回类型常用的两种嘛!
resultMap功能更强大一些,列名和实体类不一致
resultType是列名和实体类一致 就可以用


MyBatis 三大核心对象

SqlSessionFactoryBuilder
用来解析xml配置文件,创建sqlSessionFactory,一旦创建完就没有用了

SqlSessionFactory用
来创建SqlSession。重量级对象(二级缓存,连接池,一个项目就一个... 不能关闭,线程安全)

SqlSession
完成增删改查 , 轻量级对象(一级缓存,线程不安全)一个线程创建一次


mybatis优点

SQL语句统一存放到配置文件中;
SQL语句的重复
使用数据库连接池对连接进行管理


SpringBoot/SpringCloud

1.springcloud常用组件

1)服务注册中心   ---  Eureka(实现服务治理--注册与发现服务)
2)负载均衡  ---  Feign(通过springcloud封装,可以轻松的向服务的REST模板请求自动转换成客户端负载均衡的服务调用)
3)断路器  ---  Hystrix(保护系统,控制故障范围)
4)服务网关  ---  Zuul(api网关,路由,负载均衡等多种作用。类似Nginx反向代理)
5)分布式配置  ---  Cinfig(配置管理)


SpringBoot有什么优点

独立运行 + 简化配置 + 自动配置 + 无代码生成和XML配置 + 应用监控 + 上手容易


SpringBoot核心配置

SpringBoot的核心配置文件就是application和bootstrap

application:主要用于 Spring Boot 项目的自动化配置。
bootstarap: 使用 Spring Cloud Config 配置中心时,这时需要在 bootstrap 配置文件中添加连接到配置中心的配置属性来加载外部配置中心的配置信息


Eureka Server服务发现怎么实现

Eureka 提供服务注册服务,各个服务提供者节点启动后,会在Eureka Server中进行注册
这样Eureka Server中的服务注册表中将会存储所有可用服务节点信息,服务节点的信息可以在界面中直观看到


小问题

为什么使用SpringCloud?
因为我们要用分布式


服务与服务之间如果调用?
通过fegin负载均衡调用,通过打一个注解,省去重复工作,自己可以搞工具类


为什么要用fegin?
我们服务服务之间要调用,我们就要管理,不用fegin直接调用也可以,但是http地址你写的不统一,那么多怎么搞,所以我们要统一的管理,省去很多麻烦


假如Eureka挂了怎么办?
做集群(或者可以去缓存里面拿,缓存底层基于Map,缓存里面还是有的)


熔断
假如(加入购物车----订单----支付)他们是一体的,某一块挂了,他就会不断的重试,一个请求一个线程,到最后都卡在挂的那一块,这就可能出现拉闸,连环性雪崩
搞完熔断就是试几次不行之后就自动断开,断开后线程就可以去搞别的了


降级
超时降级,资源不足降级,降级后可以配合降级接口返回托底数据。


隔离
每个服务都有独立的线程池,你这个服务挂了,只会影响到自己的线程池,这就是隔离


Zuul
每个服务都有自己的端口,前段没法访问,难的搞,我们就通过网关分发到对应的服务,统一入口(我们可以坐权限,限流,过滤器,拦截)

Zuul使用过滤器
Zuul的工作原理就是一系列的过滤器,只要继承ZuulFlter,并实现ZuulFlter中的抽象方法和IZuulFlter接口中的方法,
其中filterType()为过滤器的类型;filterOrder()为过滤顺序,为一个Int类型的值,值越小,越早执行。shouldFilter()表示是否执行过滤逻辑,true则执行run()方法,false则不执行run()方法。其中run()写具体的过滤的逻辑


Nginx
反向代理,先访问Nginx,再到Zuul,通过Zuul分发到各个服务


配置中心
(DV)就是配置文件会有很多很多很多,拉到一起统一管理


SpringBoot的理解

SpringBoot就是基于Spring更深封装的一个框架,就是简化Spring的。
什么初始搭建、开发过程、编码、配置、部署、监控都简单了,他还内置了tomcat

独立运行
简化配置
自动配置
无代码生成和XML配置
应用监控
上手容易

SpringBoot配置加载顺序

1.properties文件
2.yml
3.系统环境变量
4.命令行参数


SpringBoot自动配置原理

注解@EnableAutoConfiguration,@Configuration,@ConditionalOnClass就是自动配置的核心,首先他的是一个配置文件,其次根据类路径下是否有这个类,去自动配置


SpringBoot指定配置原理

首先就是SpringBoot的配置类大的标签@SpringBootApplication,这个组合类包含三个注解,其中一个就是@EuableAutConfiguration这个注解就是给这个类开启自动配置的


SpringBootApplication标签的作用

SpringBootApplication是一个组合标签,包含了三个标签
第一个:@SpringBootConfiguration---Spring的配置标签
第二个:@EnableAutoConfiguration---开启自动配置的标签
第三个:@ComponentScan---组件自动扫描的标签,施加在配置类上


SpringBoot项目中是怎么处理事务的

有手动配的,我们用的是注解的方式,在主配置类上打@EnableTransactionManagement这个标签就是开启事务管理器,其实这个不打也行,会自动配置,但是以防万一,打上最好

再就是在serviceImpl上加注解@Transactional


SpringBoot中读取配置可怎么读取

第一种就是使用@Value标签,加在配置读取的对象中
第二种就是@ConfigurationProperties,在实体类上绑定配置对象


SpringBoot中如何对Bean的定义方法加条件

就是打标签@Confitional在bean的定义方法上做判断,不满足就不定义bean,在你的判断上面记得要是@Condition


SpringBoot中如何导入properties配置文件

直接在properties里面配置,如果连接datasourceresources里面搞一个properties在配置数据库的四大要素


SpringBoot中如何导入xml配置文件

在配置类中加上注解@Configuration这个就相当于xml一样
再顶一个MyBean方法上打@Bean的标签,这样返回实例就自动交个Spring容器管理,在标签里面可以配置bean名称,生命周期方法,单例多例,懒初始化


微服务理解

就算是面向服务的框架,把单体项目拆分成多个服务,然后每个服务都可以独立的技术选型,独立开发,有各自的数据库,扩展非常方便,然后他们服务之间直接通过网络协议来通信


微服务和分布式的区别

微服务就是在分布式的基础上对其的本身做更细腻的拆分,每个都有自己的服务器进行部署,微服务一定是分布式,分布式就不一定是微服务

分布式就是多个服务器对其对应的服务进行部署


SpringCloud的理解

SpringCloud就是基于SpringBoot实现的服务治理的工具包,主要就是微服务框架中管理和协调服务的


知道dubbo嘛?

dubbo,知道的不多,就是rpc框架,通信基于tcp嘛!性能好,SpringCloud是基于http,相对而言性能就差一点点,dubbo在通信方面的性能高于SpringCloud


Eureka在微服务架构中充当什么样的角色

Eureka在微服务中就相当于注册中心,用来管理微服务的通信地址,就是实现服务的动态上线下线。
微服务启动的时候会把通信地址提交给注册中心,然后每一个服务都会从注册中心获取服务通信地址清单列表


项目中Zuul做了什么

Zuul服务网关----进来的请求都要通过Zuul网关,能知道哪些服务器在线,可以将请求自动转发到指定的微服务上面,也可以做所谓的过滤器处理(ZuulFiter)


一个请求进来在SpringCloud组件里面怎么执行的,先执行那个

①请求统一通过API网关(Zuul/Gateway)来访问内部服务
②网关接收到请求后,从注册中心(Eureka)获取可用服务
③有Feign(Ribbon)进行负载均衡后,分发到后端具体实例
④微服务之间通过Feign进行通信处理业务
⑤Hystrix负责处理服务超时熔断并降级


Zuul原理

过滤器机制:内置的特殊过滤器 --- 自定义的过滤器
Zuul提供了一个个框架,可以对过滤器进行动态的加载,编译,运行


Zuul怎么定义自己的过滤器

先自定义过滤器 --- 在新建配置类 --- 启动 --- 测试


如何在 Spring Boot 启动的时候运行一些特定的代码?

可以实现接口 ApplicationRunner或者 CommandLineRunner,这两个接口实现方式一样,它们都只提供了一个 run方法


Feign

在工程的pom文件中加入相关的依赖,在工程的配置文件application.yml做相关的配置,在程序的启动类EurekaFeignClientApplication加上注解@EnableEurekaClient开启eureka client的功能,通过注解@EnableFeignClients开启Feign Client的功能


注解


Spring/SpringMVC/MyBatis/SpringBoot/SpringCloud

@Controller:定义Controller层,Controller处理器,用来创建处理http请求的对象(控制层)
@RestController:返回json格式,不需要再配置ResponseBody
@RequestMapper("/add"):映射信息,定义url,指定路径(映射url请求/映射Http请求方法)
@ResponseBody:返回参数输入到 http response body 里面
@Service:标注业务层,注入到spring配置中(业务层)
@Entity : 表名是一个表【实体类】
@Autowired:用来装bean,自动依赖注入。可以在字段或者方法上,更精准的控制在哪里进行自动装配
@Column(updatable = false):一加上这个注解 就是一经保存就不可修改属性;身份证号码;创建时间domain中变量上加
@ModelAttribute :只要你通过路径访问当前的Controller,在访问之前,都会先执行他 【Controller方法上面加】
@Transaction:事务
@Resourse
@RequestParam:用来将请求参数据映射到方法的参数上(因为有时候你的参数和接口传递过来的不一样)
@Cacheable:支持缓存(value="",key="",condition="")value缓存的名称,key缓存的 key,condition缓存的条件
@Resource:用来装Bean
@Repository:数据访问组件的类标识为Spring Bean --- 在xml配置文件中启用bean的自动扫描,这可以通过实现
@Component:泛指组件,不好归类的时候,加上这个注解(任何层)
@RequestBody
@Data:(tostring/get/set)lombok包注解
@AllArgsConstructor:参构造器
@NoArgsConstructor:无参构造
@NoRepositoryBean --- 告诉SringDataJpa这是个父接口,不要实现
@Conditional:在bean的定义方法上做判断,不满足就不定义,在bean上加条件
@TableName("xxxx")
@EnableSwagger2:开启swagger2的支持
@Configuration
@EnableFeignClients("cn.itsource.hrm.client")
@EnableTransactionManagement:开启事务管理器
@MapperScan("cn.itsource.hrm.mapper")

@EnableEurekaClient:在EurekaServer环境下开启客户端

配置中心注解
@EnableDiscoveryClient:客气客户端
@EnableConfigServer:开启配置中心服务端
@SpringBootApplication

注册中心注解
@EnableEurekaServer:开启注册中心
@SpringBootApplication

网关
@SpringBootApplication
@EnableDiscoveryClient:客气客户端
@EnableZuulProxy :开启zuul网关

@Configuration

feign

redis
@SpringBootApplication
@EnableDiscoveryClient:客气客户端

@RestController
@RequestMapping("/fastdfs")
@Bean
@Document(indexName = "hrm" , type = "course")
@FeignClient(value = "es-server",fallback = ESCourseFeignClientFallBack.class)
@PostMapping("/es/searchCourse")
@GetMapping("/es/searchCourse")
@DelectMapping("/es/searchCourse")
@PostMapping("/es/searchCourse")
@Override:重写
@Repository
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ESServerApplication2050.class)
@TableField("template_url")
@TableId(value = "id", type = IdType.AUTO)
@Slf4j
@param: 传递的实体
@PathVariable("id")
@Primary
@ConfigurationProperties:在实体类上绑定配置对象
@Value("${xxx.xxx}"):加在配置读取对象中
@Qualifier
@Query("SQL语句") --- 分页要用到
@Param(" ")--- 模糊查询中用到 在上方5。测试中有实例
@Component


@Autowired 与@Resource的区别

ApplicationContext与BeanFactory的区别

ApplicationContextBeanFactory的子类,拥有更多的功能与方法
ApplicationContextbean是在读取的时候创建Bean对象,而BeanFactory是在使用的时候才进行对象的创建(懒加载)
ApplicationContext也可以通过配置让他变成懒加载 ,变成和BeanFactory一样


测试代码小Demo

1.java递归的简单实现方式----------递归计算100以内的数累计求和
public class TestDemo{
    public static void main(String[] args){
          System.out.println(sum(100));
    }
    public static int sum(int num){
        if(num == 1){
              return 1;
        }
        return num + sum(num - 1);
    }
}

记住:使用递归的时候,递归方法一定要有结束条件


2.单例模式代码----------懒汉模式(方法同步----添加同步锁)
public class TestDemo{
    private static TestDemo instance;
    private TestDemo(){}
    public static synchronized TestDemo getInstance(){
        if(instance == null){
            instance = new TestDemo();
        }
        return instance;
    }
}

3.枚举
public enum TestDemo{
    INSTANCE;
    public void whateverMethod(){
    }
}

4.静态内部类
public class Singleton {
    private Singleton() {}
    private static class SingletonInstance {
        private static final Singleton INSTANCE = new Singleton();
    }
    public static Singleton getInstance() {
        return SingletonInstance.INSTANCE;
    }
}

用最熟悉的语言写{5,2,1,3,4,9,6,7,8}的排序

一、直接调用api文档

int[] arr = {5,2,1,3,4,9,6,7,8};
Arrays.sort(arr);   //排序
System.out.println(Array.toString(arr));

二、使用冒泡排序

int[] arr = {5,2,1,3,4,9,6,7,8};
int i = 0;
for(int a = 0;a arr{b+1}){
        i = arr[b];
        arr[b] = arr[b+1];
        arr[b+1] = I;
}
}
}
System.out.println(Arrays.toString(arr));

可以用冒泡排序,但我开发中一般使用arrays的工具类进行冒泡排序,就是双层for循环,把大的值排到最后,前一个和后一个作比较,知道比较完。


前端

HTML5属性

src:资源路径
autoplay:自动播放
controls:显示控件(播放、暂停、进度条)
loop:循环播放


数据结构与算法

你可能感兴趣的:(Java初中级面试题大全)