面试题整理(四)

本文涉及的产品
对象存储 OSS,20GB 3个月
传统型负载均衡 CLB,每月750个小时 15LCU
日志服务 SLS,月写入数据量 50GB 1个月
简介: 面试题整理(四)

七、SSM面试题

Spring

1、什么是Spring:

Spring 是个java企业级应用的开源开发框架。Spring主要用来开发Java应用,但是有些扩展是针对构建J2EE平台的web应用。Spring 框架目标是简化Java企业级应用开发,并通过POJO为基础的编程模型促进良好的编程习惯。


2、你们项目中为什么使用Spring框架?

轻量:Spring 是轻量的,基本的版本大约2MB。

控制反转:Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对象们。

面向切面的编程(AOP):Spring支持面向切面的编程,并且把应用业务逻辑和系统服务分开。

容器:Spring 包含并管理应用中对象的生命周期和配置。

MVC框架:Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的替代品。

事务管理:Spring 提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务

异常处理:Spring 提供方便的API把具体技术相关的异常(比如由JDBC,Hibernate or JDO抛出的)转化为一致的unchecked 异常。

3、Autowired和Resource关键字的区别?

Resource和@Autowired都是做bean的注入时使用,其实@Resource并不是Spring的注解,它的包是javax.annotation.Resource,需要导入,但是Spring支持该注解的注入。


共同点两者都可以写在字段和setter方法上。两者如果都写在字段上,那么就不需要再写setter方法。

不同点(1)@Autowired为Spring提供的注解,需要导入包org.springframework.beans.factory.annotation.Autowired;只按照byType注入。

@Autowired注解是按照类型(byType)装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它的required属性为false。如果我们想使用按照名称(byName)来装配,可以结合@Qualifier注解一起使用。

(2)@Resource默认按照ByName自动注入,由J2EE提供,需要导入包javax.annotation.Resource。@Resource有两个重要的属性:name和type,而Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以,如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不制定name也不制定type属性,这时将通过反射机制使用byName自动注入策略。

4、依赖注入的方式有几种,各是什么?

构造器注入 将被依赖对象通过构造函数的参数注入给依赖对象,并且在初始化对象的时候注入。优点: 对象初始化完成后便可获得可使用的对象。缺点: 当需要注入的对象很多时,构造器参数列表将会很长; 不够灵活。若有多种注入方式,每种方式只需注入指定几个依赖,那么就需要提供多个重载的构造函数,麻烦。

setter方法注入 IoC Service Provider通过调用成员变量提供的setter函数将被依赖对象注入给依赖类。优点: 灵活。可以选择性地注入需要的对象。缺点: 依赖对象初始化完成后由于尚未注入被依赖对象,因此还不能使用。

通过接口

5、说说你对Spring的IOC是怎么理解的?

IOC就是控制反转,是指创建对象的控制权的转移。以前创建对象的主动权和时机是由自己把控的,而现在这种权力转移到Spring容器中,并由容器根据配置文件去创建实例和管理各个实例之间的依赖关系。对象与对象之间松散耦合,也利于功能的复用。DI依赖注入,和控制反转是同一个概念的不同角度的描述,即 应用程序在运行时依赖IoC容器来动态注入对象需要的外部资源。

最直观的表达就是,IOC让对象的创建不用去new了,可以由spring自动生产,使用java的反射机制,根据配置文件在运行时动态的去创建对象以及管理对象,并调用对象的方法的。

Spring的IOC有三种注入方式 :构造器注入、setter方法注入、根据注解注入。IoC让相互协作的组件保持松散的耦合,而AOP编程允许你把遍布于应用各层的功能分离出来形成可重用的功能组件。

6、谈谈你对Spring的AOP理解

