当前位置: 首页 > news >正文

SSM框架相关面试题

写在前面

🔥我把后端Java面试题做了一个汇总,有兴趣大家可以看看!这里👉

⭐️在反复复习面试题时,我发现不同资料的解释五花八门,容易造成概念混淆。尤其是很多总结性的文章和视频,要么冗长难记,要么过于简略,导致关键知识点含糊不清。

⭐️为了系统梳理知识,我决定撰写一份面试指南,不只是简单汇总,而是融入个人理解,层层拆解复杂概念,构建完整的知识体系。我希望它不仅帮助自己更自信地应对面试,也能为同行提供清晰、实用的参考。


SSM框架相关面试题

面试官: Spring,Spring MVC,Spring Boot 之间什么关系?

Spring MVCSpring 中的一个很重要的模块,主要赋予 Spring 快速构建 MVC 架构的 Web 程序的能力。MVC 是模型(Model)、视图(View)、控制器(Controller)的简写,其核心思想是通过将业务逻辑、数据、显示分离来组织代码。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 Spring 进行开发各种配置过于麻烦比如开启某些 Spring 特性时,需要用 XML 或 Java 进行显式配置。于是,Spring Boot 诞生了!Spring Boot 只是简化了配置,如果你需要构建 MVC 架构的 Web 程序,你还是需要使用 Spring MVC 作为 MVC 框架,只是说 Spring Boot 帮你简化了 Spring MVC 的很多配置,真正做到开箱即用!

面试官:@RestController vs @Controller

候选人

@Controller + @ResponseBody = @RestController

Controller 返回⼀个⻚⾯

单独使⽤ @Controller 不加 @ResponseBody 的话⼀般使⽤在要返回⼀个视图的情况,这种情况属于⽐传统的Spring MVC 的应⽤,对应于前后端不分离的情况。

image-20250220112800901

@RestController 返回JSON 或 XML 形式数据

@RestController 只返回对象,对象数据直接以 JSON 或 XML 形式写⼊ HTTP 响应(Response)中,这种情况属于 RESTful Web服务,这也是⽬前⽇常开发所接触的最常⽤的情况(前后端分离)。

image-20250220112812238

@ResponseBody 注解的作⽤是将 Controller 的⽅法返回的对象通过适当的转换器转换为指定的格式之后,写⼊到HTTP 响应(Response)对象的 body 中,通常⽤来返回 JSON 或者XML 数据,返回 JSON 数据的情况⽐多。

image-20250220112822929

面试官:BeanFactory和FactoryBean有什么区别?

候选人

1)BeanFactory是IoC容器,在程序启动时根据传入参数产生各种类型的bean,并添加到IoC容器的singletonObject属性中。

2)FactoryBean是个bean,存放在BeanFactory当中,在程序运行中产生指定类型的bean,并添加到IoC容器的factoryBeanObjectCache(缓存)当中。

当你定义了一个 FactoryBean,Spring 通过它来创建真正的 bean,而不是将 FactoryBean 本身作为 bean 提供。

面试官:@Autowired 和 @Resource 的区别是什么?

候选人

  • @Autowired 是 Spring 提供的注解,@Resource 是 JDK 提供的注解。

  • Autowired 默认的注入方式为byType(根据类型进行匹配),@Resource默认注入方式为 byName(根据名称进行匹配)。

  • 当一个接口存在多个实现类的情况下,@Autowired@Resource都需要通过名称才能正确匹配到对应的 Bean。@Autowired 可以通过 @Qualifier 注解来显示指定名称,@Resource可以通过 name 属性来显示指定名称。

// 报错,byName 和 byType 都无法匹配到 bean
@Autowired
private SmsService smsService;

// 正确注入 SmsServiceImpl1 对象对应的 bean
@Autowired
private SmsService smsServiceImpl1;

// 正确注入  SmsServiceImpl1 对象对应的 bean
@Autowired
@Qualifier(value = "smsServiceImpl1")
private SmsService smsService;
// 报错,byName 和 byType 都无法匹配到 bean
@Resource
private SmsService smsService;

// 正确注入 SmsServiceImpl1 对象对应的 bean
@Resource
private SmsService smsServiceImpl1;

// 正确注入 SmsServiceImpl1 对象对应的 bean(比较推荐这种方式)
@Resource(name = "smsServiceImpl1")
private SmsService smsService;

