数据库
1.postgre和mysql区别?
- 数据类型:PostgreSQL支持更多的数据类型,例如数组,json,hstore等,而MySQL则支持空间数据类型(GIS)。
- 扩展性:PostgreSQL相比MySQL具有更强的扩展性,支持自定义数据类型,函数和存储过程等。它还提供了一些高级功能,如异步复制,流复制,热备等。
- ACID:PostgreSQL具有更严格的ACID(原子性,一致性,隔离性和持久性)兼容性。在默认情况下,PostgreSQL使用更为严格的隔离级别,MySQL默认使用更低的隔离级别。
- 性能:MySQL比PostgreSQL更适用于大型的数据集,因为它的性能更好,特别是在读写和并发方面。而PostgreSQL在处理复杂的查询和更大数据集方面的性能表现更优秀。
-
并发性:PostgreSQL 比 MySQL 更好地处理并发性,Postgres 实现没有读锁的多版本并发控制 (MVCC),同时支持使用多个 CPU/内核的并行查询计划。
-
函数区别:ifnull()函数,sysdate()函数。
2.MVCC
多版本并发控制,是为了在读取数据时不加锁来提高读取效率和并发性的一种手段。在读已提交和可重复读隔离级别下的快照读,都是基于MVCC实现的。
实现原理
mvcc的实现,基于undolog、版本链、readview。在mysql存储的数据中,除了我们显式定义的字段,mysql会隐含的帮我们定义几个字段。
-
trx_id:事务id,每进行一次事务操作,就会自增1。
-
roll_pointer:回滚指针,用于找到上一个版本的数据,结合undolog进行回滚。
通过readview我们才知道自己能够读取哪个版本:
(1)如果要读取的事务id等于进行读操作的事务id,说明是我读取我自己创建的记录,那么可以读取。
(2)如果要读取的事务id小于最小的活跃事务id,说明要读取的事务已经提交,那么可以读取。
(3)max_trx_id表示生成readview时,分配给下一个事务的id,如果要读取的事务id大于max_trx_id,说明该id已经不在该readview版本链中了,故无法访问。
(4)m_ids中存储的是活跃事务的id,如果要读取的事务id不在活跃列表,那么就可以读取,反之不行。(活跃的事务就是指还没有commit的事务)
3.数据库连接池?
池化技术能够减少资源对象的创建次数,提高程序的响应性能,像常见的线程池、内存池、连接池、对象池都具有资源复用,高响应速度,统一的连接管理等共同特点。
数据库连接池:是程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由程序动态地对池中的连接进行申请,使用,释放。不使用数据库连接池,则对于每条 sql 语句,都要执行下面流程TCP三次握手建立连接>mysql登录认证>sql执行>mysql关闭>TCP四次挥手关闭。而使用数据库连接池,初次访问,建立连接。之后的访问复用之前的连接,直接执行 sql 语句。
- 线程池:主动操作,主动获取任务并执行
- 连接池:被动操作,连接对象被任务获取,执行完任务后归还
连接池设计思路:
- 创建构造函数:包含连接池名称,数据库IP,端口,用户名,密码,最小,最大连接数;
- init初始化:创建最小连接数连接插入list队列;
- 请求获取连接:先判断有没有空闲连接,有空闲连接,获取连接返回,没有空闲连接,判断是否能创建新的连接;
- 归还连接:检测该连接是否已经归还,避免重复归还。若还没有归还,插入空闲队列并通知取队列;
- 析构连接池:析构连接池,通知所有等待的请求退出;
4.多数据源?
【Java多数据源实现教程】实现动态数据源、多数据源切换方式_动态多数据源_小新要变强的博客-CSDN博客
5.数据库三大范式是什么?
- 第一范式:每个列都不可以再拆分。
- 第二范式:在第一范式的基础上,非主键列完全依赖于主键,而不能是依赖于主键的一部分。
- 第三范式:在第二范式的基础上,非主键列只依赖于主键,不依赖于其他非主键。
6.什么是游标?
游标是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果,每个游标区都有一个名字。用户可以通过游标逐一获取记录并赋给主变量,交由主语言进一步处理。
7.MySQL存储引擎MyISAM与InnoDB区别?
MySQL中的数据、索引以及其他对象是如何存储的,是一套文件系统的实现。
- Innodb引擎:Innodb引擎提供了对数据库ACID事务的支持。并且还提供了行级锁和外键的约束。它的设计的目标就是处理大数据容量的数据库系统。
- MyIASM引擎(原本Mysql的默认引擎):不提供事务的支持,也不支持行级锁和外键。
- MEMORY引擎:所有的数据都在内存中,数据的处理速度快,但是安全性不高。
区别:
- InnoDB索引是聚簇索引,MyISAM索引是非聚簇索引。
- InnoDB的主键索引的叶子节点存储着行数据,因此主键索引非常高效。
- MyISAM索引的叶子节点存储的是行数据地址,需要再寻址一次才能得到数据。
- InnoDB非主键索引的叶子节点存储的是主键和其他带索引的列数据,因此查询时做到覆盖索引会非常高效。
innodb的底层数据结构及其引擎的4大特性
引擎4大特性
-
插入缓冲(insert buffer)
-
二次写(double write)
-
自适应哈希索引(ahi)
-
预读(read ahead)
底层数据结构:B+树
在数据的底层存储上,InnoDB会根据每张表的主键构造一棵B+树,也就是说表中所有的数据都是存储在B+树中的。B+树是由B树演化而来,不同于B树适合在内存中遍历访问,B+树十分适合于在磁盘中存储与读取。如下图所示,即是一棵B+树
-
每个结点可以存储多个关键字,且每个结点可以有多于两个的孩子数;
-
所有叶子结点都位于同一层次;
-
有分支结点中的关键字会在叶子结点中再次列出,也就是说叶子结点中包含全部关键字的信息;
-
叶子结点之间通过双向链表链接,即每个叶子结点都有指向上一个和下一个叶子结点的指针;
-
叶子结点之间依关键字的大小自小而大链接。
为何适合于在磁盘中存储与读取
B+树更适合于在磁盘中存储与读取,主要体现在其具有高扇出性和范围查询的高效率上。
-
高扇出性:(扇出,是指上级模块直接调用的下级模块的数量)
高扇出性带来的好处就是查询效率的提升,比如3层的B+树,查询某个关键字只需要3次IO,再考虑到一般情况下,根结点总会缓存在内存中,所以只需要2次IO即可。
-
范围查询:
传统的二叉树需要通过前序遍历或其他遍历方法来查询所有结点中的关键字,而B+树所有的关键字都按照大小顺序保存在叶子结点中,且通过双向链表链接。因此针对范围查询,只需要从第一个匹配的关键字,通过链表继续向下匹配即可。
8.什么是索引?
是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。更通俗的说,索引就相当于目录。为了方便查找书中的内容,通过对内容建立索引形成目录。索引是一个文件,它是要占据物理空间的。
索引的分类:
主键索引(PRIMARY KEY)
建立在主键上的索引被称为主键索引,一张数据表只能有一个主键索引,索引列值不允许有空值,通常在创建表时一起创建。
唯一索引(UNIQUE)
建立在UNIQUE字段上的索引被称为唯一索引,一张表可以有多个唯一索引,索引列值允许为空,列值中出现多个空值不会发生重复冲突。
普通索引(INDEX)
建立在普通字段上的索引被称为普通索引。
全文索引(FULLTEXT)
MyISAM 存储引擎支持Full-text索引,用于查找文本中的关键词,而不是直接比较是否相等。Full-text索引一般使用倒排索引实现,它记录着关键词到其所在文档的映射。
索引的优点:
- 可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
- 通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。
索引的缺点:
- 时间方面:创建索引和维护索引要耗费时间,具体地,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,会降低增/改/删的执行效率;
- 空间方面:索引需要占物理空间。
索引的基本原理:(就是把无序的数据变成有序的查询)
-
把创建了索引的列的内容进行排序
-
对排序结果生成倒排表
-
在倒排表内容上拼上数据地址链
-
在查询的时候,先拿到倒排表内容,再取出数据地址链,从而拿到具体数据
创建索引的基本原则:
- 索引字段数据应该尽量不为NULL。
- 在经常查询、排序、分组的字段上建立索引。
- 连表操作的字段(外键)上建立索引。
- 使用联合索引需要注意。
- 多写表且频繁更新的字段要慎重建立索引,影响更新效率。
- 避免冗余索引。
- 区分度低的字段不应建立索引,如性别字段。
- 要注意单表索引数量,建议控制在5个之内。
9.哪些情况下索引会失效?
- or查询:如果条件中有or,前后条件都包含索引则走索引,否则索引失效。
- 前模糊查询:like查询是以%开头,索引会失效,以%结尾,不会失效。
- 数据类型不匹配:查询条件中的列类型是字符串,一定要在条件中将数据使用引号引用起来,否则不使用索引。
- 索引区分度不高:如果mysql估计使用全表扫描要比使用索引快,则不使用索引
- 联合索引失效:最左前缀原则,查询条件第一位不是联合索引的第一列则会失效;出现范围查询【>,<】,范围查询右侧的列索引失效,推荐使用>=或<=
- 查询条件使用函数或计算或建立索引时使用函数,将导致索引失效
- 空值判断: is null可以使用索引,is not null无法触发索引
9.事物的四大特性(ACID)介绍一下?
- 原子性: 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
- 一致性: 执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的;
- 隔离性: 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
- 持久性: 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
10.什么是脏读?幻读?不可重复读?
- 脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。
- 不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。
- 幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。
11.什么是事务的隔离级别?MySQL的默认隔离级别是什么?
Mysql 默认采用的 REPEATABLE_READ隔离级别;Oracle 默认采用的 READ_COMMITTED隔离级别
- READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
- READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
- REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
- SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。
12.数据库的乐观锁和悲观锁是什么?怎么实现的?
乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段。
悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。在查询完数据的时候就把事务锁起来,直到提交事务。实现方式:使用数据库中的锁机制(一般多写的场景下用悲观锁就比较合适)
乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。在修改数据的时候把事务锁起来,通过version的方式来进行锁定。实现方式:乐一般会使用版本号机制或CAS算法实现。(乐观锁适用于写比较少的情况下(多读场景))
注:CAS的全程是:Compare And Swap(比较并交换),CAS操作涉及到3个操作符:当前内存中的值、预估值、即将修改的新增,当且仅当预估值等于内存中的值的时候,才将新的值保存到内存中,否则什么都不做
13.什么是存储过程?
存储过程是一个预编译的SQL语句,优点是允许模块化的设计,就是说只需要创建一次,以后在该程序中就可以调用多次。如果某次操作需要执行多次SQL,使用存储过程比单纯SQL语句执行要快。
14.什么是触发器?
触发器是用户定义在关系表上的一类由事件驱动的特殊的存储过程。触发器是指一段代码,当触发某个事件时,自动执行这些代码。在MySQL数据库中有如下六种触发器:
- Before Insert
- After Insert
- Before Update
- After Update
- Before Delete
- After Delete
15.mysql中 in 和 exists 区别?
mysql中的in语句是把外表和内表作hash 连接,而exists语句是对外表作loop循环,每次loop循环再对内表进行查询。一直大家都认为exists比in语句的效率要高,这种说法其实是不准确的。这个是要区分环境的。
- 如果查询的两个表大小相当,那么用in和exists差别不大。
- 如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in。
- not in 和not exists:如果查询语句使用了not in,那么内外表都进行全表扫描,没有用到索引;而not extsts的子查询依然能用到表上的索引。所以无论那个表大,用not exists都比not in要快。
16.drop、delete与truncate的区别?
17.SQL优化?
SQL性能优化的目标:至少要达到 range 级别,要求是ref级别,如果可以是consts最好.
对于低性能的SQL语句的定位,最重要也是最有效的方法就是使用执行计划,MySQL提供了explain命令来查看语句的执行计划。对于查询语句,最重要的优化方式就是使用索引。 而执行计划,就是显示数据库引擎对于SQL语句的执行的详细情况,其中包含了是否使用索引,使用什么索引,使用的索引的相关信息等。
18.大表数据查询,怎么优化
- 优化shema、sql语句+索引;
- 第二加缓存,memcached, redis;
- 主从复制,读写分离;(主库负责写,从库负责读)
- 垂直拆分,根据你模块的耦合度,将一个大的系统分为多个小的系统,也就是分布式系统;
- 水平切分,针对数据量大的表,这一步最麻烦,最能考验技术水平,要选择一个合理的sharding key, 为了有好的查询效率,表结构也要改动,做一定的冗余,应用也要改,sql中尽量带sharding key,将数据定位到限定的表上去查,而不是扫描全部的表;
19.mysql数据库优化
- 创建索引
- 复合索引最左前缀原则
- 索引不会包含有NULL值的列
- 使用短索引
- 不使用NOT IN和<>操作
- 选取最适用的字段属性【控制字段大小CHAR(6);尽量把字段设置为NOTNULL】
- 使用左右关联来代替子查询
- 使用事务
20.sql语句里面的choose when的使用?
21.常用函数?
- instr(field, str) 第一个参数 field 是列字段,第二个参数 str 是要查询的串。select * from book where INSTR( book_name , "经" ) ----mysql 进行模糊查询时,可使用内部函数 instr,替代传统的 like 方式,并且速度更快。select instr(book_name, '水') from book ----返回串 str 的位置,没找到就是0。
- 时间函数 sysdate()
- 获取随机数 rand()
- 四舍五入 round()
- 合并字符串 concat()
- 获取字符串字符长度 length(str)
- 字母大小写转换 lower(),upper()
- 字符串的逆序函数 reverse()
- 条件判断 if(expr,v1,v2)
- 系统信息函数 version()
22.防止sql注入
简而言之,SQL注入意味着通过用户输入的数据在查询中注入/插入SQL代码。
SQL注入的四种类型:
- 基于布尔SQL注入
- 基于联合SQL注入
- 基于时间SQL注入
- 基于错误SQL注入
在这种变体中,攻击者试图从数据库中获取信息,例如错误代码和消息。 攻击者注入SQL在语法上是不正确的,因此数据库服务器将返回错误代码和消息,这些错误代码和消息可用于获取数据库和系统信息。
解决方案:
- 使用PreparedStatement而不是Statement来执行查询,从请求接收的用户名和密码的值仅被视为数据,因此不会发生SQL注入。
- 通过正则表达式等在查询中使用数据之前,请先对其进行验证。
- 不要使用常用词作为表名或列名。 例如,许多应用程序使用tbluser或tblaccount来存储用户数据。 电子邮件,名,姓是常用的列名。
- 不要直接串联数据(作为用户输入接收)来创建SQL查询。
- 通过权限和授予限制应用程序对数据库的访问。
- 不要将敏感的错误代码和消息返回给最终用户。
注:mybatis底层其实就是使用了PreparedStatement,在编写MyBatis的映射语句时,尽量采用“#{xxx}”这样的格式。若不得不使用“${xxx}”这样的参数,要手工地做好过滤工作,来防止SQL注入攻击。使用#即输入参数在SQL中拼接的部分,传入参数后,打印出执行的SQL语句,会看到SQL是这样的:【 select id, username, password, role from user where username=? and password=? 】不管输入什么参数,打印出的SQL都是这样的。这是因为MyBatis启用了预编译功能,在SQL执行前,会先将上面的SQL发送给数据库进行编译;执行时,直接使用编译好的SQL,替换占位符“?”就可以了。因为SQL注入只能对编译过程起作用,所以这样的方式就很好地避免了SQL注入的问题。
Mybatis
1.什么是Mybatis?
- Mybatis是一款优秀的持久层框架
- 他支持定制化sql,存储过程以及高级映射
- 他几乎避免了所有的JDBC代码,手动设置参数以及获取结果集。
2.为什么要用Mybatis?
- 帮助程序员将数据存入到数据库中;
- 传统的JDBC太复杂,简化了其操作,方便,简单,易上手;
- 灵活,sql和代码的分离,提高了可维护性;
- 提供xml标签,支持编写动态sql;
- 使用的人多;
3.Mybatis 的三种执行?
- SIMPLE: 默认的执行器, 对每条sql进行预编译->设置参数->执行等操作
- BATCH: 批量执行器, 对相同sql进行一次预编译, 然后设置参数, 最后统一执行操作
- REUSE: REUSE 执行器会重用预处理语句(prepared statements)
4.缓存机制
一级缓存是Mybatis默认开启的缓存,我们不用自己去手动开启.它是SQLSession级别的缓存,也称为本地缓存,当调用SqlSession的修改,添加,删除,commit().close(),clearCache()等方法时就会清空一次一级缓存。
二级缓存是SQLSessionFactory级别的缓存,作用域为一个namespace,也就是在同一个mapper下都会生效,由多SqlSession所共享.需要我们手动开启和配置。【二级缓存只有在一级缓存死掉的时候才会生效】
5.MyBatis与MyBatis-Plus的区别?
MyBatis-Plus是一个MyBatis的增强工具,在 MyBatis 的基础上进行封装,只做增强不做改变,为简化开发、提高效率而生。
MyBatis:
- MyBatis所有SQL语句全部自己写
- 手动解析实体关系映射转换为MyBatis内部对象注入容器
- 不支持Lambda形式调用
Mybatis Plus:
- 强大的条件构造器,满足各类使用需求
- 内置的Mapper,通用的Service,继承后通过少量配置即可实现单表大部分CRUD操作,连SQL语句都不需要编写
- 支持Lambda形式调用
- 自动解析实体关系映射转换为MyBatis内部对象注入容器
Spring
1.简单说一下spring
spring是轻量级的开源的javaEE框架,他可以解决企业应用开发的复杂性。spring有俩个核心部分,AOP面向切面编程及IOC控制反转。他的特点为:方便解耦,简化开发;支持AOP编程;方便程序测试;方便进行事务操作;方便与其他框架整合;
2.IOC了解一哈
IOC是spring的俩大核心概念之一,IOC提供了一个bean容器,这个容器会帮助我们去创建对象,而不需要我们手动的去创建对象。IOC容器有一个非常强大的功能DI,依赖注入。我们可以通过写java代码和基于xml的自动装配的方式,把我们想要注入对象所依赖的一些其他的bean自动的注入进去。正是因为依赖注入,使得IOC有了非常强大的功能解耦。比如JDBCTemplate,将它注入到容器中,是需要一个数据源的。如果JDBCTemplate和德鲁伊的数据源强耦合在一起,会导致我们要想使用JDBCTemplate,必须使用德鲁伊的数据源。而通过依赖注入,我们只需要在注入的时候将他依赖一个datasource接口,不需要去依赖具体的实现,这样的好处是将来我们注入一个德鲁伊的数据源,它会自动帮我们将其注入到JDBCTemplate,如果我们注入其他的数据源,其他的数据源,也是一样的。这样JDBCTemplate和我们的数据源就已经完全的解耦和了。它不强依赖于任何一个数据源。同时程序在启动的时候,就会把所有的bean帮我们全部创建好,程序运行的时候就不需要再创建bean,提高的程序的运行速度。IOC中帮我们管理着很多的bean,像service,mapper,controller在我们的容器中只有一份,用的时候直接注入就行了,不需要我们再为了这些类去独立的写单例,节省了我们的时间。
Spring的依赖注入有3种方式:
1.Setter方法注入
属性注入即通过setXxx()方法注入Bean的属性值或依赖对象,属性注入要求Bean提供一个默认的构造函数,并为需要注入的属性提供对应的Setter方法。
<!-- 属性注入 -->
<bean id="car" class="com.spring.model.Car">
<property name="maxSpeed" value="200"></property>
<property name="brand" value="红旗CA72"></property>
<property name="price" value="200000.00"></property>
</bean>
属性注入原理:Spring先调用Bean的默认构造函数实例化Bean对象,然后通过反射的方式调用Setter方法注入属性值
2.构造函数注入
生成该类带参的构造方法,通过构造器注入,我们可以在创建一个Bean实例时,将其所需的依赖项作为构造函数的参数进行传递。Spring容器会负责解析依赖关系并创建Bean的实例。其中用<constructor-arg>标签定义构造函数的参数。
3.注解注入
Spring框架提供了多个注解用于依赖注入,简化了配置和代码的编写。常用的注解包括:
@Autowired
:自动装配依赖项。@Qualifier
:在存在多个候选Bean时,指定要注入的具体Bean。@Resource
:指定要注入的Bean,并可以通过名称或类型进行查找。@Value
:注入简单的值,如基本类型、字符串等。
@autowired和@resource注解的区别:
- 来源不同; 【@Autowired 是 Spring 定义的注解,而 @Resource 是 Java 定义的注解】
- 依赖查找的顺序不同;【@Autowired 是先根据类型(byType)查找,如果存在多个 Bean 再根据名称(byName)进行查找,@Resource 相反】
- 支持的参数不同;【@Autowired 只支持 required 的参数,而 @Resource 支持 name 和 type 等7 个参数】
- 依赖注入的用法不同;【@Autowired 支持属性注入、构造方法注入和 Setter 注入,而 @Resource 只支持属性注入和 Setter 注入】
3.AOP了解一哈
AOP是面向切面编程,在日常工作当中,会遇到很多重复性的代码,比如说事物,比如说日志。我们需要在很多类里边,同时把这些代码全部写进去,这样的话是非常非常麻烦的,就比如说事务,我们需要在所有的service层里边去开启事务,提交回滚,这些事情我们都要写,但是能不能不写。当然可以,spring的AOP就给我们提供这些方式。我们可以把这些共有的代码抽象出来,然后切入到我们想要切入的类里面,这样使各部分之间的耦合度降低,提高了代码的可重用性,同时提高了开发效率。AOP的实现是依靠动态代理来完成的,如果我们将来要代理的这个对象,他有接口,那我们就使用JDK动态代理来创建接口实现类代理对象,增强类的方法。如果他没有实现任何的借口,他会采用CGLib动态代理创建子类的代理对象,增强类的方法。
Aop常用注解:
- @Aspect: 该注解是把此类声明为一个切面类。
- @Before: 该注解是声明此方法为前置通知 (目标方法执行之前就会先执行被此注解标注的方法)
- @After: 该注解是声明此方法为后置通知 (目标方法执行完之后就会执行被此注解标注的方法)
- @AfterReturning: 该注解是声明此方法为返回通知 (目标方法正常执行返回后就会执行被此注解标注的方法)
- @AfterThrowing: 该注解是声明此方法为异常通知 (目标方法在执行出现异常时就会执行被此注解标注的方法)
- @Around: 该注解是环绕通知是动态的,可以在前后都设置执行
- @PointCut: 该注解是声明一个公用的切入点表达式(通知行为的注解的都可以直接拿来复用)
SpringMVC
1.什么是Spring MVC?
Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把模型-视图-控制器分离,将web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。优点:
(1)可以支持各种视图技术,而不仅仅局限于JSP;
(2)与Spring框架集成(如IoC容器、AOP等);
(3)清晰的角色分配:前端控制器(dispatcherServlet) , 请求到处理器映射(handlerMapping), 处理器适配器(HandlerAdapter), 视图解析器(ViewResolver)。
(4) 支持各种请求资源的映射策略。
2.请描述Spring MVC的工作流程?
- 用户发送请求至前端控制器DispatcherServlet;
- DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handle;
- 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
- DispatcherServlet 调用 HandlerAdapter处理器适配器;
- HandlerAdapter 经过适配调用 具体处理器(Handler,也叫后端控制器);
- Handler执行完成返回ModelAndView;
- HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
- DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
- ViewResolver解析后返回具体View;
- DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
- DispatcherServlet响应用户。
3.Spring MVC常用的注解有哪些?
- @RequestMapping:用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径。
- @RequestBody:注解实现接收http请求的json数据,将json转换为java对象。
- @ResponseBody:注解实现将conreoller方法返回对象转化为json对象响应给客户。
-
@Controller:标记一个类是Controller。
@PathVariable和@RequestParam的区别:@PathVariable主要用于接收http://host:port/path/{参数值}数据。@RequestParam主要用于接收http://host:port/path?参数名=参数值数据,这里后面也可以不跟参数值。
4.@RestController和@Controller的区别
@Controller和@RestController注解都是标识该类是否可以处理HTTP请求,可以认为@RestController是@Controller和@ResponseBody的结合体。
- @Controller标识当前类是SpringMVC Controller处理器,而@RestController则只负责数据返回。
- 使用@RestController注解,则Controller中的方法无法返回Web页面,配置的视图解析器不起作用,返回的内容就是Return中的数据。如果需要返回指定页面,则使用@Controller注解,并配合视图解析器返回页面和数据。如果需要返回JSON、XML或自定义内容到页面,则需要在对应的方法上加上@ResponseBody注解。
- @RestController注解相当于@Controller和@ResponseBody两个注解的结合,能直接将返回的数据转换成JSON数据格式,无须在方法前添加@ResponseBody注解,但使用@RestController注解时不能返回JSP、HTML页面,视图解析器无法解析JSP、HTML页面。
5.Spring MVC与Struts2区别?
相同点:
- 都是基于mvc的表现层框架,都用于web项目的开发。
不同点:
- 1.前端控制器不一样。Spring MVC的前端控制器是servlet:DispatcherServlet。struts2的前端控制器是filter:StrutsPreparedAndExcutorFilter。
- 2.请求参数的接收方式不一样。Spring MVC是使用方法的形参接收请求的参数,基于方法的开发,线程安全,可以设计为单例或者多例的开发,推荐使用单例模式的开发(执行效率更高),默认就是单例开发模式。struts2是通过类的成员变量接收请求的参数,是基于类的开发,线程不安全,只能设计为多例的开发。
- 3.Struts采用值栈存储请求和响应的数据,通过OGNL存取数据,Spring MVC通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过reques域传输到页面。Jsp视图解析器默认使用jstl。
- 4.与spring整合不一样。Spring MVC是spring框架的一部分,不需要整合。在企业项目中,Spring MVC使用更多一些。
6.重定向和转发的区别?
- 转发在服务器端完成的;重定向是在客户端完成的
- 转发的速度快;重定向速度慢
- 转发的是同一次请求;重定向是两次不同请求
- 转发不会执行转发后的代码;重定向会执行重定向之后的代码
- 转发地址栏没有变化;重定向地址栏有变化
- 转发必须是在同一台服务器下完成;重定向可以在不同的服务器下完成
7.如何解决POST请求中文乱码问题,GET的又如何处理呢?
解决post请求乱码问题:
- 在web.xml中配置一个CharacterEncodingFilter过滤器,设置成utf-8;
get请求中文参数出现乱码解决方法有两个:
- ①修改tomcat配置文件添加编码与工程编码一致
- ②另外一种方法对参数进行重新编码:(String userName = new String(request.getParamter(“userName”).getBytes(“ISO8859-1”),“utf-8”);ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码。)
8.Spring MVC用什么对象从后台向前台传递数据的?
通过ModelMap对象,可以在这个对象里面调用put方法,把对象加到里面,前台就可以通过el表
达式拿到.
9.Spring MVC里面拦截器是怎么写的?
- 实现HandlerInterceptor接口
- 继承适配器类
Springboot
1.SpringBoot配置devtools实现热部署?
https://www.cnblogs.com/liu2-/p/9118393.html
spring为开发者提供了一个名为spring-boot-devtools的模块来使Spring Boot应用支持热部署,提高开发者的开发效率,无需手动重启Spring Boot应用。
devtools的原理:深层原理是使用了两个ClassLoader,一个Classloader加载那些不会改变的类(第三方Jar包),另一个ClassLoader加载会更改的类,称为restart ClassLoader,这样在有代码更改的时候,原来的restart ClassLoader 被丢弃,重新创建一个restart ClassLoader,由于需要加载的类相比较少,所以实现了较快的重启时间。
注意:在application.properties中配置spring.devtools.restart.enabled=false,此时restart类加载器还会初始化,但不会监视文件更新。在SprintApplication.run之前调用System.setProperty(“spring.devtools.restart.enabled”, “false”);可以完全关闭重启支持。
2.什么是 Spring Boot?
Spring Boot 是 Spring 开源组织下的子项目,是 Spring 组件一站式解决方案,主要是简化了使用 Spring 的难度,约定大于配置,简省了繁重的配置,提供了各种启动器,开发者能快速上手。
- 容易上手,提升开发效率,为 Spring 开发提供一个更快、更广泛的入门体验。
- 开箱即用,远离繁琐的配置。
- 提供了一系列大型项目通用的非业务性功能,例如:内嵌服务器、安全管理、监控、高速缓存等。
- 没有代码生成,也不需要XML配置。
- 避免大量的 Maven 导入和各种版本冲突
3.什么是 JavaConfig?
Spring JavaConfig 是 Spring 社区的产品,它提供了配置 Spring IoC 容器的纯Java 方法。因此它有助于避免使用 XML 配置。使用 JavaConfig 的优点在于:
- (1)面向对象的配置。由于配置被定义为 JavaConfig 中的类,因此用户可以充分利用 Java 中的面向对象功能。一个配置类可以继承另一个,重写它的@Bean 方法等。
- (2)减少或消除 XML 配置。基于依赖注入原则的外化配置的好处已被证明。但是,许多开发人员不希望在 XML 和 Java 之间来回切换。JavaConfig 为开发人员提供了一种纯 Java 方法来配置与 XML 配置概念相似的 Spring 容器。从技术角度来讲,只使用 JavaConfig 配置类来配置容器是可行的,但实际上很多人认为将JavaConfig 与 XML 混合匹配是理想的。
- (3)类型安全和重构友好。JavaConfig 提供了一种类型安全的方法来配置 Spring容器。由于 Java 5.0 对泛型的支持,现在可以按类型而不是按名称检索 bean,不需要任何强制转换或基于字符串的查找。
4.Spring Boot 自动配置原理是什么?
自动装配可以简单的理解为:通过注解或者一些简单的配置就能在spring boot的帮助下实现某款功能。比如你想要在项目中使用 redis 的话,直接在项目中引入对应的 starter 即可,引入后,通过少量注解和一些简单的配置就能使用第三方组件提供的功能了。
原理:@SpringBootApplication核心注解包含了以下 3 个注解:
- @Configuration:实现配置文件的功能
- @EnableAutoConfiguration:启用 SpringBoot 的自动配置机制
- @ComponentScan:Spring组件扫描
@EnableAutoConfiguration是实现自动装配的核心注解。Spring Boot通过@EnableAutoConfiguration注解开启自动装配,通过 SpringFactoriesLoader 最终加载META-INF/spring.factories中的自动配置类实现自动装配,自动配置类通过@Conditional
按需加载配置类。
5.比较一下 Spring Security 和 Shiro 各自的优缺点 ?
- Spring Security 是一个重量级的安全管理框架;Shiro 则是一个轻量级的安全管理框架
- Spring Security 概念复杂,配置繁琐;Shiro 概念简单、配置简单
- Spring Security 功能强大;Shiro 功能简单
6.Spring Boot中的监视器是什么?
Spring boot actuator是spring启动框架中的重要功能之一。Spring boot监视器可帮助您访问生产环境中正在运行的应用程序的当前状态。
7.什么是YAML?
YAML是一种人类可读的数据序列化语言。它通常用于配置文件。 与properties相比,如果我们想要在配置文件中添加复杂的属性,YAML文件就更加结构化,而且更少混淆。可以看出YAML具有分层配置数据。
8.springboot常用的starter有哪些?
- spring-boot-starter-web :提bai供 Spring MVC + 嵌入式的 Tomcat 。web开发du一整套
- mybatis-spring-boot-starter :提供 MyBatis持久层操作数据库zhi
- spring-boot-starter-test:提供完备的测试功能
- spring-boot-starter-thymeleaf:提供Thymeleaf模板dao视图整合
- spring-boot-starter-actuator:提供生产级监控
- spring-boot-starter-security :使用 SpringSecurity 进行身份验证和授权
- spring-boot-starter-data-redis`:提供 Redis整合能力
11.RequestMapping 和 GetMapping 的不同之处在哪里?
-
RequestMapping 具有类属性的,可以进行 GET,POST,PUT 或者其它的注释中具有的请求方法。
-
GetMapping 是 GET 请求方法中的一个特例。它只是 ResquestMapping 的一个延伸,目的是为了提高清晰度。
12.Spring Boot 有哪几种读取配置的方式?
Spring Boot 可以通过 @Value, @ConfigurationProperties 来绑定变量。【@Value("${info.address}");@ConfigurationProperties(prefix = "info")】
13.Spring Boot 支持哪些日志框架?推荐和默认的日志框架是哪个?
Spring Boot支持Java Util Logging,Log4j2,Lockback作为日志框架,如果你使用starters启动器,Spring Boot将使用Logback作为默认日志框架。无论使用哪种日志框架,Spring Boot都支持配置将日志输出到控制台或者文件中。
14.Spring MVC/Boot 统一异常处理最佳实践?
15.配置文件bootstrap和application的区别?
Spring Cloud
1.Spring Cloud 是什么?
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、智能路由、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。同时将比较成熟、经得起实际考验的服务框架组合起来,通过再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
2.Spring Cloud和SpringBoot版本对应关系?
3. Spring Cloud组件
负载均衡组件:Ribbon
一.Ribbon是什么:
是一套客户端负载均衡和服务调用工具,是 Spring Cloud 体系中最核心、最重要的组件之一
二.负载均衡:
将用户请求平摊到多个服务器上,以达到扩展服务器带宽、增强数据处理能力、增加吞吐量、提高网络的可用性和灵活性的目的。Ribbon 是一个基于 HTTP 和 TCP 的客户端负载均衡器,Ribbon 会从 Eureka Server(服务注册中心)中获取服务端列表,然后通过负载均衡策略将请求分摊给多个服务提供者,从而达到负载均衡的目的。
三.负载均衡算法:
1、轮询法【将请求按顺序轮流地分配到后端服务器上,它均衡地对待后端的每一台服务器,而不关心服务器实际的连接数和当前的系统负载】
2、随机法【通过系统的随机算法,根据后端服务器的列表大小值来随机选取其中的一台服务器进行访问。由概率统计理论可以得知,随着客户端调用服务端的次数增多,其实际效果越来越接近于平均分配调用量到后端的每一台服务器,也就是轮询的结果】
3、源地址哈希法【源地址哈希的思想是根据获取客户端的IP地址,通过哈希函数计算得到的一个数值,用该数值对服务器列表的大小进行取模运算,得到的结果便是客服端要访问服务器的序号。采用源地址哈希法进行负载均衡,同一IP地址的客户端,当后端服务器列表不变时,它每次都会映射到同一台后端服务器进行访问】
4、加权轮询,随机法【不同的后端服务器可能机器的配置和当前系统的负载并不相同,因此它们的抗压能力也不相同。给配置高、负载低的机器配置更高的权重,让其处理更多的请;而配置低、负载高的机器,给其分配较低的权重,降低其系统负载,加权轮询能很好地处理这一问题,并将请求顺序/随机按照权重分配到后端】
5、最小连接数法【最小连接数算法比较灵活和智能,由于后端服务器的配置不尽相同,对于请求的处理有快有慢,它是根据后端服务器当前的连接情况,动态地选取其中当前积压连接数最少的一台服务器来处理当前的请求,尽可能地提高后端服务的利用效率,将负责合理地分流到每一台服务器】
服务网关组件:Gateway
一.什么是服务网关:
在微服务架构中,一个系统往往由多个微服务组成,而这些服务可能部署在不同机房、不同地区、不同域名下。这种情况下,客户端(例如浏览器、手机、软件工具等)想要直接请求这些服务,就需要知道它们具体的地址信息,例如 IP 地址、端口号等。通过服务网关,请求直接到服务网关,再由服务网关根据不同的标识信息将请求转发到微服务实例。同时可以在服务网关中处理一些非业务功能的逻辑,例如权限验证、监控、缓存、请求路由等。
二.Spring Cloud Gateway:
Spring Cloud GateWay 最主要的功能就是路由转发,而在定义转发规则时主要涉及了以下三个核心概念【Route(路由),Predicate(断言),Filter(过滤器)】
Spring Cloud Gateway 工作流程说明如下:
- 客户端将请求发送到 Spring Cloud Gateway 上。
- Spring Cloud Gateway 通过 Gateway Handler Mapping 找到与请求相匹配的路由,将其发送给 Gateway Web Handler。
- Gateway Web Handler 通过指定的过滤器链(Filter Chain),将请求转发到实际的服务节点中,执行业务逻辑返回响应结果。
- 过滤器之间用虚线分开是因为过滤器可能会在转发请求之前(pre)或之后(post)执行业务逻辑。
- 过滤器(Filter)可以在请求被转发到服务端前,对请求进行拦截和修改,例如参数校验、权限校验、流量监控、日志输出以及协议转换等。
- 过滤器可以在响应返回客户端之前,对响应进行拦截和再处理,例如修改响应内容或响应头、日志输出、流量监控等。
- 响应原路返回给客户端。
熔断器组件:Hystrix
一.什么是Hystrix:
Spring Cloud Hystrix 是一款优秀的服务容错与保护组件,他能够有效地阻止分布式微服务系统中出现联动故障,以提高微服务系统的弹性。具有服务降级、服务熔断、线程隔离、请求缓存、请求合并以及实时故障监控等强大功能。