AOP(Aspect-Oriented Programming,面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可扩展性和可维护性。

Spring AOP是基于动态代理的,如果要代理的对象实现了某个接口,那么Spring AOP就会使用JDK动态代理去创建代理对象;而对于没有实现接口的对象,就无法使用JDK动态代理,转而使用CGlib动态代理生成一个被代理对象的子类来作为代理。

当然也可以使用AspectJ,Spring AOP中已经集成了AspectJ,AspectJ应该算得上是Java生态系统中最完整的AOP框架了。使用AOP之后我们可以把一些通用功能抽象出来,在需要用到的地方直接使用即可,这样可以大大简化代码量。我们需要增加新功能也方便,提高了系统的扩展性。日志功能、事务管理和权限管理等场景都用到了AOP。

7、Spring AOP和AspectJ AOP有什么区别?

Spring AOP是属于运行时增强,而AspectJ是编译时增强。

Spring AOP基于代理(Proxying),而AspectJ基于字节码操作(Bytecode Manipulation)。

Spring AOP已经集成了AspectJ,AspectJ应该算得上是Java生态系统中最完整的AOP框架了。

AspectJ相比于Spring AOP功能更加强大,但是Spring AOP相对来说更简单。如果我们的切面比较少,那么两者性能差异不大。

但是,当切面太多的话,最好选择AspectJ,它比SpringAOP快很多。

8、在Spring AOP 中,关注点和横切关注的区别是什么?

关注点是应用中一个模块的行为,一个关注点可能会被定义成一个我们想实现的一个功能。 横切关注点是一个关注点,此关注点是整个应用都会使用的功能,并影响整个应用,比如日志,安全和数据传输,几乎应用的每个模块都需要的功能。因此这些都属于横切关注点。那什么是连接点呢?连接点代表一个应用程序的某个位置,在这个位置我们可以插入一个AOP切面,它实际上是个应用程序执行Spring AOP的位置。

切入点是什么?切入点是一个或一组连接点,通知将在这些位置执行。可以通过表达式或匹配的方式指明切入点。

9、什么是通知呢?有哪些类型呢?

通知是个在方法执行前或执行后要做的动作,实际上是程序执行时要通过SpringAOP框架触发的代码段。


Spring切面可以应用五种类型的通知:


before:前置通知,在一个方法执行前被调用。

after: 在方法执行之后调用的通知,无论方法执行是否成功。

after-returning: 仅当方法成功完成后执行的通知。

after-throwing: 在方法抛出异常退出时执行的通知。

around: 在方法执行之前和之后调用的通知。

10、解释一下spring bean的生命周期

Bean 容器找到配置文件中 Spring Bean 的定义。

Bean 容器利用 Java Reflection API 创建一个 Bean 的实例。

如果涉及到一些属性值 利用 set()方法设置一些属性值。

如果 Bean 实现了 BeanNameAware 接口,调用 setBeanName()方法,传入 Bean 的名字。

如果 Bean 实现了 BeanClassLoaderAware 接口,调用 setBeanClassLoader()方法,传入 ClassLoader对象的实例。

如果 Bean 实现了 BeanFactoryAware 接口,调用 setBeanFactory()方法,传入 BeanFactory对象的实例。

如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessBeforeInitialization() 方法

如果 Bean 实现了InitializingBean接口,执行afterPropertiesSet()方法。

如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。

当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接口,执行 destroy() 方法。

当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。

11、解释Spring支持的几种bean的作用域?

singleton:默认,每个容器中只有一个bean的实例,单例的模式由BeanFactory自身来维护。

prototype:每次获取都会创建一个新的 bean 实例。也就是说,连续 getBean() 两次,得到的是不同的 Bean 实例。

request:每一次 HTTP 请求都会产生一个新的 bean(请求 bean),该 bean 仅在当前 HTTP request 内有效。

session: 每一次来自新 session 的 HTTP 请求都会产生一个新的 bean(会话 bean),该 bean 仅在当前 HTTP session 内有效。

global-session:每个 Web 应用在启动时创建一个 Bean(应用 Bean),该 bean 仅在当前应用启动时间内有效。

12、静态代理和动态代理的区别

静态代理:只能代理一种业务,如果有多种业务需要编写多个代理类


动态代理:通过反射机制动态生成代理类,不需要手动编写,能够代理多种业务,更加灵活。


13、JDK动态代理和CGLIB动态代理的区别

Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理:


JDK动态代理只提供接口的代理,不支持类的代理。核心InvocationHandler接口和Proxy类,InvocationHandler 通过invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起;接着,Proxy利用 InvocationHandler动态创建一个符合某一接口的的实例, 生成目标类的代理对象。

如果代理类没有实现 InvocationHandler 接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。

静态代理与动态代理区别在于生成AOP代理对象的时机不同,相对来说AspectJ的静态代理方式具有更好的性能,但是AspectJ需要特定的编译器进行处理,而Spring AOP则无需特定的编译器处理。


14、Spring框架中都用到了哪些设计模式?

工厂设计模式 : Spring 使用工厂模式通过 BeanFactory、ApplicationContext 创建 bean 对象。

代理设计模式 : Spring AOP 功能的实现。

单例设计模式 : Spring 中的 Bean 默认都是单例的。

模板方法模式 : Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。

包装器设计模式 : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。

观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。

适配器模式 : Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配

15、说说Spring 中 ApplicationContext 和 BeanFactory 的区别

16、Spring 框架中的单例 Bean 是线程安全的么?

Spring 框架并没有对单例 Bean 进行任何多线程的封装处理。


关于单例 Bean 的线程安全和并发问题,需要开发者自行去搞定。

单例的线程安全问题,并不是 Spring 应该去关心的。Spring 应该做的是,提供根据配置,创建单例 Bean 或多例 Bean 的功能。

但实际上,大部分的 Spring Bean 并没有可变的状态,所以在某种程度上说 Spring 的单例Bean 是线程安全的。如果你的 Bean 有多种状态的话,就需要自行保证线程安全。最浅显的解决办法,就是将多态 Bean 的作用域(Scope)由 Singleton 变更为 Prototype。


17、Spring 是怎么解决循环依赖的?

循环依赖是指一个或多个Bean实例之间存在直接或间接的依赖关系,构成循环调用。通常表现为三种形态。互相依赖,也就是A依赖B,B依赖A


Spring设计了三级缓存来解决循环依赖问题。


第一级缓存里面存储完整的Bean实例,这些实例是可以直接被使用的。

第二级缓存里面存储的是实例化以后,但是还没有设置属性值的Bean实例,也就是Bean里面的依赖注入还没有做。

第三级缓存用来存放Bean工厂,它主要用来生成原始Bean对象并且放到第二级缓存里面。三级缓存的核心思想,就是把Bean的实例化,和Bean里面的依赖注入进行分离。

采用一级缓存存储完整的Bean实例,采用二级缓存来存储不完整的Bean实例,通过不完整的Bean实例作为突破口,解决循环依赖的问题。至于第三级缓存,主要是解决代理对象的循环依赖问题

18、Spring 管理事务的方式有几种?

编程式事务 :在代码中硬编码(不推荐使用) : 通过 TransactionTemplate或者 TransactionManager 手动管理事务,实际应用中很少使用,但是对于你理解 Spring 事务管理原理有帮助。

声明式事务 :在 XML 配置文件中配置或者直接基于注解(推荐使用) : 实际是通过 AOP 实现(基于@Transactional 的全注解方式使用最多)

19、Spring 事务中的隔离级别有哪几种?

TransactionDefinition.ISOLATION_DEFAULT :使用后端数据库默认的隔离级别,MySQL 默认采用的 REPEATABLE_READ 隔离级别 Oracle 默认采用的 READ_COMMITTED 隔离级别.

TransactionDefinition.ISOLATION_READ_UNCOMMITTED :最低的隔离级别,使用这个隔离级别很少,因为它允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读

TransactionDefinition.ISOLATION_READ_COMMITTED : 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生

TransactionDefinition.ISOLATION_REPEATABLE_READ : 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。

TransactionDefinition.ISOLATION_SERIALIZABLE : 最高的隔离级别,完全服从 ACID 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别

SpringMVC

1、SpringMVC的执行流程

6d1029d241fbf4cfb00d9619316e722b.png


用户发送请求给前端控制器

前端控制器将请求的URL发送给处理器映射

处理器映射将请求里面的handler(包装的信息和方法)返回给前端控制器

前端控制器发送handler给适配器,适配器执行handler里的方法

适配器执行完毕后返回逻辑视图给前端控制器

前端控制器再将逻辑视图发送给视图解析器,解析成物理视图返回给前端控制器

前端控制器渲染视图,发送视图给用户

2、SpringMVC中的拦截器和Servlet中的Filter过滤器的区别?

拦截器:用于过滤请求,只能在SpringMVC中使用,效率高


过滤器:拦截范围更大


3、什么是Spring MVC?简单介绍下你对Spring MVC的理解?

首先,SpringMVC是是属于SpringFramework生态里面的一个模块,它是在Servlet基础上构建并且使用MVC模式设计的一个Web框架,主要的目的是简化传统Servlet+JSP模式下的Web开发方式。其次,SpringMVC的整体架构设计对JavaWeb里面的MVC架构模式做了增强和扩展,主要有几个方面。把传统MVC框架里面的Controller控制器做了拆分,分成了前端控制器DispatcherServlet和后端控制器Controller。把Model模型拆分成业务层Service和数据访问层Repository。在视图层,可以支持不同的视图,比如Freemark、velocity、JSP等等。所以,SpringMVC天生就是为了MVC模式而设计的,因此在开发MVC应用的时候会更加方便和灵活。SpringMVC的具体工作流程是,浏览器的请求首先会经过SpringMVC里面的核心控制器DispatcherServlet,它负责对请求进行分发到对应的Controller。Controller里面处理完业务逻辑之后,返回ModeAndView。然后DispatcherServlet寻找一个或者多个ViewResolver视图解析器,找到ModeAndView指定的视图,并把数据显示到客户端。


4、Spring MVC的控制器是不是单例模式,如果是,有什么问题,怎么解决?

答:是单例模式,所以在多线程访问的时候有线程安全问题,不要用同步,会影响性能的,解决方案是在控制器里面不能写字段。


5、MVC是什么?MVC设计模式的好处有哪些

mvc是一种设计模式(设计模式就是日常开发中编写代码的一种好的方法和经验的总结)。模型(model)-视图(view)-控制器(controller),三层架构的设计模式。用于实现前端页面的展现与后端业务数据处理的分离。


mvc设计模式的好处


分层设计,实现了业务系统各个组件之间的解耦,有利于业务系统的可扩展性,可维护性。

有利于系统的并行开发,提升开发效率。

6、Spring MVC常用的注解有哪些?

e4f061ca9308ae616fdfbd29fba158fe.png


7、Spring MVC怎么样设定重定向和转发的?

转发:在返回值前面加"forward:“,譬如"forward:user.do?name=method4”

重定向:在返回值前面加"redirect:“,如"redirect:http://www.baidu.com”

MyBatis

1、介绍一下MyBatis:

MyBatis 是一款优秀的持久层框架,一个半 ORM(对象关系映射)框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。


2、ORM是什么

ORM(Object Relational Mapping),对象关系映射,是一种为了解决关系型数据库数据与简单Java对象(POJO)的映射关系的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系型数据库中。


3、为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?

Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。


而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具。


4、传统JDBC开发存在的问题

频繁创建数据库连接对象、释放,容易造成系统资源浪费,影响系统性能。可以使用连接池解决这个问题。但是使用jdbc需要自己实现连接池。

sql语句定义、参数设置、结果集处理存在硬编码。实际项目中sql语句变化的可能性较大,一旦发生变化,需要修改java代码,系统需要重新编译,重新发布。不好维护。

使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护。

结果集处理存在重复代码,处理麻烦。如果可以映射成Java对象会比较方便

5、JDBC编程有哪些不足之处,MyBatis是如何解决这些问题的?

94b9438b7fda76cdda594af1b0df2d1f.png


6、Mybatis优缺点

image-20230212221513223.png

7、Hibernate 和 MyBatis 的区别

相同点


都是对jdbc的封装,都是持久层的框架,都用于dao层的开发。


不同点


映射关系


MyBatis 是一个半自动映射的框架,配置Java对象与sql语句执行结果的对应关系,多表关联关系配置简单

Hibernate 是一个全表映射的框架,配置Java对象与数据库表的对应关系,多表关联关系配置复杂

SQL优化和移植性


Hibernate 对SQL语句封装,提供了日志、缓存、级联(级联比 MyBatis 强大)等特性,此外还提供 HQL(Hibernate Query Language)操作数据库,数据库无关性支持好,但会多消耗性能。如果项目需要支持多种数据库,代码开发量少,但SQL语句优化困难。

MyBatis 需要手动编写 SQL,支持动态 SQL、处理列表、动态生成表名、支持存储过程。开发工作量相对大些。直接使用SQL语句操作数据库,不支持数据库无关性,但sql语句优化容易。

开发难易程度和学习成本


Hibernate 是重量级框架,学习使用门槛高,适合于需求相对稳定,中小型的项目,比如:办公自动化系统

MyBatis 是轻量级框架,学习使用门槛低,适合于需求变化频繁,大型的项目,比如:互联网电子商务系统

总结


MyBatis 是一个小巧、方便、高效、简单、直接、半自动化的持久层框架,

Hibernate 是一个强大、方便、高效、复杂、间接、全自动化的持久层框架。

8、MyBatis编程步骤是什么样的?

1、 创建SqlSessionFactory


2、 通过SqlSessionFactory创建SqlSession


3、 通过sqlsession执行数据库操作


4、 调用session.commit()提交事务


5、 调用session.close()关闭会话


9、请说说MyBatis的工作原理

读取 MyBatis 配置文件:mybatis-config.xml 为 MyBatis 的全局配置文件,配置了 MyBatis 的运行环境等信息,例如数据库连接信息。

加载映射文件。映射文件即 SQL 映射文件,该文件中配置了操作数据库的 SQL 语句,需要在 MyBatis 配置文件 mybatis-config.xml 中加载。mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。

造会话工厂:通过 MyBatis 的环境等配置信息构建会话工厂 SqlSessionFactory。

创建会话对象:由会话工厂创建 SqlSession 对象,该对象中包含了执行 SQL 语句的所有方法。

Executor 执行器:MyBatis 底层定义了一个 Executor 接口来操作数据库,它将根据 SqlSession 传递的参数动态地生成需要执行的 SQL 语句,同时负责查询缓存的维护。

MappedStatement 对象:在 Executor 接口的执行方法中有一个 MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储要映射的 SQL 语句的 id、参数等信息。

输入参数映射:输入参数类型可以是 Map、List 等集合类型,也可以是基本数据类型和 POJO 类型。输入参数映射过程类似于 JDBC 对 preparedStatement 对象设置参数的过程。

输出结果映射:输出结果类型可以是 Map、 List 等集合类型,也可以是基本数据类型和 POJO 类型。输出结果映射过程类似于 JDBC 对结果集的解析过程。

10、Mybatis都有哪些Executor执行器?它们之间的区别是什么?

Mybatis有三种基本的Executor执行器,SimpleExecutor、ReuseExecutor、BatchExecutor。

SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。

ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map<String, Statement>内,供下一次使用。简言之,就是重复使用Statement对象。

BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。

作用范围:Executor的这些特点,都严格限制在SqlSession生命周期范围内。


11、Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?

Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。


它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。


当然了,不光是Mybatis,几乎所有的包括Hibernate,支持延迟加载的原理都是一样的。


12、MyBatis#{}和${}的区别

#{}是占位符,预编译处理;${}是拼接符,字符串替换,没有预编译处理。

Mybatis在处理#{}时,#{}传入参数是以字符串传入,会将SQL中的#{}替换为?号,调用PreparedStatement的set方法来赋值。

Mybatis在处理时 , 是 原 值 传 入 , 就 是 把 {}时,是原值传入,就是把时,是原值传入,就是把{}替换成变量的值,相当于JDBC中的Statement编译。

变量替换后,#{} 对应的变量自动加上单引号 ‘’;变量替换后,${} 对应的变量不会加上单引号 ‘’

#{} 可以有效的防止SQL注入,提高系统安全性;${} 不能防止SQL 注入

#{} 的变量替换是在DBMS 中;${} 的变量替换是在 DBMS 外

13、MyBatis如何获取生成的主键

对于支持主键自增的数据库(MySQL)

4fe24573db1f54a8f8e038018c8a1eb0.png



14、使用MyBatis的mapper接口调用时有哪些要求?

Mapper接口方法名和mapper.xml中定义的每个sql的id相同。

Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同。

Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同。

Mapper.xml文件中的namespace即是mapper接口的类路径。

15、Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?

第一种是使用标签,逐一定义列名和对象属性名之间的映射关系。


第二种是使用sql列的别名功能,将列别名书写为对象属性名,比如T_NAME AS NAME,对象属性名一般是name,小写,但是列名不区分大小写,Mybatis会忽略列名大小写,智能找到与之对应对象属性名,你甚至可以写成T_NAME AS NaMe,Mybatis一样可以正常工作。


有了列名与属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。


16、MyBatis实现一对一,一对多有几种方式,怎么操作的?

有联合查询和嵌套查询。联合查询是几个表联合查询,只查询一次,通过在resultMap里面的association,collection节点配置一对一,一对多的类就可以完成


嵌套查询是先查一个表,根据这个表里面的结果的外键id,去再另外一个表里面查询数据,也是通过配置association,collection,但另外一个表的查询通过select节点配置。


17、Mybatis动态sql是做什么的?都有哪些动态sql?能简述一下动态sql的执行原理不?

Mybatis动态sql可以让我们在Xml映射文件内,以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能,Mybatis提供了9种动态sql标签trim|where|set|foreach|if|choose|when|otherwise|bind。


其执行原理为,使用OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql,以此来完成动态sql的功能。


18、Mybatis是如何进行分页的?分页插件的原理是什么?

Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。


分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。

举例:select * from student,拦截sql后重写为:select t.* from (select * from student) t limit 0, 10


19、Mybatis的一级、二级缓存

一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。

二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置 ;

对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。

SSM

1、SSM分工:

(1)Spring 作为基础框架,整合其他框架


(2)SpringMVC 作为Web开发框架,提供服务期开发支持


(3)MyBatis 作为ORM框架,提供数据库开发支持


八、SpringBoot面试题

1、什么是SpringBoot

Spring Boot 是 Spring 开源组织下的子项目,是 Spring 组件一站式解决方案,主要是简化了使用 Spring 的难度,简省了繁重的配置,提供了各种启动器,开发者能快速上手。


2、Spring Boot 有哪些优点?

容易上手,提升开发效率,为 Spring 开发提供一个更快、更广泛的入门体验。

开箱即用,远离繁琐的配置。

提供了一系列大型项目通用的非业务性功能,例如:内嵌服务器、安全管理、运行数据监控、运行状况检查和外部化配置等。

没有代码生成,也不需要XML配置。

避免大量的 Maven 导入和各种版本冲突。

3、Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?

启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了以下 3 个注解:


@SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。


@EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })。