面试官: Spring Bean 默认是单例的,如何保证并发安全?

候选人:

Spring 的 Bean 默认都是单例的,某些情况下,单例是并发不安全的,以 Controller 举例,问题根源在于,我们可能会在 Controller 中定义成员变量,如此一来,多个请求来临,进入的都是同一个单例的 Controller 对象,并对此成员变量的值进行修改操作,因此会互相影响,无法达到并发安全(不同于线程隔离的概念,后面会解释到)的效果。

首先来举个例子,证明单例的并发不安全性:

@Controller
public class HomeController {
    private int i;
    @GetMapping("testsingleton1")
    @ResponseBody
    public int test1() {
        return ++i;
    }
}

多次访问此 url,可以看到每次的结果都是自增的,所以这样的代码显然是并发不安全的。

我们为了让无状态的海量 HTTP 请求之间不受影响,我们可以采取以下几种措施:

1、单例变原型

对 web 项目,可以 Controller 类上加注解 @Scope("prototype")@Scope("request")

对非 web 项目,在 Component 类上添加注解 @Scope("prototype")

这种方式实现起来非常简单,但是很大程度上增大了 Bean 创建实例化销毁的服务器资源开销

2、尽量避免使用成员变量

有人说,单例 Bean 的成员变量这么麻烦,能不用成员变量就尽量避免这么用,在业务允许的条件下,将成员变量替换为方法中的局部变量,多省事。这种方式自然是最恰当的。代码修改如下:

@Controller
public class HomeController {
    @GetMapping("testsingleton1")
    @ResponseBody
    public int test1() {
         int i = 0;
         // TODO biz code
         return ++i;
    }
}

但当很少的某种情况下,必须使用成员变量呢,我们该怎么处理?

3、使用并发安全的容器

Java 作为功能性超强的编程语言,API 丰富,如果非要在单例 Bean 中使用成员变量,可以考虑使用并发安全的容器,如 ConcurrentHashMapConcurrentHashSet 等等。

4、分布式或微服务的并发安全

如果还要进一步考虑到微服务或分布式服务的影响,方式 4 便不足以处理了,所以可以借助于可以共享某些信息的分布式缓存中间件如 Redis 等,这样即可保证同一种服务的不同服务实例都拥有同一份共享信息(如当前运行中的任务列表等这类变量)。

面试官:谈谈⾃⼰对于 Spring IoC 和 AOP 的理解(高频)

候选人

IoC

IoC(Inverse of Control:控制反转)是⼀种设计思想,就是将原本在程序中⼿动创建对象的控制权,交由Spring框架来管理。 IoC 容器实际上就是个Map(key,value),Map 中存放的是各种对象。将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC 容器完成对象的注⼊。这样可以很⼤程度上简化应⽤的开发,把应⽤从复杂的依赖关系中解放出来。

IoC 容器就像是⼀个⼯⼚⼀样,当我们需要创建⼀个对象的时候,只需要配置好配置⽂件/注解即可,完全不⽤考虑对象是如何被创建出来的。 在实际项⽬中⼀个 Service 类可能有⼏百甚⾄上千个类作为它的底层,假如我们需要实例化这个 Service,你可能要每次都要搞清这个 Service 所有底层类的构造函数,这可能会把⼈逼疯。如果利⽤ IoC 的话,你只需要配置好,然后在需要的地⽅引⽤就⾏了,这⼤⼤增加了项⽬的可维护性且降低了开发难度。

AOP

AOP是面向切面编程,在spring中用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取公共模块复用,降低耦合,一般比如可以做为公共日志保存事务处理等。

Spring AOP 主要依赖动态代理来实现,接下来我会讲述 Spring AOP 的执行流程,主要分为六步。

当 Spring AOP 拦截一个方法调用时:

第一步是要定义切面(Aspect),可以使用 @Aspect 标注类,并在其中定义切点(Pointcut)和通知(Advice),如 @Before、@After、@Around 等。

第二步是要解析切点,Spring 会解析 @Pointcut 表达式,确定需要增强的方法。

第三步是要创建代理对象,如果目标类实现了接口,Spring 使用 JDK 动态代理,通过 Proxy.newProxyInstance 生成代理对象;如果目标类没有实现接口,Spring 使用 CGLIB 动态代理,通过创建目标类的子类来生成代理对象。

