一、线程与进程
1、什么是线程和进程?它们之间有什么区别?
答案:
线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个进程可以有很多线程,每条线程并行执行不同的任务。线程共享进程的资源,如内存空间和文件描述符,但有自己的程序计数器、栈和局部变量。
进程则是程序执行的一个实例,拥有独立的内存空间和系统资源。每个进程都有自己的地址空间、数据栈和其他系统资源。进程间通信需要通过特定的机制,如管道、消息队列等。
线程与进程的主要区别在于它们的资源占用和通信方式。线程间共享进程资源,因此切换线程的开销通常小于切换进程。然而,由于共享资源,线程间的同步和互斥问题也更为复杂。
2、Java中如何实现多线程?
答案:
在Java中,实现多线程主要有:
- 通过继承java.lang.Thread类,并重写其run()方法。
- 实现java.lang.Runnable接口,并实现其run()方法。
- 使用Callable和Future,Callable接口与Runnable类似,但它可以返回结果,并且可以抛出异常。
- 使用线程池。ExecutorService接口代表了一个异步执行机制,它可以管理一组线程,允许你提交任务来异步执行。使用线程池可以减少线程创建和销毁的开销,提高系统性能。
3、start()方法和run()方法有什么区别?
答案:
start()方法和run()方法在多线程编程中扮演着不同的角色。调用start()方法会启动一个新的线程来执行run()方法中的代码。而直接调用run()方法则会在当前线程中同步执行run()方法中的代码,不会创建新的线程。因此,只有调用start()方法才能表现出多线程的特性。
4、什么是线程的生命周期?Java线程有哪些状态?
答案:
线程的生命周期描述了线程从创建到销毁的过程。在Java中,线程的状态包括:新建(NEW)、就绪(RUNNABLE)、阻塞(BLOCKED)、等待(WAITING)、超时等待(TIMED_WAITING)和终止(TERMINATED)。线程在不同的状态下会进行不同的操作,如等待获取锁、执行任务、等待通知等。
5、什么是线程同步?Java中如何实现线程同步?
答案:
线程同步是多线程编程中的一个重要概念,用于保证在并发环境中数据的一致性和完整性。在Java中,可以通过使用synchronized关键字或Lock接口来实现线程同步。synchronized关键字可以修饰方法或代码块,使得同一时间只有一个线程可以执行被修饰的方法或代码块。Lock接口则提供了更灵活的锁机制,可以实现更复杂的同步需求。
6、什么是死锁?如何避免死锁?
答案:
死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法向前推进。
避免死锁的方法主要有:
避免嵌套锁:尽量避免在一个线程中同时请求多个锁,因为可能导致循环等待条件,从而引发死锁。
设置锁超时:在尝试获取锁时设置一个超时时间,超时后放弃锁的请求,这样可以防止线程无限期的等待。
7、Java中如何保证线程安全?
答案:
使用同步机制:通过synchronized关键字或ReentrantLock等锁机制来确保线程同步,防止多个线程同时访问共享资源导致数据不一致。
使用不可变对象:不可变对象一旦创建,其状态就不能被改变,因此可以安全地在多线程环境下共享。
使用线程安全的集合类:如Vector、Hashtable、ConcurrentHashMap等,这些集合类内部已经实现了同步机制,可以在多线程环境下安全使用。
避免共享资源:尽量将共享资源封装在局部方法中,避免多个线程同时访问同一资源。
8、Java中的volatile关键字有什么作用?
答案:
volatile关键字:用于修饰变量,确保变量对所有线程的可见性。当一个变量被声明为volatile时,线程在写入变量时会立即刷新到主存中,其他线程在读取该变量时会直接从主存中读取,而不是从自己的缓存中读取。这样就保证了变量的可见性。但是,volatile并不保证原子性,即它不能保证复合操作的原子性。
9、Java中的线程池是什么?它有什么好处?
答案:
线程池:是一种基于池化技术的线程管理机制,它能够减少线程的创建和销毁开销,提高系统的性能。
好处:
降低资源消耗:通过复用已存在的线程,减少线程的创建和销毁的开销。
提高响应速度:当任务到达时,可以立即分配线程进行执行,而不需要等待线程的创建。
提高线程的可管理性:线程池可以统一管理线程,包括线程的创建、调度、执行和销毁等。
10、线程间通信的方式有哪些?
答案:
线程间通信的主要方式包括:
共享内存:线程之间通过读写共享变量来交换信息。这种方式需要确保线程间的同步,以避免数据不一致。
管道和流:通过管道的输入/输出流进行数据的传递。这种方式主要用于I/O操作,但也可以用于线程间的通信。
等待/通知机制:使用Object类的wait()、notify()和notifyAll()方法。当一个线程需要等待某个条件成立时,可以调用wait()方法进入等待状态;当条件成立时,其他线程调用notify()或notifyAll()方法来唤醒等待的线程。
Lock和Condition:ReentrantLock提供了Condition接口,用于支持更灵活的线程间通信。与Object的监视器方法相比,Condition接口允许多个条件变量,并且提供了更精细的锁控制。
二、MySql
1、mysql的索引有哪些?
按照数据结构分类:B+树(InnoDB存储引擎和MyISAM存储引擎,存储的是全量的),Hash索引(精确定位),全量索引。
mysql 有4种不同的索引: 主键索引(PRIMARY) 唯一索引(UNIQUE) 普通索引(INDEX) 全文索引(FULLTEXT)。
2、InnoDB索引和MyISAM索引实现的区别是?
(1)存储上:InnoDB聚集索引,索引即数据,数据即索引;非聚集索引,没有记录完整内容,需要先通过索引找到主键值,再通过主键值来查询数据完整记录。MyISAM的索引和数据是分开的,MyISAM的索引文件仅保存数据记录的地址(或称为指针)。
(2)数据库访问上:InnoDB:由于采用了聚集索引,InnoDB可以直接通过索引定位到数据行,无需额外的磁盘I/O操作。对于非聚集索引的查询,虽然需要回表操作,但由于索引和数据都在内存中(通过缓冲池),因此访问速度仍然很快。MyISAM:在查询时,MyISAM需要通过索引文件找到数据记录的地址,然后再通过地址访问数据文件中的数据行。这种额外的磁盘I/O操作可能会降低查询性能。
3、如果一个表中没有创建索引,那么还会创建B+树吗?
如果指定了主键,就会根据该主键创建聚集索引,如果没有主键,mysql会生成一个隐式的rowId作为聚集索引,因此,会创建B+树。
4、B树和B+树的区别?
B+树和树都以固定16K页来存储,
(1)B树的每一个页存储主键或者索引值同时也一起存储了数据 。
(2)B+树的每一页都存储了主键或者索引值,只有最叶子节点存储了数据。
5、常见的索引原则?
1. 选择唯一性索引,唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。 2. 为经常需要排序、分组和联合操作的字段建立索引。
3. 为常用作为查询条件的字段建立索引。
4. 限制索引的数目: 越多的索引,会使更新表变得很浪费时间。尽量使用数据量少的索引 。5. 如果索引的值很长,那么查询的速度会受到影响。尽量使用前缀来索引 。
6. 如果索引字段的值很长,最好使用值的前缀来索引。
7. 删除不再使用或者很少使用的索引 。
8. 最左前缀匹配原则,非常重要的原则。
9. 尽量选择区分度高的列作为索引区分度的公式是表示字段不重复的比例 。
10. 索引列不能参与计算,保持列“干净”:带函数的查询不参与索引。
11. 尽量的扩展索引,不要新建索引。
6、 MySQL中的事务具有哪些特性(ACID属性)?这些特性在事务中分别起什么作用?
答案:
MySQL中的事务具有ACID四个基本属性,即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。
原子性:事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。这通过回滚(Rollback)机制实现,如果事务中的任何操作失败,则事务中的所有操作都会被撤销,数据库回到事务开始前的状态。
一致性:事务必须使数据库从一个一致性状态变换到另一个一致性状态。这意味着事务执行的结果必须是合理的,数据库的完整性约束(如外键约束、主键约束等)不会被破坏。
隔离性:事务的执行不能被其他事务干扰。MySQL通过锁和事务隔离级别来保证事务的隔离性,防止脏读、不可重复读和幻读等并发问题。
持久性:一旦事务提交,则其结果永久保存在数据库中,即使系统崩溃,重新启动后数据库还能恢复到事务成功结束的状态。这通过redo log等机制实现,确保数据的持久化存储。
7、数据库的三范式是什么?
第一范式:列不可再分 第二范式:行可以唯一区分,主键约束 第三范式:表的非主属性不能依赖与其他表的非主属性 外键约束 且三大范式是一级一级依赖的,第二范式建立在第一范式上,第三范式建立第一第二范式上 。
8、简单说一说drop、delete与truncate的区别?
SQL中的drop、delete、truncate都表示删除,但是三者有一些差别 delete和truncate只删除表的数据不删除表的结构 速度,一般来说: drop> truncate >delete delete语句是dml,这个操作会放到rollback segement中,事务提交之后才生效; 如果有相应的trigger,执行的时候将被触发. truncate,drop是ddl, 操作立即生效,原数据不放到rollbacksegment中,不能回滚. 操作不触发 trigger。
9、事务隔离级别有哪些?MySQL的默认隔离级别是?
SQL 标准定义了四个隔离级别:
READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
REPEATABLE-READ(可重复读-默认): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复 读,但幻读仍有可能发生。
SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干 扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。
10、CHAR 和 VARCHAR 的区别?
1、CHAR 和 VARCHAR 类型在存储和检索方面有所不同
2、CHAR 列长度固定为创建表时声明的长度,长度值范围是 1 到 255 当 CHAR值被存储时,它们被用空格填充到特定长度,检索 CHAR 值 时需删除尾随空格。
11、SQL优化有哪些?
1、查询语句中不要使用select * 2、尽量减少子查询,使用关联查询(left join,right 替代)
三、Redis
1、Redis 的数据类型?
Redis 支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及 zsetsorted set:有序集合)。
2、使用 Redis 有哪些好处?
(1)速度快,因为数据存在内存中,类似于 HashMap,HashMap 的优势就是查找和操作的时间复杂度都是 O1)。
(2)支持丰富数据类型,支持 string,list,set,Zset,hash 等。
(3)支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行。
(4)丰富的特性:可用于缓存,消息,按 key 设置过期时间,过期后将会自动删除。
3、Redis 是单进程单线程的?
Redis 是单进程单线程的,redis 利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销。
4、单线程的redis为什么这么快?
(一)纯内存操作 (二)单线程操作,避免了频繁的上下文切换 (三)采用了非阻塞I/O多路复用机制。(四)高效的数据结构Redis使用了精心设计的数据结构,如SDS(Simple Dynamic Strings)、跳表(Skip Lists)等,这些数据结构在内存中的操作效率很高。
5、Redis 的持久化机制是什么?各自的优缺点?
Redis 提供两种持久化机制 RDB 和 AOF 机制: 1、RDB(Redis DataBase)持久化方式: 是指用数据集快照的方式半持久化模式)记录 redis 数据库的所有键值对,在某个时间点将数据写入一 个临时文件,持久化结束后,用这个临时文件替换上次持久化的文件,达到数据恢复。 优点: 1、只有一个文件 dump.rdb,方便持久化。 2、容灾性好,一个文件可以保存到安全的磁盘。 3、性能最大化,fork 子进程来完成写操作,让主进程继续处理命令,所以是 IO最大化。使用单独子进程来进行持久化,主进程不会进行任 何 IO 操作,保证了 redis的高性能) 4.相对于数据集大时,比 AOF 的启动效率更高。 缺点: 1、数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化之间 redis 发生故障,会发生数据丢失。所以这种方式更适合数据要求不 严谨的时候) 2、AOF(Append-only file)持久化方式: 是指所有的命令行记录以 redis 命令请求协议的格式完全持久化存储)保存为 aof 文件。 优点: maxmemory-policy volatile-lru 1、数据安全,aof 持久化可以配置 appendfsync 属性,有 always,每进行一次命令操作就记录到 aof 文件中一次。 2、通过 append 模式写文件,即使中途服务器宕机,可以通过 redis-check-aof工具解决数据一致性问题。 3、AOF 机制的 rewrite 模式。AOF 文件没被 rewrite 之前(文件过大时会对命令进行合并重写),可以删除其中的某些命令(比如误操作 的 flushall)) 缺点: 1、AOF 文件比 RDB 文件大,且恢复速度慢。 2、数据集大的时候,比 rdb 启动效率低。
6、Redis的主从复制机制是怎样的?
答案:
Redis的主从复制机制允许将一个Redis服务器的数据复制到其他Redis服务器。具体过程如下:
主服务器:执行写操作,并将写命令记录到AOF或RDB文件中。
从服务器:与主服务器建立连接,接收并执行主服务器的写命令,从而复制数据。当主从连接断开后,从服务器可以独立提供读操作服务。
7、Redis的缓存穿透、缓存击穿和缓存雪崩是什么?如何解决?
答案:
缓存穿透:大量并发查询不存在的key,导致缓存和数据库都受到压力。解决方法包括缓存空值、使用布隆过滤器等。
缓存击穿:某个热点key失效时,大量并发请求直接访问数据库。解决方法包括设置热点数据永不过期、使用互斥锁等。
缓存雪崩:大量缓存同时失效,导致大量请求直接访问数据库。解决方法包括设置缓存过期时间随机、使用限流降级等。
8、Redis如何实现事务?
Redis的事务是通过MULTI、EXEC、DISCARD和WATCH这四个命令来实现的。
MULTI:标记一个事务块的开始。
EXEC:执行所有MULTI命令之后的所有操作,并且只在所有的命令都成功执行之后才执行。
DISCARD:取消事务,放弃执行事务块内的所有命令。
WATCH:是一个乐观锁,可以为Redis事务提供CAS(check-and-set)行为。如果事务执行之前,被WATCH的键被其他命令所改动,那么事务将被打断。
9、redis的集群模式:
模式类型 | 原理 | 特点 | 不足 |
主从复制模式 | 主从复制是Redis的一种基本集群模式,它通过将一个Redis节点(主节点)的数据复制到一个或多个其他Redis节点(从节点)来实现数据的冗余和备份。 主节点负责处理所有写操作和读操作,而从节点则复制主节点的数据,并且通常只能处理读操作。 | 实现了数据的多机备份,以及对读操作的负载均衡和简单的故障恢复。 当主节点出现故障时,可以将一个从节点升级为主节点,实现故障转移(但这一过程通常需要手动实现)。 | 故障恢复无法自动化。 写操作无法负载均衡。 存储能力受到单机的限制。 |
哨兵模式 | 哨兵模式是在主从复制的基础上加入了哨兵节点。哨兵节点是一种特殊的Redis节点,用于监控主节点和从节点的状态。 当主节点发生故障时,哨兵节点会自动从从节点中选举出一个新的主节点,并通知其他从节点和客户端,实现故障转移。 | 实现了自动化的故障恢复。 降低了运维的复杂度。 | 写操作仍然无法负载均衡。 存储能力仍然受到单机的限制。 哨兵无法对从节点进行自动故障转移;在读写分离场景下,从节点故障会导致读服务不可用。 |
Cluster模式 | Cluster模式是Redis的一种高级集群模式,它通过数据分片和分布式存储实现了负载均衡和高可用性。 在Cluster模式下,Redis将所有的键值对数据分散在多个节点上,每个节点负责一部分数据,称为槽位。 Redis Cluster将数据分为16384个槽位,每个节点负责管理一部分槽位。 | 实现了数据的自动分片,突破了单节点内存限制,支持更大规模的数据存储。 提供了自动的故障检测和故障转移功能,保证了服务的高可用性。 支持横向扩展,可以根据业务需求动态地添加或移除节点。 |
四、Spring
1、什么是 Spring IOC 容器?
Spring 框架的核心是 Spring 容器。容器创建对象,将它们装配在一起,配置它们并管理它们的完整生命周期。Spring 容器使用依赖注入来 管理组成应用程序的组件。容器通过读取提供的配置元数据来接收对象进行实例化,配置和组装的指令。该元数据可以通过 XML,Java 注 解或 Java 代码提供。
2、什么是依赖注入?
在依赖注入中,您不必创建对象,但必须描述如何创建它们。您不是直接在代码中将组件和服务连接在一起,而是描述配置文件中哪些组件 需要哪些服务。由 IoC容器将它们装配在一起。
3、什么是 spring bean?
它们是构成用户应用程序主干的对象
Bean 由 Spring IoC 容器管理
它们由 Spring IoC 容器实例化,配置,装配和管理。
Bean 是基于用户提供给容器的配置元数据创建。
4、spring 提供了哪些配置方式?
(1)基于 xml 配置
(2)基于注解配置
(3)基于 Java API 配置
5、常见的注解有哪些?
@Component :这将 java 类标记为 bean。它是任何 Spring 管理组件的通用构造型。spring 的组件扫描机制现在可以将其拾取并将其拉 入应用程序环境中。
@Controller :这将一个类标记为 Spring Web MVC 控制器。标有它的Bean 会自动导入到 IoC 容器中。
@Service :此注解是组件注解的特化。它不会对 @Component 注解提供任何其他行为。您可以在服务层类中使用,@Service 而不是 @Component,因为它以更好的方式指定了意图。
@Repository :这个注解是具有类似用途和功能的 @Component 注解的特化。它为 DAO 提供了额外的好处。它将 DAO 导入 IoC 容器, 并使未经检查的异常有资格转换为 Spring DataAccessException。
@Required:@Required 应用于 bean 属性 setter 方法。
@Autowired:@Autowired 可以更准确地控制应该在何处以及如何进行自动装配。
@Qualifier: 创建多个相同类型的 bean 并希望仅使用属性装配其中一个 bean 时,您可以使用@Qualifier 注解和 @Autowired 通过指定应该装配哪 个确切的 bean 来消除歧义。
@RequestMapping 注解用于将特定 HTTP 请求方法映射到将处理相应请求的 控制器中的特定类/方法。此注释可应用于两个级别: 类级别:映射请求的 URL 方法级别:映射 URL 以及 HTTP 请求方法。
6、Spring的AOP理解 ?
OOP面向对象,允许开发者定义纵向的关系,但并适用于定义横向的关系,导致了大量代码的重复,而不利于各个模块的重用。 AOP,一般称为面向切面,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为 一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。 可用于权限认证、日志、事务处理。 AOP实现的关键在于 代理模式,AOP代理主要分为静态代理和动态代理。静态代理的代表为AspectJ;动态代理则以Spring AOP为代表。 (1)AspectJ是静态代理的增强,所谓静态代理,就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强,他会在编译阶段将 AspectJ(切面)织入到Java字节码中,运行的时候就是增强之后的AOP对象。 (2)Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP 对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。 Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理 : ①JDK动态代理只提供接口的代理,不支持类的代理。核心InvocationHandler接口和Proxy类,InvocationHandler 通过invoke()方法反射 来调用目标类中的代码,动态地将横切逻辑和业务编织在一起;接着,Proxy利用 InvocationHandler动态创建一个符合某一接口的的实例, 生成目标类的代理对象。 ②如果代理类没有实现 InvocationHandler 接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现 AOP。CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的 3)静态代理与动态代理区别在于生成AOP代理对象的时机不同,相对来说AspectJ的静态代理方式具 有更好的性能,但是AspectJ需要特定的编译器进行处理,而Spring AOP则无需特定的编译器处理。
7、Spring的IOC理解
(1)IOC就是控制反转,是指创建对象的控制权的转移,以前创建对象的主动权和时机是由自己把控的,而现在这种权力转移到Spring容器 中,并由容器根据配置文件去创建实例和管理各个实例之间的依赖关系,对象与对象之间松散耦合,也利于功能的复用。DI依赖注入,和控 制反转是同一个概念的不同角度的描述,即 应用程序在运行时依赖IoC容器来动态注入对象需要的外部资源。
(2)最直观的表达就是,IOC让对象的创建不用去new了,可以由spring自动生产,使用java的反射机制,根据配置文件在运行时动态的去 创建对象以及管理对象,并调用对象的方法的。
(3)Spring的IOC有三种注入方式 :构造器注入、setter方法注入、根据注解注入。
8、什么是 Spring 的 MVC 框架?
Spring 配备构建 Web 应用的全功能 MVC 框架。Spring 可以很便捷地和其他MVC 框架集成,如 Struts,Spring 的 MVC 框架用控制反转把 业务对象和控制逻辑清晰地隔离。它也允许以声明的方式把请求参数和业务对象绑定。
9、解释 AOP?
面向切面的编程,或 AOP, 是一种编程技术,允许程序模块化横向切割关注点,或横切典型的责任划分,如日志和事务管理。
10、Aspect 切面?
AOP 核心就是切面,它将多个类的通用行为封装成可重用的模块,该模块含有一组 API 提供横切功能。比如,一个日志模块可以被称作日 志的 AOP 切面。根据需求的不同,一个应用程序可以有若干切面。在 Spring AOP 中,切面通过带有@Aspect 注解的类实现。
五、Spring Boot
1、Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?
启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了以下 3 个注解: @SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。 @EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })。 @ComponentScan:Spring组件扫描
2、Spring Boot 的核心配置文件有哪几个?它们的区别是什么?
Spring Boot 的核心配置文件是 application 和 bootstrap 配置文件。 application 配置文件这个容易理解,主要用于 Spring Boot 项目的自动化配置。 bootstrap 配置文件有以下几个应用场景。 1. 使用 Spring Cloud Config 配置中心时,这时需要在 bootstrap 配置文件中添加连接到配置中心的配置属性来加载外部配置中心的配置 信息; 2. 一些固定的不能被覆盖的属性; 3. 一些加密/解密的场景
3、 Spring Boot的自动配置原理是什么?
答案:
Spring Boot的自动配置原理主要依赖于@EnableAutoConfiguration注解和spring-boot-autoconfigure模块中的自动配置类。
在Spring Boot启动时,@EnableAutoConfiguration注解会触发自动配置过程。Spring Boot会检查classpath下是否存在特定的类(通过@Conditional注解的条件判断),如果存在,则会自动配置相应的组件并注册到Spring容器中。
自动配置类通常通过@Configuration注解定义,并使用@Bean注解来声明需要创建的bean。同时,它们还会通过@Conditional注解来指定自动配置的条件。
4、Spring Boot 支持哪些日志框架?推荐和默认的日志框架是哪个?
Spring Boot 支持 Java Util Logging, Log4j2, Lockback 作为日志框架,如果你使用 Starters 启动器,Spring Boot 将使用 Logback 作为默 认日志框架。
5、springboot集成mybatis的过程?
添加mybatis的starter maven依赖 org.mybatis.spring.boot mybatis-spring-boot-starter 1.2.0 在mybatis的接口中 添加@Mapper注解 在application.yml配置数据源信息。
6、SpringBoot和SpringCloud的区别?
SpringBoot专注于快速方便的开发单个个体微服务。 SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并 管理起来,为各个微服务之间提供,配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞 选、分布式会话等等集成服务SpringBoot可以离开SpringCloud独立使用开发项目, 但是SpringCloud离不开SpringBoot ,属于依赖的关系. SpringBoot专注于快速、方便的开发单个微服务个体,SpringCloud关注全局的服务治理框架。
7、微服务之间是如何独立通讯的?
1.远程调用,比如feign调用,直接通过远程过程调用来访问别的service。 2.消息中间件
8、作为服务注册中心,Eureka比Zookeeper好在哪里?
1.Eureka保证的是可用性和分区容错性,Zookeeper 保证的是一致性和分区容错性 。 2.Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故 障。而不会像zookeeper那样使整个注册服务瘫痪。
9、eureka自我保护机制是什么?
1.当Eureka Server 节点在短时间内丢失了过多实例的连接时(比如网络故障或频繁启动关闭客户端)节点会进入自我保护模式,保护注册 信息,不再删除注册数据,故障恢复时,自动退出自我保护模式。
10、什么是feigin?它的优点是什么?
1.feign采用的是基于接口的注解 2.feign整合了ribbon,具有负载均衡的能力 3.整合了Hystrix,具有熔断的能力。
使用: 1.添加pom依赖。 2.启动类添加@EnableFeignClients 3.定义一个接口@FeignClient(name=“xxx”)指定调用哪个服务。
六、常用注解
注解名称 | 作用 | 详细描述 |
@Service | 表示这是一个业务层bean,通常用于标注服务层组件。 | |
@Repository | 表示这是一个数据访问层bean,通常用于标注数据访问对象(DAO),用于对数据库的操作。 | 通常在标记在dao上 |
@Component | 表示通用bean,当组件不好归类时,可以使用这个注解。它是一个更通用的注解,可以标注任何Spring管理的组件。 | |
@Controller | 用于标记Web层组件,是@Component注解的特化 | |
@RestController | 与@Controller类似,但是@RestController会自动将返回值转换为JSON格式(或其他配置的格式)。它是@Controller和@ResponseBody的组合注解,用于标注一个类,表示这个类是一个RESTful风格的控制器。 | 它用于处理HTTP请求并返回JSON/XML格式的响应,默认情况下会将控制器方法的返回值转换为JSON格式,并以HTTP响应的方式返回给客户端。 |
@RequestMapping | 用于映射请求URL和处理方法。它是Spring MVC框架中的一个核心注解,用于映射HTTP请求和控制器方法之间的关系。 | 它可以用于类级别和方法级别,用于指定请求URL和HTTP方法(GET、POST、PUT、DELETE等)。@RequestMapping可以与其他HTTP方法映射注解(如@GetMapping、@PostMapping等)一起使用,提供更具体的请求映射 |
@RequestParam | 用于获取请求参数的值。 | 它可以将请求参数绑定到控制器方法的参数上,方便在方法内部使用这些参数。 |
@PathVariable | 用于获取URL中的参数值。 | 它可以将HTTP请求路径中的变量绑定到控制器方法的参数上,常用于RESTful风格的URL设计。 |
@Configuration | 用于标注一个类作为配置类,相当于Spring的配置文件(XML方式)的Java配置方式。 | 它与@Bean注解配合使用,用于定义Spring容器中的Bean。 |
@Bean | 用于声明当前方法返回一个Bean,并将该Bean注册到Spring容器中。 | 它通常与@Configuration注解一起使用,在配置类中定义Bean。 |
@Autowired | 用于自动装配Spring容器中的Bean。 | 它可以按类型注入Bean,默认属性required=true。当不能确定Spring容器中一定拥有某个类的Bean时,可以使用@Autowired(required=false)。 |
@SpringBootApplication | 这是一个组合注解,包括了@Configuration、@EnableAutoConfiguration和@ComponentScan三个注解。它用于标识Spring Boot应用程序的入口类,能够简化Spring应用程序的配置和启动过程。 | @Configuration:指示这个类是一个配置类,它定义了一个或多个@Bean方法,用于创建和配置Spring应用程序上下文中的Bean。 @EnableAutoConfiguration:启用Spring Boot的自动配置机制,它会自动添加所需的依赖项和配置,以使应用程序能够运行。 @ComponentScan:指示Spring Boot扫描当前包及其子包中的所有@Component、@Service、@Repository和@Controller注解的类,并将它们注册为Spring Bean。 |
@ComponentScan | 指定要扫描的包,以便发现和注册Spring组件。 | 默认情况下,@ComponentScan会扫描主应用类所在的包及其子包。但你可以通过basePackages属性指定要扫描的包。 |
@ResponseBody | 表示该方法的返回结果直接写入HTTP response body中,而不是解析为跳转路径或视图名称。 | 它通常与@RequestMapping注解一起使用,在RESTful服务中非常常见,用于构建直接返回数据的API。 |
@Value | 用于注入配置文件的属性值。 | 它可以将配置文件(如application.properties或application.yml)中的属性值注入到Bean的字段中。 |
@Async | 用于声明异步方法。 | 它可以使被注解的方法异步执行,即调用者不会等待方法的执行完成。这对于提高应用的响应性和处理性能非常有帮助。 |
@Scheduled | 用于在特定时间间隔或指定时间点执行定时任务。 |
七、MyBatis
1、#{}和${}的区别是什么?
#{}是预编译处理,${}是字符串替换。 Mybatis 在处理#{}时,会将 sql 中的#{}替换为?号,调用 PreparedStatement 的set 方法来赋值; Mybatis 在处理${}时,就是把${}替换成变量的值。 使用#{}可以有效的防止 SQL 注入,提高系统安全性.
2、在 mapper 中如何传递多个参数?
1、第一种: DAO 层的函数.
2、第二种: 使用 @param 注解
3、第三种:多个参数封装成 map
3、Mybatis 动态 sql 有什么用?执行原理?有哪些动态 sql?
Mybatis 动态 sql 可以在Xml 映射文件内,以标签的形式编写动态 sql,执行原理是根据表 达式 的值 完成 逻辑 判断 并动 态拼 接 sql 的功 能。 Mybatis提供了9种动态 sql 标签 :trim | where | set | foreach | if | choose| when | otherwise | bind
4、Mybatis 的 Xml 映射文件中,不同的 Xml 映射文件,id 是否可以重复?
不同的 Xml 映射文件,如果配置了namespace,那么 id 可以重复;如果没有配置 namespace,那么 id 不能重复;
5、MyBatis 实现一对一有几种方式?具体怎么操作的?
有联合查询和嵌套查询,联合查询是几个表联合查询,只查询一次, 通过在resultMap 里面配置 association 节点配置一对一的类就可以完成; 嵌套查询是先查一个表,根据这个表里面的结果的 外键 id,去再另外一个表里面查询数据,也是通过 association 配置,但另外一个表的查询通过 select 属性配置。
6、MyBatis 实现一对多有几种方式,怎么操作的?
有联合查询和嵌套查询。联合查询是几个表联合查询,只查询一次,通过在resultMap 里面的 collection 节点配置一对多的类就可以完成;嵌套查询是先查一个表,根据这个表里面的 结果的外键 id,去再另外一个表里面查询数据,也是通过配置 collection,但另外一个表的查询通过 select 节点配置。
7、用 MyBatis 的 mapper 接口调用时有哪些要求?
1.Mapper 接口方法名和 mapper.xml 中定义的每个 sql 的 id 相同;
2.Mapper 接口方法的输入参数类型和 mapper.xml 中定义的每个 sql 的parameterType 的类型相同;
3.Mapper 接口方法的输出参数类型和 mapper.xml 中定义的每个 sql 的resultType 的类型相同;
4.Mapper.xml 文件中的 namespace 即是 mapper 接口的类路径。
8、当实体类中的属性名和表中的字段名不一样 ,怎么办?
第 1 种: 通过在查询的 sql 语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。
第 2 种: 通过来映射字段名和实体类属性名的一一对应的关系。
9、MyBatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?
答案:
不同的Xml映射文件,如果配置了namespace,那么id可以重复;如果没有配置namespace,那么id不能重复。因为MyBatis在解析XML映射文件时,会将namespace和id组合起来作为唯一标识。
10、MyBatis是如何进行分页的?分页插件的原理是什么?
答案:
分页方式:
(1)使用RowBounds对象进行分页:这是MyBatis内置的分页方式,但它是针对ResultSet结果集执行的内存分页,而非物理分页。
(2)编写物理分页的SQL:可以在sql内直接书写带有物理分页的参数来完成物理分页功能。
(3)使用分页插件:分页插件的基本原理是实现MyBatis提供的插件接口,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据数据库方言添加对应的分页语句。
分页插件原理:
分页插件通过实现MyBatis的Interceptor接口,并在其intercept方法中拦截待执行的SQL语句,然后根据配置的数据库方言重写SQL语句,以实现物理分页。
11、MyBatis的Mapper接口是如何工作的?
答案:
MyBatis的Mapper接口是MyBatis的一个核心特性,它允许开发者以面向接口编程的方式操作数据库。Mapper接口的工作原理如下:
接口定义:首先,定义一个Mapper接口,其中包含了与数据库表操作相关的CRUD方法。
XML映射文件:然后,创建一个与Mapper接口同名的XML映射文件,该文件位于类路径下的某个目录(通常是resources/mappers),并遵循MyBatis的命名空间和SQL映射规则。
方法绑定:在XML映射文件中,使用<select>、<insert>、<update>、<delete>等标签定义SQL语句,并通过id属性将这些SQL语句与Mapper接口中的方法绑定。
动态代理:当MyBatis配置完成后,MyBatis会利用Java的动态代理机制为Mapper接口生成一个代理对象。这个代理对象在调用方法时,会根据方法的名称和参数找到对应的SQL语句,并执行它。
结果映射:MyBatis还会负责将SQL执行的结果映射回Java对象。这可以通过在XML映射文件中定义<resultMap>来实现,也可以通过MyBatis的自动映射功能来简化。
八、RabbitMQ
1、什么是 rabbitmq?
采用 AMQP 高级消息队列协议的一种消息队列技术,最大的特点就是消费并不需要确保提供方存在,实现了服务之间的高度解耦。
2、使用 rabbitmq 的场景?
1.服务间异步通信
2.顺序消费
3.定时任务
4.请求削峰
3、使用 RabbitMQ 有什么好处?
1.服务间高度解耦
2.异步通信性能高
3.流量削峰
4、如何避免消息重复投递或重复消费?
在消息生产时,MQ 内部针对每条生产者发送的消息生成一个 inner-msg-id,作为去重的依据(消息投递失败并重传),避免重复的消息进 入队列; 在消息消费时,要求消息体中必须要有一个 bizId(对于同一业务全局唯一,如支付 ID、订单 ID、帖子 ID 等)作为去重的依据,避免同一 条消息被重复消费。
5、消息如何分发?
若该队列至少有一个消费者订阅,消息将以循环(round-robin)的方式发送给消费者。每条消息只会分发给一个订阅的消费者(前提是消 费者能够正常处理消息并进行确认)。 通过路由可实现多消费的功能。
6、消息基于什么传输?
由于 TCP 连接的创建和销毁开销较大,且并发数受系统资源限制,会造成性能瓶颈。RabbitMQ 使用信道的方式来传输数据。信道是建立在真实的 TCP 连接内的虚拟连接,且每条 TCP 连接上的信道数量没有限制。
7、消息怎么路由?
消息提供方->路由->一至多个队列 消息发布到交换器时,消息将拥有一个路由键(routing key),在消息创建时设定。 通过队列路由键,可以把队列绑定到交换器上。 消息到达交换器后,RabbitMQ 会将消息的路由键与队列的路由键进行匹配(针对不同的交换器有不同的路由规则); 常用的交换器主要分为一下三种 fanout:如果交换器收到消息,将会广播到所有绑定的队列上 direct:如果路由键完全匹配,消息就被投递到相应的队列 topic:可以使来自不同源头的消息能够到达同一个队列。 使用 topic 交换器时,可以使用通配符。
8、如何确保消息不丢失?
消息持久化,当然前提是队列必须持久化 RabbitMQ 确保持久性消息能从服务器重启中恢复的方式是,将它们写入磁盘上的一个持久化日志文件,当发布一条持久性消息到持久交换 器上时,Rabbit 会在消息提交到日志文件后才发送响应。 一旦消费者从持久队列中消费了一条持久化消息,RabbitMQ 会在持久化日志中把这条消息标记为等待垃圾收集。如果持久化消息在被消费 之前 RabbitMQ 重启,那么 Rabbit 会自动重建交换器和队列(以及绑定),并重新发布持久化日志文件中的消息到合适的队列。
9、如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万 消息持续积压几小时,说说怎么解决 ?
消息积压处理办法:临时紧急扩容: 先修复 consumer 的问题,确保其恢复消费速度,然后将现有 cnosumer 都停掉。新建一个 topic,partition 是原来的 10 倍,临时建立好 原先 10 倍的 queue 数量。然后写一个临时的分发数据的 consumer 程序,这个程序部署上去消费积压的数据,消费之后不做耗时的处 理,直接均匀轮询写入临时建立好的 10 倍数量的 queue。
九、Linux
1、列举几个常用的Linux命令
列出文件列表:ls【参数 -a -l】
创建目录和移除目录:mkdir rmdir
用于显示文件后几行内容:tail,例如: tail -n 1000:显示最后1000行
打包:tar -xvf
打包并压缩:tar -zcvf
查找字符串:grep
显示当前所在目录:pwd
创建空文件:touch
编辑器:vim vi
2、查看文件有哪些命令
vi 文件名 #编辑方式查看,可修改
cat 文件名 #显示全部文件内容
more 文件名 #分页显示文件内容
less 文件名 #与 more 相似,更好的是可以往前翻页
tail 文件名 #仅查看尾部,还可以指定行数
head 文件名 #仅查看头部,还可以指定行数
创建目录: mkdir
创建文件:典型的如 touch,vi 也可以创建文件,其实只要向一个不存在的文件
文件权限修改: chmod命令允许你改变文件或目录的权限。权限分为三种:读(r)、写(w)和执行(x),分别对应数字4、2和1。