@ComponentScan:Spring组件扫描。


4、Spring Boot 自动配置原理是什么?

自动装配,简单来说就是自动把第三方组件的Bean装载到SpringIOC器里面,不需要开发人员再去写Bean的装配配置。


在SpringBoot应用里面,只需要在启动类加上@SpringBootApplication注解就可以实现自动装配。


@SpringBootApplication是一个复合注解,真正实现自动装配的注解是@EnableAutoConfiguration。


自动装配的实现主要依靠三个核心关键技术。


引入Starter启动依赖组件的时候,这个组件里面必须要包含@Configuration配置类,在这个配置类里面通过@Bean注解声明需要装配到IOC容器的Bean对象。


这个配置类是放在第三方的jar包里面,然后通过SpringBoot中的约定优于配置思想,把这个配置类的全路径放在classpath:/META-INF/spring.factories文件中。这样SpringBoot就可以知道第三方jar包里面的配置类的位置,这个步骤主要是用到了Spring里面的SpringFactoriesLoader来完成的。


SpringBoot拿到所第三方jar包里面声明的配置类以后,再通过Spring提供的ImportSelector接口,实现对这些配置类的动态加载。


在我看来,SpringBoot是约定优于配置这一理念下的产物,所以在很多的地方,都会看到这类的思想。它的出现,让开发人员更加聚焦在了业务代码的编写上,而不需要去关心和业务无关的配置。