第四步是要方法调用拦截,如果是JDK 动态代理,代理对象会拦截方法调用,并调用invoke,执行增强逻辑后,再调用目标方法;如果是CGLIB 动态代理,代理对象则通过 intercept 代理方法调用,执行增强逻辑后,再调用目标方法。

第五步是要执行增强逻辑,根据通知类型,在方法执行前后或异常时,执行对应的 AOP 逻辑,如日志记录、事务提交等。

第六步是要执行目标方法,最终调用目标对象的方法,完成实际业务逻辑。

Comparison and application of Spring AOP and AspectJ - Spring Cloud

面试官: 什么是动态代理?(高频)

动态代理是一种在运行时动态生成代理对象,并在代理对象中增强目标对象方法的技术。它被广泛用于 AOP(面向切面编程)、权限控制、日志记录等场景,使得程序更加灵活、可维护。动态代理可以通过 JDK 原生的 Proxy 机制或 CGLIB 方式实现。接下来我会讲述动态代理的实现方式和执行流程。

JDK 动态代理

首先,JDK 动态代理基于接口,适用于代理实现了接口的对象,当使用 JDK 动态代理时,主要分为四步,

第一步是定义接口,由于动态代理是基于接口进行代理的,因此目标对象必须实现接口。

第二步是创建并实现 InvocationHandler 接口,并在 invoke 方法中定义增强逻辑。

第三步是生成代理对象,使用 Proxy.newProxyInstance 创建代理对象,代理对象内部会调用 invoke 方法。

第四步是调用代理方法,当调用代理对象的方法时,invoke 方法会被触发,执行增强逻辑,并最终调用目标方法。

CGLIB 动态代理

其次,CGLIB 通过子类继承目标类,适用于没有实现接口的类,当使用 CGLIB 动态代理时,主要分为四步,

第一步是通过 Enhancer 创建代理对象

第二步是设置父类,CGLIB 代理基于子类继承,因此代理对象是目标类的子类。

第三步是定义并实现 MethodInterceptor 接口,在 intercept 方法中增强目标方法。

第四步是调用代理方法,当调用代理对象的方法时,intercept 方法会被触发,执行增强逻辑,并最终调用目标方法。

面试官: 动态代理和静态代理的区别(高频)

动态代理和静态代理都属于代理模式,它们都用于在不修改目标对象代码的情况下增强其功能。接下来我会详细讲述动态代理和静态代理的五点区别。

第一点是实现方式的不同,静态代理需要手动编写代理类,而动态代理在运行时动态生成代理类。

第二点是灵活性的不同,静态代理不够灵活,代理类与目标类一一对应;而动态代理更加灵活,适用于多种目标类。

第三点是维护成本的不同,静态代理的维护成本较高,因为每个目标类都需要一个代理类;而动态代理的维护成本较低,因为代理逻辑是通用的。

第四点是技术依赖的不同,静态代理基于普通 Java 类;动态代理依赖反射或字节码技术。

第五点是适用场景的不同,静态代理则适用于简单的、目标类较少的场景;而动态代理适合需要为多个目标类添加相同逻辑的场景。

面试官:将⼀个类声明为Spring的 bean 的注解有哪些?

候选人

我们⼀般使⽤ @Autowired 注解⾃动装配 bean,要想把类标识成可⽤于 @Autowired 注解⾃动装配的 bean 的类,采⽤以下注解可实现:

  1. @Component :通⽤的注解,可标注任意类为 Spring 组件。如果⼀个Bean不知道属于哪个层,可以使⽤ @Component 注解标注。

  2. @Repository : 对应持久层即 Dao 层,主要⽤于数据库相关操作。

  3. @Service : 对应服务层,主要涉及⼀些复杂的逻辑,需要⽤到 Dao层。

  4. @Controller : 对应 Spring MVC 控制层,主要⽤户接受⽤户请求并调⽤ Service 层返回数据给前端⻚⾯。

面试官:Spring中事务失效的场景有哪些(高频)

候选人:见文章:详解Spring事务失效的八种常见场景

第一个,如果方法上异常捕获处理,自己处理了异常,没有抛出,就会导致事务失效,所以一般处理了异常以后,别忘了抛出去就行。

