自我介绍
略,以及两道接口测试代码题目
什么是索引
索引可以帮助我们快速搜索数据,innodb 存储引擎用的是 b+树索引,叶子节点存放的是索引+数据,非叶子节点只存放索引。
可以按照四个角度来分类索引。
按数据结构分类:B+tree索引、Hash索引、Full-text索引。
按物理存储分类:聚簇索引(主键索引)、二级索引(辅助索引)。
按字段特性分类:主键索引、唯一索引、普通索引、前缀索引。
按字段个数分类:单列索引、联合索引。
- 查看存在索引的sql语句
show index from table
联合索引(a、b、c,什么时候失效)
通过将多个字段组合成一个索引,该索引就被称为联合索引。
创建索引abc ab a,最左前缀原则,如果不遵循最左匹配原则,联合索引会失效,这样就无法利用到索引快速查询的特性了。
a命中,b不命中,c不命中;ab命中;ac命中;bc不命中;abc命中,acb命中。
- 索引失效的场景有哪些,你知道什么改进方法吗?
- 当我们使用左或者左右模糊匹配的时候,也就是 like %xx 或者 like %xx%这两种方式都会造成索引失效;
- 当我们在查询条件中对索引列使用函数,就会导致索引失效。
- 当我们在查询条件中对索引列进行表达式计算,也是无法走索引的。
- MySQL 在遇到字符串和数字比较的时候,会自动把字符串转为数字,然后再进行比较。如果字符串是索引列,而条件语句中的输入参数是数字的话,那么索引列会发生隐式类型转换,由于隐式类型转换是通过 CAST 函数实现的,等同于对索引列使用了函数,所以就会导致索引失效。
- 联合索引要能正确使用需要遵循最左匹配原则,也就是按照最左优先的方式进行索引的匹配,否则就会导致索引失效。
- 在 WHERE 子句中,如果在 OR 前的条件列是索引列,而在 OR 后的条件列不是索引列,那么索引会失效。
SpringBoot常见注解
1. @RestController:用于定义Controller层的类,可以自动将返回结果转换为JSON格式;
2. @RequestMapping:用于定义URI映射,可以将请求路由到对应的Controller方法;
3. @Autowired:用于实现依赖注入,自动装配Bean实例;
4. @Service:用于定义Service层的类;
5. @Component:用于定义普通的Bean对象;
6. @Configuration:用于定义配置类;
7. @Value:用于从配置文件中加载属性;
8. @Transactional:用于实现事务的管理;
9. @ExceptionHandler:用于处理异常;
SpringBoot启动注解
整个spring框架启动分为两部分,构造SpringBootApplication对象和执行run方法
核心注解@SpringBootConfiguration标识启动类为配置类,@EnableAutoConfiguration通过内部@Import注解AutoConfigurationImportSelector.class实现自动装配,@ComponentScan默认扫描当前目录及子目录下的bean。
面试官:我们简单聊一下SpringBoot的启动流程吧。 - 掘金
-
AOP
AOP是OOPs(面向对象编程)的补充,它也提供了模块化。在面向对象编程中,关键的单元是对象,AOP的关键单元是切面,或者说关注点(可以简单地理解为你程序中的独立模块)。一些切面可能有集中的代码,但是有些可能被分散或者混杂在一起,例如日志或者事务。这些分散的切面被称为横切关注点。一个横切关注点是一个可以影响到整个应用的关注点,而且应该被尽量地集中到代码的一个地方,例如事务管理、权限、日志、安全等,使用方式主要通过注解实现。
为什么统一记录日志,怎么做的
项目中有很多业务模块,而每一个业务模块都有相同的系统需求,比如对它们做统一的记录日志、权限检查以及事务管理。而使用AOP的时候我们只需要单独定义一个组件,这个组件不会和业务组件发生任何直接的关系,我们不用去业务组件里面调用它,所以我们额外定义了系统组件,就好像这个组件横跨了多个业务组件,横向扩展业务组件的需求,所以为面向方面或者切面编程,变成的角度是面向这个横切组件。
定义了一个pointcut方法,加上注解@Pointcut(),生效范围为Service层下所有的类,编写before方法并加上Before注解。
Java集合
HashMap
HashMap底层是基于数组和链表实现的。简单来说,HashMap将key通过hash算法映射到数组中,然后在对应的链表中查找value。当多个key的hash值相同时,会在同一个数组位置上使用链表来存储这些key-value。但是,当链表长度太长时,会影响HashMap的性能,因此在JDK1.8中,当链表长度超过阈值时,会将链表转换为红黑树,以提高查找效率。
HashMap不是线程安全的,因为多个线程同时访问HashMap时可能会导致数据不一致的问题。可以使用ConcurrentHashMap来实现线程安全的Map。
- 存储不重复的元素用什么集合
set用于存放不重复的数据,如果需要排序使用TreeSet。
-
Java8新特性,Lambda表达式
Lambda 表达式 − Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)。
方法引用 − 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
-
项目中登录用什么做的(token)
用户登录之后,会给用户创建⼀个ticket,并放⼊cookie返回给浏览器,下⼀次再访问时,浏览器带上 cookie(ticket),服务端可以根据cookie确定用户的登录状态,以及通过ticket查询到用户id,通过用户id,就可以知道当前用户的具体信息了,把user放⼊model,再由模板引擎渲染后,返回HTML给客户端浏览器。
-
Redis用来干嘛了
使用Redis存储验证码,当用户点击刷新验证码时,服务端⾸先给当前需要登陆的游客,设置⼀个随机字符串(kaptchaOwner),用于标识 当前这个游客,然后将随机字符串存⼊到cookie中,返回给浏览器,然后服务端的redis保存 key:随机字符串, value:验证码 。
接着用户输⼊用户名,密码,验证码,再次点击登陆时,服务端会从cookie中拿到kaptchaOwner,通过它,可以从 Redis中得到正确的验证码,然后与用户输⼊的验证码做⽐较,看是否⼀致。
-
Redis为什么快
Redis将所有的数据都存在内存中,所以它的读写性能⼗分惊⼈。 同时,Redis还可以将内存中的数据以快照或者⽇志的形式保存到硬盘上,以保证数据的安全性。
-
Redis是单线程还是多线程?
Redis5及之前的版本使用的是 单线程,也就是说只有一个 worker队列,所有的读写操作都要在这一个队列进行操作,好处是不会有线程安全问题(因为它在读写时就只有一个线程,那对于读写操作肯定没有线程安全问题啊!),但是读写 write、read 这些系统调用在Redis执行期间占用了大部分的 CPU 时间,所以这就是单线程模式的缺点。
Redis6引入了多线程机制,但是不是说有多个worker线程同时并发读写, 而是它有 “一个 worker线程+多个IO子线程”,其实就是在 IO 就绪之后使用多线程提升读写解析数据的效率,而在操作内存数据的时候还是用单线程。
同时,这种机制同样不会产生线程安全问题,因为Redis在针对数据的内存操作时,是在一个公共的worker队列中实现的,先进先出,所以不会有线程安全问题。
面试官:Redis是单线程还是多线程?(你为何怎么说都不对?)_redis5 多线程_啊泽泽泽zz的博客-CSDN博客
-
单例模式
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
优点:
1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
2、避免对资源的多重占用(比如写文件操作)。
缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
-
Kafka为什么可以用来做系统通知
异步通信:很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。
-
ES怎么匹配关键词
为了增加效率,搜索引擎会把正向索引变为反向索引(倒排索引)即把“文档→单词”的形式变为“单词→文档”的形式。倒排索引具体机构如下:
单词1→文档1的ID;文档2的ID;文档3的ID…
使用到的分词器为IK分词器,match查询会将搜索词分词,再与目标查询字段进行匹配,若分词中的任意一个词与目标字段匹配上,则可查询到。