其实,自动装配的思想,在SpringFramework3.x版本里面的@Enable注解,就有了实现的雏形。@Enable注解是模块驱动的意思,我们只需要增加某个@Enable注解,就自动打开某个功能,而不需要针对这个功能去做Bean的配置,@Enable底层也是帮我们去自动完成这个模块相关Bean的注入。以上,就是我对SpringBoot自动装配机制的理解。


5、Spring Boot 配置加载顺序详解

1、properties文件;


2、YAML文件;


3、系统环境变量;


4、命令行参数;


6、YAML 配置的优势在哪里 ?

YAML 现在可以算是非常流行的一种配置文件格式了,无论是前端还是后端,都可以见到 YAML 配置。那么 YAML 配置和传统的 properties 配置相比到底有哪些优势呢?


配置有序,在一些特殊的场景下,配置有序很关键

支持数组,数组中的元素可以是基本数据类型也可以是对象

简洁

7、Spring Boot 中如何解决跨域问题 ?

跨域可以在前端通过 JSONP 来解决,但是 JSONP 只可以发送 GET 请求,无法发送其他类型的请求,在 RESTful 风格的应用中,就显得非常鸡肋,因此我们推荐在后端通过 (CORS,Cross-origin resource sharing) 来解决跨域问题。这种解决方案并非 Spring Boot 特有的,在传统的 SSM 框架中,就可以通过 CORS 来解决跨域问题,只不过之前我们是在 XML 文件中配置 CORS ,现在可以通过实现WebMvcConfigurer接口然后重写addCorsMappings方法解决跨域问题。