第二个,如果事务方法内部抛出了 运行时异常(RuntimeException),Spring 会默认回滚事务。如果抛出了 受检查异常(Checked Exception),Spring 默认不会回滚事务,除非使用 @Transactional(rollbackFor = Exception.class) 明确指定应当回滚受检查异常。

第三个,如果方法上不是public修饰的,也会导致事务失效。为了解决这个问题,我们需要将事务方法的访问修饰符改为public即可。

第四个,当方法内部通过 this 调用事务也会失败,需要通过上下文获取代理对象才能重启事务。

第五个,同一个Service类中非事务方法调用了事务性的方法,也会导致事务失效。解决方法:确保所有涉及数据库操作的方法都被@Transactional注解修饰。

第六个,当使用不支持事务的数据库引擎时,例如 MySQL 的 MyISAM 引擎不支持事务,即使代码中配置了事务管理,也无法生效。因此,确保使用的数据库引擎(如 InnoDB)支持事务是非常重要的。

面试官:Spring的bean的生命周期(高频)

候选人

首先会通过一个非常重要的类,叫做BeanDefinition获取bean的定义信息,这里面就封装了bean的所有信息。在创建bean的时候:

第一步是调用构造函数实例化bean

第二步是bean的依赖注入,比如一些set方法注入,像平时开发用的@Autowire都是这一步完成

第三步是处理Aware接口,如果某一个bean实现了Aware接口就会重写方法执行

第四步是执行了bean的前置处理器BeanPostProcessor对象的postProcessBeforeInitialization() ⽅法

第五步是初始化方法,比如实现了接口InitializingBean或者自定义init方法

第六步是执行了bean的后置处理器BeanPostProcessor对象的postProcessAfterInitialization() ⽅法,主要是对bean进行增强,有可能在这里产生代理对象

最后一步是销毁bean

如何记忆Spring Bean的生命周期- 草捏子

面试官:Spring中的循环引用

候选人

循环依赖:循环依赖其实就是循环引用,也就是两个或两个以上的bean互相持有对方,最终形成闭环。比如A依赖于B,B依赖于A。

循环依赖在spring中是允许存在,spring框架依据三级缓存已经解决了大部分的循环依赖问题:

①一级缓存:单例池,缓存(已经经历了完整的生命周期,已经初始化完成的)bean对象

②二级缓存:缓存早期的bean对象(生命周期还没走完)

③三级缓存:缓存的是ObjectFactory,表示对象工厂,用来创建某个对象的

面试官:那具体解决流程清楚吗?

候选人

第一,先实例A对象,同时会创建ObjectFactory对象存入三级缓存singletonFactories

第二,A在初始化的时候需要B对象,这个走B的创建的逻辑

第三,B实例化完成,也会创建ObjectFactory对象存入三级缓存singletonFactories

第四,B需要注入A,通过三级缓存中获取ObjectFactory来生成一个A的对象同时存入二级缓存,这个是有两种情况,一个是可能是A的普通对象,另外一个是A的代理对象,都可以让ObjectFactory来生产对应的对象,这也是三级缓存的关键

第五,B通过从通过二级缓存earlySingletonObjects 获得到A的对象后可以正常注入,B创建成功,存入一级缓存singletonObjects

第六,回到A对象初始化,因为B对象已经创建完成,则可以直接注入B,A创建成功存入一级缓存singletonObjects

第七,二级缓存中的临时对象A清除

image-20250220131739478

面试官:构造方法出现了循环依赖怎么解决?

候选人

由于bean的生命周期中构造函数是第一个执行的,spring框架并不能解决构造函数的的依赖注入,可以使用@Lazy懒加载,什么时候需要对象再进行bean对象的创建。例如:

public A(@lazy B b){
	....
}

面试官:SpringMVC的执行流程知道嘛(高频)

候选人

image-20250220131759779

1、用户发送出请求到前端控制器DispatcherServlet,这是一个调度中心

2、DispatcherServlet收到请求调用HandlerMapping(处理器映射器)。

3、HandlerMapping找到具体的处理器(可查找xml配置或注解配置),生成处理器对象及处理器拦截器(如果有),再一起返回给DispatcherServlet。

4、DispatcherServlet调用HandlerAdapter(处理器适配器)。

5、HandlerAdapter经过适配调用具体的处理器(Handler/Controller)。

6、Controller执行完成返回ModelAndView对象。

