- 简述spring的优势与劣势
优点:
spring是一个轻量级的开发框架,提供了一种管理对象的方法,
可以把中间层对象有效地组织起来。采用了分层结构,可以增量引入到项目中。
缺点:
spring使用了大量的反射机制,非常占用内存。
因为简化开发,如果需要深入给底层去了解就非常困难。
- 什么是Spring的IOC?
SpringIOC称为控制反转,是Spring框架的核心。
把对象的创建交给spring创建我们就可以称之为控制反转。
spring提供了三种方式来依赖注入,
构造器注入,set方法注入,p标签注入
- 什么是Spring的Aop?
SpringAOP是面向切面编程,对逻辑业务方法和非业务方法进行分离。
减少重复代码,降低了程序之间的耦合,后期维护管理方便。
提高程序的可重用性,同时提高了开发的效率。
AOP的底层实现是基于JDK的动态代理和基于Cglib的动态代理。
- Spring的循环依赖是什么?Spring是如何解决的?
循环依赖,就是两个或则两个以上的bean互相依赖对方,最终形成闭环。
Spring解决循环依赖的方法是在实例化之后,依赖注入之前,
将实例化的对象放到缓存中进行提前曝光,后边的对象则在实例化前,
先到缓存中查找有无对应的实例化对象。
- Spring的Bean的生命周期是什么?
对bean进行实例化 -> 对bean属性进行赋值 ->
调用bean的初始化方法 -> 容器关闭时,调用bean的销毁方法
- SpringMVC的执行流程是?
1.客户端发起请求,前端控制器接收这个请求。
2.前端控制器将请求信息交给处理器映射器,
处理器映射器根据地址查找对应的处理器与拦截器,
并封装为一个处理器执行链对象返回给前端控制器。
3.前端控制器调用相应的处理器适配器执行处理器里的方法,
执行完后返回给前端控制器一个Model视图对象。
4.前端控制器将Model视图交给视图解析器解析,
解析完后返回给前端控制器一个具体的物理视图。
5.前端控制器将Model里的数据渲染到View里,并响应回客户端。
- SpringMVC是如何解析传入的JSON为实体类对象的?
导入jackson的jar包,
在处理请求的方法上加上@ResponseBody注解,将返回的数据放在响应体中。
在形参列表加上@RequestBody注解,用于获取请求体中的内容。
- SSM项目中的注解有哪些,并介绍注解的作用
1.@Test
在类上面加入,声明这个类是一个测试类
2.@Param
方法传参时给参数取别名
3.@component
表示这个类或接口是spring组件,相当于当前类或接口在spring中声明的
4.@Service
声明这个类在业务层
7.@Controller
声明这个类在控制层
8.@Repository
声明这个类在dao层
9.@value
给属性赋值,相对于set方法
10.@Autowired
自动注入对象,ioc的体现
11.@RequestMapping
表示前端请求的映射路径
12.@RequestParam
对前端传到后台的值取别名
13.@ResponseBody
响应ajax请求,将返回的数据放在响应体中
14.@PathVariable
url路径传参到处理器
15.@Transactional
业务层开启事务自动提交
- Mybatis 是如何进行进行接口与xml的映射?
1.在mybatis容器初始化的时候,会自动进行驱动注册,
并把xml中配置的sql语句按照接口名加sqllID的方式作为key,
2.sql语句作为value放入hashMap中存储起来,
等到使用的时候从hashmap中取出,经过反射处理得到原生的sql语句,
再使用jdbc进行执行!
3.执行过程中,如果有parameterType映射错误,
或者SQL语句错误,则会抛出异常到应用层!
4.得到数据操作结果以后,使用resultmap中的映射关系
把数据映射到JAVA实体类中,并创建相应的实例对象!
- Mybatis的优势是什么?# 与$ 的区别是?
优点:
1.基于SQL语句编程,相当灵活,
不会对应用程序或者数据库的现有设计造成任何影响,
SQL写在XML里,解除sql与程序代码的耦合,便于统一管理;
提供XML标签,支持编写动态SQL语句,并可重用。
2.与JDBC相比,减少了代码量,消除了大量冗余的代码,不需要手动开关连接;
3.很好的与各种数据库兼容。
4.能够与Spring 很好的集成;
5.提供映射标签,支持对象与数据库的ORM 字段关系映射;
提供对象关系映射标签,支持对象关系组件维护。
区别:
1、#对传入的参数视为字符串,也就是它会预编译,
2、$将不会将传入的值进行预编译,
3、#的优势就在于它能很大程度的防止sql注入,而$则不行。
- Linux的常用命令?
盘符切换命令:
cd ..回退上一级目录
cd / :回退根目录
cd 目录名称 :进入指定的目录名称
cd /usr/local:进入多级目录
文件操作命令:
mkdir: 创建目录
vim 文件: 编辑文本文件
touch: 创建新文件
cat 源文件: 查看文件内容
ls: 查看当前目录下的所有文件以及文件夹的名称
-l: 列出文件的详细信息
-a: 列出所有文件,包括隐藏文件
ll: 查看当前目录下的所有的文件以及文件夹的详情信息
pwd: 显示当前访问的文件夹的路径
rm: 删除文件或者文件夹
-i: interactive 若覆盖,先询问
-r: recursive mode 删除所有子文件(夹)
rm -rf: 文件或者文件夹 (删除文件以及文件夹(递归删除)) 暴力删除
mv 以前具体的文件名称 新的文件名称 改名
mv 文件名称 路径 : 剪切过去改名
cp: 复制copy
-i: interactive mode,若有同名文件,会询问是否覆盖(如果没这个参数,会不提示,直接覆盖)
-r:复制文件夹时连同子文件(夹)一起复制,如果是对文件夹进行操作,一定要带这个参数
-jcv:压缩
-jxv:解压
- Docker的常用命令?
启动docker
systemctl start docker
关闭docker
systemctl stop docker
重启docker
systemctl restart docker
docker设置随服务启动而自启动
systemctl enable docker
查看docker 运行状态
systemctl status docker
查看docker 版本号信息
docker version
docker info
docker 帮助命令
docker --help
查看自己服务器中docker镜像列表
docker images
搜索镜像
docker search 镜像名
拉取镜像
docker pull 镜像名 (拉取docker仓库中该镜像的最新版本)
docker pull 镜像名:tag(拉取指定版本)
运行镜像
docker run 镜像名
docker run 镜像名:Tag
删除镜像(当前镜像没有被任何容器使用才可以删除)
docker rmi -f 镜像名/镜像ID
删除多个 镜像ID或镜像用空格隔开
docker rmi -f 镜像名/镜像ID 镜像名/镜像ID 镜像名/镜像ID
删除全部镜像 -a 意思为显示全部, -q 意思为只显示ID
docker rmi -f $(docker images -aq)
强制删除镜像
docker image rm 镜像名称/镜像ID
- 说说你了解的安全框架?并介绍认证/授权流程
shiro:
Shiro是一个强大且易用的Java平台的开源权限框架,
用于身份验证、授权、加解密和会话管理,
shiro具有的功能:
1.用户分配角色,角色定义权限;
2.访问授权时支持角色或者权限,并且支持多级的权限定义;
认证流程:
1)用户点击登录---发送请求
2)控制器----接收前台请求----获取用户信息
3)创建安全管理器实例SecurityManager
SecurityUtils设置SecurityManager
SecurityUtils获取主体对象
Subject 获取用户的信息
存储到认证凭据器UserNamePasswordToken
subject主体对象.login(token对象)
4)realm交给SecurityManager
安全管理器将登录的请求告诉realm
5)realm执行认证的方法
通过token对象获取用户名
通过Jpa的操作方式,通过用户名找用户
判断对象是否为空,如果不为空,获取它的密码
6)授权
通过安全管理器告知realm用户具有的权限
- Springboot的自动装配原理
在@SpringBootApplication中有一个注解@EnableAutoConfiguration,
作用是开启自动配置
Spring Boot启动的时候会通过@EnableAutoConfiguration注解
找到META-INF/spring.factories配置文件中的所有自动配置类,
并对其进行加载,而这些自动配置类都是以AutoConfiguration结尾来命名的,
它实际上就是一个JavaConfig形式的Spring容器配置类,
它能通过以Properties结尾命名的类中取得在全局配置文件中配置的属性
如:server.port,
而Properties类是通过@ConfigurationProperties注解
与全局配置文件中对应的属性进行绑定的。
- Jpa是如何进行使用的?注解有哪些?作用是?
使用:
自定义接口继承JpaRepository,传入泛型,
第一个参数为要操作的实体类,第二个参数为该实体类的主键类型
注解:
@Repository
将DAO类声明为Bean
@Entity
对实体注释。任何Hibernate映射对象都要有这个注释
@Table
声明此对象映射到数据库的数据表,通过它可以为实体指定表(talbe),
name:表名
@Id
声明此属性为主键
@GeneratedValue
指定主键的生成策略
TABLE:使用表保存id值,通过表产生主键
IDENTITY:通过序列产生主键
SEQUENCR :表自增长字段
@Column
声明该属性与数据库字段的映射关系
- Redis是什么?存储结构?存储类型?持久化方式?三大场景问题?应用场景?淘汰策略?
Redis是一个NoSQL的,基于内存的的非关系型数据库
存储结构: Key-value格式
存储类型有
String 字符串类型
hash 散列类型
list 列表类型
set 集合类型
zset 有序集合类型
持久化方式:
Redis持久化存储支持两种方式:RDB和AOF(建议两种方式同时使用)
RDB一定时间取存储文件,
AOF默认每秒去存储历史命令,
1.RDB是redis默认持久化的方式
快照是redis默认的持久化的方式,
这种方式在规定的时间将内存中数据以快照的方式写入到二进制文件中,
默认的文件名是:dump.rdb;
可以通过配置设置自动持久化的方式,
我们可以修改redis.conf文件,
来配置redis在n秒如果超过m个key被修改,则自动做快照操作。
缺点:
由于快照的方式有一定的间隔时间,
所以如果redis在间隔时间内意外down掉后,
就会丢失最后一次快照后的所有数据。
2.AOF
aof比快照方式有更好的持久化性
是由于在使用aof时,
redis会将每一个收到的命令通过write函数追加到文件中,
当redis重启后,会通过重新执行aof文件中的内容,
来在内存中重建整个数据库的内容。
三大场景问题:
1.缓存雪崩现象
一般redis的数据都是有过期时间。
当大量的数据在同一时间失效,
此时大量的用户请求就会直接请求我们的数据库,
此时就有可能将我们的数据库打崩。
解决:
存入redis的数据的过期值添加一些随机数,
这样数据不会大量的在同一时间过期,即使有一部分数据过期了,
访问了数据库,也不会出现问题,
访问到数据库后又会将这个数据存入redis,这样就避免了缓存雪崩问题。
2.缓存击穿
缓存击穿现象,缓存中没有但数据库中有的数据(一般是缓存时间到期)
一般针对redis中的热点数据,用户对这一条数据进行的请求非常大,
这些请求就会涌入数据库,也可能会打崩我们的数据库。
解决:
将热点数据设置永不过期。
3.缓存穿透
缓存穿透现象,缓存中没有,数据库也没有的数据。
这种是一种不合法的请求方式(攻击方式),
在我们的数据库和redis中都没有的情况下,
这个请求就穿过了我们的redis,查询数据库,
由于我们的数据库中也没有就无法同步到redis,
就可能会将我们的数据库打崩。
解决:
1.对请求的接口进行鉴权,数据合法性的校验等;
比如查询的userId不能是负值或者包含非法字符等。
2.当数据库返回空值时,将空值缓存到redis,并设置合理的过期时间。
3.使用布隆过滤器存储所有可能访问的key,
不存在的key直接被过滤,存在的key则再进一步查询缓存和数据库。
Redis的淘汰策略
在使用Redis的过程中,当Redis缓存被写满之后,
Redis就会根据配置的淘汰策略进行数据淘汰。
Redis一共有8种淘汰策略。
1.noeviction
不进行数据淘汰,也是Redis的默认配置。
这时,当缓存被写满时,再有写请求进来,
Redis不再提供服务,直接返回错误。
2.volatile-random
缓存满了之后,在设置了过期时间的键值对中进行随机删除。
3.volatile-ttl
缓存满了之后,会针对设置了过期时间的键值对中,
根据过期时间的先后顺序进行删除,越早过期的越先被删除。
4.volatile-lru
缓存满了之后,针对设置了过期时间的键值对,
采用LRU算法进行淘汰,
5.volatile-lfu
缓存满了之后,针对设置了过期时间的键值对,
采用LFU的算法进行淘汰。
6.allkeys-random
缓存满了之后,从所有键值对中随机选择并删除数据。
7.allkeys-lru
缓存写满之后,使用LRU算法在所有的数据中进行筛选删除。
8.allkeys-lfu
缓存满了之后,使用LRU算法在所有的数据中进行筛选删除。
- nginx 是什么?作用是什么?有哪些负载均衡的策略?
Nginx的概述:
Nginx是一个高性能的HTTP和反向代理服务器
也是一个IMAP/POP3/SMTP代理服务器。
Nginx的作用:
1、作为Web服务器
2、作为负载均衡服务器
3、作为邮件代理服务器
负载均衡策略
1、轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,
如果后端服务器关闭掉,能自动剔除。
2、指定权重
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
3、IP绑定 ip_hash
指定负载均衡器按照基于客户端IP的分配方式,
这个方法确保了相同的客户端的请求一直发送到相同的服务器,
以保证session会话。
这样每个访客都固定访问一个后端服务器,
可以解决session不能跨服务器的问题。
4、fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
5、url_hash(第三方)
按访问url的hash结果来分配请求,
使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
6.least_conn
把请求转发给连接数较少的后端服务器。
- mysql的索引是什么?如何进行设置?
索引的概念:
索引是一种单独的、物理的
对数据库表中一列或多列的值进行排序的一种存储结构,
它是某个表中一列或若干列值的集合和
相应的指向表中物理标识这些值的数据页的逻辑指针清单。
索引的作用相当于目录,可以根据目录中的页码快速找到所需的内容。
索引的作用:
加快查找效率.减慢插入和删除,修改效率.(需要同步调整索引结果)
添加索引:
1、使用CREATE INDEX语句
CREATE INDEX [<索引名>] ON <表名> (<列名> [<长度>] [ ASC | DESC])
2.使用 CREATE TABLE 语句
1)创建主键索引
CONSTRAINT PRIMARY KEY [索引类型] (<列名>,…)
2)创建一般索引
KEY | INDEX [<索引名>] [<索引类型>] (<列名>,…)
3)创建唯一性索引
UNIQUE [ INDEX | KEY] [<索引名>] [<索引类型>] (<列名>,…)
4)创建外键索引
FOREIGN KEY <索引名> <列名>
- 写出最擅长的排序方式 (除了 冒泡排序)
选择排序思想:
第一次从 arr[0]~arr[n-1] 中选取最小值,与 arr[0] 交换
第二次从 arr[1]~arr[n-1] 中选取最小值,与 arr[1] 交换
第 i 次从 arr[i-1]~arr[n-1] 中选取最小值,与 arr[i-1] 交换
依次类推,总共通过 n - 1 次,得到一个按排序码从小到大排列的有序序列
public void SelectSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int min = arr[i];
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) {
if (min > arr[j]) {
min = arr[j];
minIndex = j;
}
}
if (minIndex != i) {
arr[minIndex] = arr[i];
arr[i] = min;
}
System.out.println("第 " + (i + 1) + " 轮排序后:" + Arrays.toString(arr));
}
}
- 说出最熟悉的设计模式,以及是怎么在程序中应用的?
单例模式:
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
优点:
1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例
2、避免对资源的多重占用(比如写文件操作)。
缺点
1、没有接口,不能继承,
2、与单一职责原则冲突,
3、一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
public class Teacher {
private static Teacher t ;
private Teacher(){}
public synchronized static Teacher getTeacher(){
if(t == null){
t = new Teacher() ;
}
return t ;
}
}
饿汉式
在程序启动或单例模式类被加载的时候,单例模式实例就已经被创建。
好处:饿汉式是线程安全的。
坏处:对象加载时间过长。
饿汉模式通过提前初始化一个实例来解决多线程问题
public class SingletonHungry {
private static SingletonHungry instance = new SingletonHungry();
private SingletonHungry() {
System.out.println("one");
}
public static SingletonHungry getInstance() {
return instance;
}
}
懒汉式
当程序第一次访问单例模式实例时才进行创建。
好处:延迟对象的创建。
坏处:线程不安全--->到多线程内容时,再修改。
懒汉模式通过同步解决多线程问题
public class SingletonLazy {
private static SingletonLazy instance;
private SingletonLazy() {
System.out.println("two");
}
public static SingletonLazy getInstance() {
if(instance != null) return instance;
synchronized (SingletonLazy.class) {
if(instance == null) instance = new SingletonLazy();
return instance;
}
}
}