8、SpringBoot打成的jar和普通的jar有什么区别?

Spring Boot 项目最终打包成的 jar 是可执行 jar ,这种 jar 可以直接通过 java -jar xxx.jar 命令来运行,


这种 jar 不可以作为普通的 jar 被其他项目依赖,即使依赖了也无法使用其中的类。


Spring Boot 的 jar 无法被其他项目依赖,主要还是他和普通 jar 的结构不同。普通的 jar 包,解压后直、接就是包名,包里就是我们的代码,而 Spring Boot 打包成的可执行 jar 解压后,在 \BOOT-INF\classes目录下才是我们的代码,因此无法被直接引用。如果非要引用,可以在 pom.xml 文件中增加配置,将Spring Boot 项目打包成两个 jar ,一个可执行,一个可引用。


9、什么是YAML?

YAML是一种人类可读的数据序列化语言。它通常用于配置文件。 与属性文件相比,如果我们想要在配置文件中添加复杂的属性,YAML文件就更加结构化,而且更少混淆。可以看出YAML具有分层配置数据。


10、Spring Boot、Spring MVC 和 Spring 有什么区别?

Spring Spring最重要的特征是依赖注入。所有 SpringModules 不是依赖注入就是 IOC 控制反转。当我们恰当的使用 DI 或者是 IOC 的时候,我们可以开发松耦合应用。松耦合应用的单元测试可以很容易的进行。