7、HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet。

8、DispatcherServlet将ModelAndView传给ViewReslover(视图解析器)。

9、ViewReslover解析后返回具体View(视图)。

10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。

11、DispatcherServlet响应用户。

当然现在的开发,基本都是前后端分离的开发的,并没有视图这些,一般都是handler中使用Response直接返回结果。

面试官:#{ }和${ }的区别是什么?(高频)

候选人

  1. 符号类型

    #{ }:参数占位符,即预编译,对传入参数自动加单引号

    ${ }:字符串替换符,即SQL拼接,对传入参数不加任何引号

    预编译(Prepared Statement)是指将SQL语句模板提前编译为可执行计划,参数(如用户输入)在运行时绑定。这样可以避免SQL注入,并提高重复执行的效率。

    PREPARE stmt FROM 'SELECT * FROM users WHERE id = ?';
    SET @id = 1;
    EXECUTE stmt USING @id;
    
  2. 防止注入问题

    #{ }:能防止SQl注入

    ${ }:不能防止SQL注入

  3. sql执行过程

    #{ }:先编译再取值

    ${ }:先取值后编译

  4. MyBatis排序时使用order by用${ }而不是#{ }

  5. 使用场景

    大部分情况下,特别是传入的值为用户输入、动态条件时,推荐使用 #{ } 进行参数绑定。它能有效防止 SQL 注入,并且让代码更安全和简洁。

    表名、列名的动态拼接:这些不能作为参数绑定的元素,只能使用 ${ } 进行拼接。拼接 SQL 片段:在一些复杂 SQL 语句(比如动态构造的 ORDER BYGROUP BY 子句)中,可以使用 ${ } 直接拼接。

<!-- 查询用户 -->
<select id="findUserByName" resultType="User">
    SELECT * FROM users WHERE username = #{username}
</select>