Spring MVC Spring MVC 提供了一种分离式的方法来开发 Web 应用。通过运用像 DispatcherServelet,MoudlAndView 和 ViewResolver 等一些简单的概念,开发 Web 应用将会变的非常简单。

SpringBoot Spring 和 SpringMVC 的问题在于需要配置大量的参数。

11、Spring Boot 中如何解决跨域问题 ?

跨域可以在前端通过 JSONP 来解决,但是 JSONP 只可以发送 GET 请求,无法发送其他类型的请求,在RESTful 风格的应用中,就显得非常鸡肋,因此我们推荐在后端通过 (CORS,Cross-origin resourcesharing) 来解决跨域问题。这种解决方案并非 Spring Boot 特有的,在传统的 SSM 框架中,就可以通过 CORS 来解决跨域问题,只不过之前我们是在 XML 文件中配置 CORS ,现在可以通过实现


WebMvcConfigurer接口然后重写addCorsMappings方法解决跨域问题。


12、什么是 CSRF 攻击?

CSRF 代表跨站请求伪造。这是一种攻击,迫使最终用户在当前通过身份验证的Web 应用程序上执行不需要的操作。CSRF 攻击专门针对状态改变请求,而不是数据窃取,因为攻击者无法查看对伪造请求的响应。


14、SpringBoot支持哪些日志框架?推荐和默认的日志框架是哪个?

Spring Boot 支持 Java Util Logging, Log4j2, Lockback 作为日志框架,如果你使用 Starters 启动器,Spring Boot 将使用 Logback 作为默认日志框架,但是不管是那种日志框架他都支持将配置文件输出到控制台或者文件中。


15、SpringBoot Starter的工作原理

我个人理解SpringBoot就是由各种Starter组合起来的,我们自己也可以开发Starter在sprinBoot启动时由@SpringBootApplication注解会自动去maven中读取每个starter中的spring.factories文件,该文件里配置了所有需要被创建spring容器中的bean,并且进行自动配置把bean注入SpringContext中 //(SpringContext是Spring的配置文件)


16、SpringBoot多数据源事务如何管理

第一种方式是在service层的@TransactionManager中使用transactionManager指定DataSourceConfig中配置的事务

第二种是使用jta-atomikos实现分布式事务管理

17、SpringBoot中如何实现定时任务 ?

在 Spring Boot 中使用定时任务主要有两种不同的方式,一个就是使用 Spring 中的 @Scheduled 注解,另一-个则是使用第三方框架 Quartz。

使用 Spring 中的 @Scheduled 的方式主要通过 @Scheduled 注解来实现。

18、spring-boot-starter-parent有什么用?

我们都知道,新创建一个 Spring Boot 项目,默认都是有 parent 的,这个 parent 就是 springboot-starter-parent ,spring-boot-starter-parent 主要有如下作用:1. 定义了 Java 编译版本为 1.8 。2. 使用 UTF-8 格式编码。3. 继承自 spring-boot-dependencies,这个里边定义了依赖的版本,也正是因为继承了这个依赖,所以我们在写依赖时才不需要写版本号。4. 执行打包操作的配置。5. 自动化的资源过滤。6. 自动化的插件配置。7. 针对 application.properties 和 application.yml 的资源过滤,包括通过 profile 定义的不同环境的配置文件,例如 application-dev.properties 和 application-dev.yml。


九、SpringCloud微服务面试题

1、什么是SpringCloud

Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、智能路由、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它只是将各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。


2、互联网架构演进

1、单体应用架构

项目所有功能模块放在一个工程中编码、编译、打包部署在一个tomcat容器中。


简单实用、便于维护、成本低。


**优点:**高效开发、架构简单、易于测试、易于部署。


**缺点:**可靠性差、复杂性高、扩展能力受限。


2、垂直应用架构

为了业务之间互不影响,提高效率、减少组件之间的依赖。


优点:流量分担解决并发问题;


可以针对不同模块进行优化;


方便水平扩展、负载均衡、容错率高;


系统间相互独立,互不影响,业务迭代更高效。


**缺点:**服务之间相互调用,端口发生改变得手动改变;


搭建集群之后,实现负载均衡比较复杂;


服务之间调用方式不统一;


服务监控不到位。


3、SOA应用架构

Dubbo 高性能、轻量级的开源java RPC框架,可以和Spring框架无缝集成。


核心功能:面向接口的远程方法调用;


智能容错和负载均衡;


服务自动注册和发现。


**优点:**分布式、松耦合、扩展灵活、可重用。


缺点:服务抽取力度较大,服务调用方和提供耦合度较高。


4、微服务应用架构

拆分粒度更小,服务更独立。微小、独立、轻量级通信。


重点:业务需要彻底组件化服务化。


优点:


微小,便于特定服务的聚焦,解耦、便于实施敏捷开发。


便于重用和模块之间的组装


独立,松耦合,不同的微服务可以使用不同的语言开发。


更容易引进新的技术。


缺点:


分布式复杂难以管理。


分布式链路跟踪难。


3、什么是服务注册与服务发现。

服务注册:提供者将所提供服务的信息(服务器IP和端口、访问协议)


服务发现:消费者从中获取到服务列表。


Eureka 服务注册和发现可以在这种情况下提供帮助。由于所有服务都在 Eureka 服务器上注册并通过调用 Eureka 服务器完成查找,因此无需处理服务地点的任何更改和处理。


4、SpringBoot和SpringCloud的区别?

SpringBoot专注于快速方便的开发单个个体微服务。

SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并管理起来,

为各个微服务之间提供,配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等集成服务

SpringBoot可以离开SpringCloud独立使用开发项目, 但是SpringCloud离不开SpringBoot ,属于依赖的关系

SpringBoot专注于快速、方便的开发单个微服务个体,SpringCloud关注全局的服务治理框架。

5、Spring Cloud的优缺点有哪些?

优点:


服务拆分粒度更细,有利于资源重复利用,有利于提高开发效率

可以更精准的制定优化服务方案,提高系统的可维护性

微服务架构采用去中心化思想,服务之间采用Restful等轻量级通讯,比ESB更轻量

适于互联网时代,产品迭代周期更短

缺点:


微服务过多,治理成本高,不利于维护系统

分布式系统开发的成本高(容错,分布式事务等)对团队挑战大

总的来说优点大过于缺点,目前看来SpringCloud是一套非常完善的分布式框架,目前很多企业开始用微服务、Spring Cloud的优势是显而易见的。因此对于想研究微服务架构的同学来说,学习 Spring Cloud 是一个不错的选择。


6、Eureka的服务治理是什么?

Spring Cloud 封装了 Netflix 公司开发的 Eureka 模块来实现服务治理。


在传统的rpc远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务于服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册。


7、Eureka的服务注册是什么?

Eureka采用了CS的设计架构,Eureka Server 作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用 Eureka的客户端连接到 Eureka Server并维持心跳连接。这样系统的维护人员就可以通过 Eureka Server 来监控系统中各个微服务是否正常运行。


在服务注册与发现中,有一个注册中心。当服务器启动的时候,会把当前自己服务器的信息 比如 服务地址通讯地址等以别名方式注册到注册中心上。另一方(消费者|服务提供者),以该别名的方式去注册中心上获取到实际的服务通讯地址,然后再实现本地RPC调用RPC远程调用框架核心设计思想:在于注册中心,因为使用注册中心管理每个服务与服务之间的一个依赖关系(服务治理概念)。在任何rpc远程框架中,都会有一个注册中心(存放服务地址相关信息(接口地址))


8、什么是Spring Cloud Ribbon?

Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。


9、Nginx和Ribbon的区别

Nginx是反向代理同时可以实现负载均衡,nginx拦截客户端请求采用负载均衡策略根据upstream配置进行转发,相当于请求通过nginx服务器进行转发。Ribbon是客户端负载均衡,从注册中心读取目标服务器信息,然后客户端采用轮询策略对服务直接访问,全程在客户端操作


10、Ribbon支持的负载均衡算法

轮询策略

随机策略

重试策略

最小连接数策略

可用过略策略

区域权衡策略

11、服务器雪崩

一种因“服务提供者不可用”导致“服务调用这不可用”,并将不可用逐渐扩大的现象。


形成原因:


(1)服务提供者不可用(硬件故障、程序bug、缓存击穿、用户大量请求)


(2)重试加大请求流量(用户重试、代码逻辑重试)


(3)服务调者不可用(同步等待造成的资源耗尽)


解决方案:


(1)服务器熔断


(2)服务降级


(3)服务限流