<!-- 插入用户 -->
<insert id="insertUser">
    INSERT INTO users (username, password, email) VALUES (#{username}, #{password}, #{email})
</insert>

<!-- 更新用户 -->
<update id="updateUser">
    UPDATE users SET password = #{password} WHERE id = #{id}
</update>
<!-- 根据动态表名查询 -->
<select id="findRecordsByTable" resultType="Record">
    SELECT * FROM ${tableName} WHERE id = #{id}
</select>

<!-- 动态列名 -->
<select id="findUserOrderByColumn" resultType="User">
    SELECT * FROM users ORDER BY ${columnName} ASC
</select>

<!-- 动态 SQL 片段 -->
<select id="findUsersWithConditions" resultType="User">
    SELECT * FROM users
    WHERE 1=1
    <if test="age != null">
        AND age = #{age}
    </if>
    <if test="gender != null">
        AND gender = #{gender}
    </if>
    ORDER BY ${sortColumn} ${sortOrder}
</select>

面试官:SpringBoot 是如何实现自动装配的?(高频)

候选人

在SpringBoot项目中的引导类上有一个注解@SpringBootApplication,这个注解是对三个注解进行了封装,分别是:

  • @SpringBootConfiguration:这也是一个配置类
  • @EnableAutoConfiguration:springboot实现自动装配的核心注解
  • @ComponentScan: 组件扫描

其中 @EnableAutoConfiguration 是实现自动装配的核心注解。

它通过 @Import 注解来导入一个特殊的配置类,这个配置类会读取项目及其依赖库中的 META-INF/spring.factories 文件里定义的自动配置类,并将它们注册到 Spring 容器中。

在这些配置类中所定义的Bean会根据条件注解所指定的条件决定是否需要将其导入到Spring容器中。

面试官:Spring 的常见注解有哪些?

候选人

第一类是:声明bean,有 @Component、@Service、@Repository、@Controller

第二类是:依赖注入相关的,有@Autowired、@Qualifier、@Resourse

第三类是:设置作用域 @Scope(singleton、prototype, request, session, global-session等)

第四类是:spring配置相关的,比如@Configuration,@ComponentScan 和 @Bean

第五类是:跟aop相关做增强的注解 @Aspect,@Before,@After,@Around,@Pointcut

面试官:SpringMVC常见的注解有哪些?

候选人

@RequestMapping:用于映射请求路径;

@RequestBody:注解实现接收http请求的json数据,将json转换为java对象

@RequestParam:指定请求参数的名称;

@PathViriable:从请求路径下中获取请求参数(/user/{id}),传递给方法的形式参数;

@ResponseBody:注解实现将controller方法返回对象转化为指定类型对象响应给客户端。

@RequestHeader:获取指定的请求头数据,还有像@PostMapping、@GetMapping这些。

面试官:MyBatis执行流程

候选人

①读取MyBatis配置文件(mybatis-config.xml) ,加载运行环境和映射文件

②构造会话工厂SqlSessionFactory,一个项目只需要一个,单例的,一般由spring进行管理

③会话工厂创建SqlSession对象,这里面就含了执行SQL语句的所有方法

④操作数据库的接口,Executor执行器,同时负责查询缓存的维护

⑤Executor接口的执行方法中有一个MappedStatement类型的参数,封装了映射信息

⑥输入参数映射

⑦输出结果映射

面试官:MyBatis分⻚插件的原理是什么?

候选人

分⻚插件的基本原理是使⽤ Mybatis 提供的插件接⼝,实现⾃定义插件,在插件的拦截⽅法内拦截待执⾏的 sql,然后重写 sql,根据 dialect ⽅⾔,添加对应的物理分⻚语句和物理分⻚参数。

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

面试官:Mybatis是否支持延迟加载?

候选人

延迟加载的意思是:就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。

Mybatis 仅⽀持 association 关联对象collection 关联集合对象的延迟加载,association 指的就是⼀对⼀,collection 指的就是⼀对多查询。

在Mybatis配置文件中,可以配置是否启用延迟加载,默认是关闭的。

lazyLoadingEnabled=true|false

面试官:延迟加载的底层原理知道吗?

候选人

延迟加载在底层主要使用的CGLIB动态代理完成的。

第一是,使用CGLIB创建目标对象的代理对象。

第二个是当调用目标方法时,进入拦截器invoke方法,发现目标方法是null值(第一次延迟加载肯定为空),再执行sql查询。

第三个是获取数据以后,调用set方法设置属性值,再继续查询目标方法,就有值了。

面试官:Mybatis的一级、二级缓存用过吗?

候选人

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

PerpetualCache:持久化的缓存接口PerpetualCache,其内部实现是一个HashMap,用于存储查询结果。

关于二级缓存需要单独开启:

二级缓存是基于Namespace和Mapper的作用域起作用的,不是依赖于Session,默认也是采用 PerpetualCache的HashMap 存储。

如果想要开启二级缓存需要在全局配置文件映射文件中开启配置才行。

面试官:Mybatis的二级缓存什么时候会清理缓存中的数据

候选人

当某一个作用域(一级缓存 Session/二级缓存Namespaces)进行了新增、修改、删除操作后,默认该作用域下所有 select 中的缓存将被 clear。

相关阅读:手写SSM、手写SpringBoot

相关文章:

  • Vue3实战七、登录认证与退出登录
  • Spring AOP 核心的技术之一:动态代理
  • 其他合成方式介绍
  • nacos集群部署
  • 【redis】summary
  • rust 同时处理多个异步任务,并在一个任务完成退出
  • PythonJSON解析如何优雅处理嵌套JSON字符串
  • springboot中使用async实现异步编程
  • Docker Compose 部署Nginx反向代理 tomcat
  • 每日算法-250407
  • 数字经济产业标杆:树莓集团如何塑造产业服务价值体系
  • 没有独立显卡如何安装torch
  • 极简设计的力量:用 `apiStore` 提升项目效率与稳定性
  • oracle查询是否锁表了
  • Objective-C语言的编程范式
  • 昇腾910b多机部署deepseek-r1-w8a8量化全攻略
  • Hive 常见面试 300 问
  • leetcode 368. 最大整除子集 中等
  • Scala(六)
  • Matlab绘图—‘‘错误使用 plot输入参数的数目不足‘‘
  • 李成钢:近期个别经济体实施所谓“对等关税”,严重违反世贸组织规则
  • 中国青年报:为见义勇为者安排补考,体现了教育的本质目标
  • 韧性十足的中国外贸企业:“不倒翁”被摁下去,还会再弹起来
  • 严打金融黑灰产,今年来上海警方破获各类经济犯罪案件690余起
  • 泽连斯基启程前往土耳其
  • 江西贵溪:铜板上雕出的国潮美学