12、Hystrix熔断器

一个延迟和容错库,用于隔离访问远程系统、服务或者第三方库,防止级联失败,提升系统的可用性与容错性。


包裹请求

跳闸机制

资源隔离

监控

回退机制

自我修复

13、Feign

轻量级HTTP服务客户端(发送请求、远程调用)。


本质:封装了Http调用流程,更符合面向接口化的编程习惯,类似于Dubbo的服务调用。


对熔断的支持:


客户端工程配置文件中开启支持,超时时长设置。


(1)开启Hystrix后,Feign中的方法进行一个管理,一旦出问题就进入对应的回退逻辑处理。


(2)当有两个超时时间设置,熔断的时候根据两个时间的最小值进行。


14、Gateway的作用

网关的作用是负载均衡、路由转发、请求过虑等。项目中网关与Nginx配合使用


15、Gateway的工作流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TwNNoD45-1676522455054)(https://edu–learn.oss-cn-beijing.aliyuncs.com/weixin/%E5%9B%BE%E7%89%873.png)]


16、Gateway的路由规则

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zjenkbPD-1676522455055)(https://edu–learn.oss-cn-beijing.aliyuncs.com/weixin/%E5%9B%BE%E7%89%874.png)]


17、Gateway的过滤使用


GlobalFilter全局过滤器是程序员使用比较多的过滤器,可以在过滤器中完成鉴权、流量控制、IP黑白名单、权限控制、日志监控等。


18、什么是Spring Cloud Alibaba?

Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。


19、Spring Cloud Alibaba有哪些功能?

服务限流降级:默认支持 WebServlet、WebFlux, OpenFeign、RestTemplate、Spring Cloud Gateway, Zuul, Dubbo 和 RocketMQ 限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。

服务注册与发现:适配 Spring Cloud 服务注册与发现标准,默认集成了 Ribbon 的支持。

分布式配置管理:支持分布式系统中的外部化配置,配置更改时自动刷新。

消息驱动能力:基于 Spring Cloud Stream 为微服务应用构建消息驱动能力。

分布式事务:使用 @GlobalTransactional 注解, 高效并且对业务零侵入地解决分布式事务问题。

阿里云对象存储:阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。

分布式任务调度:提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有 Worker(schedulerx-client)上执行。

阿里云短信服务:覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。

20、Spring Cloud Alibaba的常用组件有哪些?

Sentinel (opens new window):把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。


Nacos (opens new window):一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。


RocketMQ (opens new window):一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。


Dubbo (opens new window):Apache Dubbo™ 是一款高性能 Java RPC 框架。


Seata (opens new window):阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。


Alibaba Cloud OSS (opens new window): 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。


Alibaba Cloud SchedulerX (opens new window): 阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。


Alibaba Cloud SMS (opens new window): 覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。


21、什么是Nacos?

前面组件中也有简单介绍;Nacos命名的由来:前四个字母分别是Naming和Configuration的前两个字母,后面的s是Service


Nacos是一个易于使用的动态服务发现,配置和服务管理平台,用于构建云本机应用程序。使用Spring Cloud Alibaba Nacos Discovery,您可以基于Spring Cloud的编程模型快速访问Nacos服务注册功能。


Nacos就是注册中心+配置中心的组合


22、Nacos有什么作用?

替代Eureka做服务注册

替代Config做配置中心

服务发现与服务健康检查 Nacos使服务更容易注册,并通过DNS或HTTP接口发现其他服务,Nacos还提供服务的实时健康检查,以防 止向不健康的主机或服务实例发送请求。

动态配置管理 动态配置服务允许您在所有环境中以集中和动态的方式管理所有服务的配置。Nacos消除了在更新配置时重新 部署应用程序,这使配置的更改更加高效和灵活。

动态DNS服务 Nacos提供基于DNS 协议的服务发现能力,旨在支持异构语言的服务发现,支持将注册在Nacos上的服务以 域名的方式暴露端点,让三方应用方便的查阅及发现。

服务和元数据管理 Nacos 能让您从微服务平台建设的视角管理数据中心的所有服务及元数据,包括管理服务的描述、生命周 期、服务的静态依赖分析、服务的健康状态、服务的流量管理、路由及安全策略。

23、什么是Spring Cloud Seata?

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。


目录
相关文章
|
安全
病理学知识点整理
病理学知识点整理
71 0
|
NoSQL Java 关系型数据库
面试题整理
面试题整理
61 0
|
消息中间件 缓存 Java
常见面试题整理(2022-11)
常见面试题整理(2022-11)
59 0
|
缓存 JavaScript 前端开发
前端面试题整理?
前端面试题整理?
|
缓存 前端开发 JavaScript
前端面试题大全整理中...
前端面试题大全整理中...
75 0
|
存储 NoSQL 网络协议
面试题整理(六)
面试题整理(六)
176 0
|
存储 监控 安全
面试题整理(二)
面试题整理(二)
129 0
|
存储 SQL 缓存
面试题整理(三)
面试题整理(三)
363 0
|
存储 消息中间件 缓存
面试题整理(五)
面试题整理(五)
253 0
|
存储 XML 安全
面试题整理(一)
面试题整理(一)
184 0