Java 全栈开发工程师面试题

2025 年 3 月 17 日 | 阅读 26 分钟

全栈开发工程师是能够同时处理网站和应用程序的**前端和后端**的熟练程序员。他们负责开发和设计前端/后端 Web 架构、服务器端应用程序、设计数据库、服务器端应用程序等等。

正因如此,科技巨头们会招聘全栈开发工程师并进行面试。如果你为**全栈开发工程师面试**做好了充分准备,那么你被公司录用的机会就会增加。在本节中,我们收集了一些**全栈开发工程师面试题**,它们可以帮助你通过面试,找到心仪的工作。

在过去的几年里,**全栈开发工程师**的职位需求一直在增长,因为他们能够处理不同的技术和语言。此外,全栈开发工程师还擅长解决应用程序或 Web 开发的各个阶段出现的异常问题。

Full-Stack Developer Interview Questions Java

1) 全栈开发工程师应该了解什么?

Java 全栈开发工程师需要全面理解前端和后端开发,同时熟练掌握 Java 及相关技术。

1. 核心 Java

  • 面向对象编程 (OOP): 理解继承、多态、封装和抽象等概念。
  • 集合框架: 熟练使用列表、集合、映射和队列等数据结构。
  • 并发: 了解多线程和并发机制。
  • 异常处理: 正确的错误处理和日志记录技术。

2. Java 框架

  • Spring 框架: 熟练掌握 Spring Core、Spring MVC、Spring Boot 和 Spring Security,用于构建健壮且可扩展的 Web 应用程序。
  • Hibernate/JPA: 熟练掌握对象关系映射 (ORM) 工具,用于数据库交互。

3. 前端技术

  • HTML/CSS: 牢固掌握创建结构化和样式化的网页。
  • JavaScript: 掌握核心语言技能,用于添加交互性。
  • 现代 JavaScript 框架/库: 熟悉 Angular、React 或 Vue.js 等框架,用于构建动态的用户界面。
  • 响应式设计: 使用 CSS 框架(如 Bootstrap)创建可在各种设备和屏幕尺寸上运行的应用程序。

4. Web 开发概念

  • HTTP/HTTPS 协议: 了解 Web 通信的工作原理。
  • RESTful 服务: 设计和消费 RESTful API。
  • 身份验证与授权: 实现 OAuth、JWT 和会话管理等安全措施。

5. 数据库管理

  • SQL 和 NoSQL 数据库: 熟练使用 MySQL、PostgreSQL、MongoDBOracle 和 Redis 等数据库。
  • 数据库设计: 理解规范化、索引和事务。

6. 版本控制系统

  • Git: 熟练使用 Git 仓库进行版本控制和协作。

7. 开发工具

  • IDE: 熟悉 IntelliJ IDEA、Eclipse 或 Visual Studio Code 等集成开发环境。
  • 构建工具: 了解 Maven 或 Gradle 等构建自动化工具。

8. DevOps

  • 持续集成/持续部署 (CI/CD): 熟悉 Jenkins、Docker 和 Kubernetes 等工具,用于自动化部署流程。
  • 云服务: 对 AWS、Azure 或 Google Cloud 等云平台有基本了解,用于部署应用程序。

9. 软技能

  • 解决问题能力: 强大的分析和故障排除能力。
  • 沟通能力: 与团队成员和利益相关者有效沟通的能力。
  • 敏捷方法: 有在敏捷环境中工作的经验,理解 Scrum 或 Kanban 实践。

2) 什么是 MVC 和 MVP?MVC 与 MVP 有何不同?

MVC 和 MVP 都是用于开发应用程序的架构模式。

MVC

MVC 代表**模型-视图-控制器**。它是一种用于开发 Java 企业应用程序的架构模式。它将应用程序分为三个逻辑组件:**模型、视图**和**控制器**。它将特定于业务的逻辑(模型组件)与表示层(视图组件)相互分离。

模型组件包含与其相关的数据和逻辑。视图组件负责在用户界面中显示模型对象。控制器接收输入,并根据处理程序映射调用模型对象。它还将模型对象传递给视图,以便在视图层中显示输出。

Full-Stack Developer Interview Questions Java

MVP

MVP 代表**模型-视图-呈现器**。它源自 MVC 架构模式。它在架构模式中增加了一个额外的层(称为间接层),将视图和控制器分成视图和呈现器。控制器的角色被呈现器取代。它与 MVC 中的视图处于同一级别。它包含视图的 UI 业务逻辑。从视图接收的调用会直接发送给呈现器。它维护视图和模型之间的操作(事件)。呈现器不直接与视图通信。它通过接口进行通信。

Full-Stack Developer Interview Questions Java

MVCMVP 架构模式之间的主要区别在于,在 MVC 架构模式中,控制器不将数据从模型传递给视图。它只通知视图自行从模型获取数据。

而在 **MVP** 架构模式中,视图和模型层是相互连接的。呈现器本身从模型接收数据,并将其发送给视图进行显示。

另一个区别是 MVC 通常用于 Web 框架,而 MVP 用于应用程序开发。

Full-Stack Developer Interview Questions Java

3) 什么是结对编程?

结对编程是一种敏捷软件开发技术,其中两个程序员在一个工作站上协同工作。一名程序员担任“驾驶员”,负责**编写**代码,而另一名程序员担任“**观察员**”或“**导航员**”,负责在代码输入时**审查**每一行代码。两名程序员会频繁地交换角色。

驾驶员可能专注于实现核心 Java 功能或设置 Spring Boot 项目,而导航员则提供有关最佳实践的见解,确保遵守设计模式,或提出改进建议。对于前端开发,一个人可能专注于用 Angular 或 React 编码,而另一个人则检查最佳的 UI/UX 设计和跨浏览器兼容性。这种编程技术更有效率,可以将编码错误降至最低。结对编程的缺点是会增加成本。

结对编程有助于确保前端和后端组件都得到良好的集成,并在整个开发过程中保持应用程序的高质量标准。


4) MVC 中的 CORS 是什么?它是如何工作的?

CORS 代表**跨源资源共享**。它是一种 **W3C** 标准和基于 HTTP 头的机制。它允许服务器指示除请求之外的任何其他源(如域、端口等)。换句话说,它允许一个网站使用 JavaScript 访问另一个网站的资源。

它支持安全的跨源请求,并在服务器和浏览器之间传输数据。高级浏览器在 API 中使用 CORS。与 JSONP(填充式 JSON)相比,它更灵活、更安全。它提供了更好的 Web 服务集成。

Full-Stack Developer Interview Questions Java

在使用 MVC 实现 CORS 时,可以使用相同的 CORS 服务,但不能使用相同的 CORS 中间件。我们可以为特定操作、特定控制器以及全局所有控制器使用特定的 CORS。

浏览器会向服务器(托管跨源资源的服务器)发送一个预检请求,以确保服务器允许实际请求。例如,通过 https://demo.com 调用 URL https://example.com

Full-Stack Developer Interview Questions Java

5) 如何提高网站的可伸缩性和效率?

提高网站的可伸缩性和效率涉及优化其设计和实现的各个方面。以下是对每种方法的说明:

减少 DNS 查找

DNS 查找可能非常耗时,因为浏览器在加载资源之前需要将域名解析为 IP 地址。减少网站上使用的唯一域名数量可以最大程度地减少所需的 DNS 查找次数,从而加快加载过程。

避免 URL 重定向

URL 重定向会引入额外的 HTTP 请求并增加延迟,从而减慢页面加载时间。最小化或消除重定向可确保用户能够更快、更有效地访问所需资源。

避免重复代码

重复的代码会膨胀网页,导致加载时间变慢和处理时间增加。确保每段功能或样式只定义一次,可以减少浏览器需要解析和执行的代码量,从而提高整体性能。

避免不必要的图片

大型或过多的图片会显著减慢网站速度。通过仅使用必需的图片,优化其大小和格式,并利用懒加载等技术,可以提高网站的加载时间和性能。

利用浏览器缓存

浏览器缓存会将网站的一部分(如图片、样式表和脚本)存储在用户的设备上。当用户再次访问网站时,可以从缓存加载这些资源,而无需再次下载,从而大大缩短加载时间并减轻服务器负载。

延迟 JavaScript 解析

JavaScript 的解析和执行会阻塞网页的渲染。通过在初始页面加载后延迟 JavaScript 的解析,可以更快地显示主要内容,从而提高用户感知的加载时间。

避免内联 JavaScript 和 CSS

内联 JavaScript 和 CSS 会增加 HTML 文档的大小,并阻止浏览器有效地缓存这些资源。将 JavaScript 和 CSS 分离到外部文件中,可以使浏览器在不同页面之间缓存和重用它们,从而缩短加载时间。

使用 srcset 实现响应式图片

srcset 属性允许开发人员为不同的屏幕尺寸和分辨率指定不同的图像源。这可确保浏览器下载最适合用户设备的图像,从而提高加载时间并减少不必要的数据传输。

将所有资源放在无 Cookie 域上,最好使用 CDN

Cookie 会为每个 HTTP 请求添加额外数据,从而减慢静态资源的传输速度。从无 Cookie 域提供资源可避免此开销。此外,使用内容分发网络 (CDN) 将资源放置在离用户更近的服务器上,可以减少延迟并提高加载时间。CDN 还有助于分发负载,提高网站的可伸缩性。

通过实施这些优化技术,您可以显著提高网站的可伸缩性和效率,从而获得更快的加载时间、更好的用户体验,并能够处理更多的流量。


6) Get 和 Post 请求之间有什么区别?

序号比较基础GetPost
1目的Get 请求用于**从服务器获取**数据。Post 请求用于**将数据发送到服务器**。
2Post 机制请求通过**URL**发送。请求通过**HTTP 请求体**发送。
3参数传递请求参数作为**查询字符串**传递,附加在请求后面。请求参数随请求的**主体**一起传递。
4默认它是**默认**方法,因此会自动实现。我们需要**手动**指定。
5容量我们可以使用 Get 请求发送**有限**的数据。我们可以使用 Post 请求发送**大量**数据。
6数据类型它总是以**文本**形式提交数据。我们可以发送**任何类型**的数据。
7安全性Get 的使用是**安全**的,因为它是幂等的。Post 的使用是**不安全**的,因为它不是幂等的。
8数据可见性数据对用户是**可见**的,因为它将数据放在 URL 中。数据对用户是**不可见**的,因为它将数据放在消息体中。
9书签和缓存Get 请求可以**添加书签**并**缓存**。Post 请求不能**添加书签**和**缓存**。
10效率它比 Post **更有效率**。它**效率较低**。
11示例**搜索**是 Get 请求的最佳示例。**登录**是 Post 请求的最佳示例。

7) 函数式编程中的引用透明性是什么意思?

如果程序中任何两个具有相同值的表达式可以被替换到程序中的任何位置而不会改变程序的运行结果,那么该程序就具有引用透明性。它用于函数式编程。例如,考虑以下代码片段

如果 fun(x) 的值没有被反映出来,变量 **count1** 和 **count2** 将相等。如果 count1 和 count2 不相等,则违反了引用透明性。


8) 什么是 RESTful API?

REST 代表表征状态转移 (Representational State Transfer)。它是一种用于创建Web 服务的架构风格。它使用 HTTP 请求来访问和使用数据。我们可以创建、更新、读取和删除数据。

网站的 API(应用程序编程接口)是允许两个软件程序相互通信的代码。它允许我们请求操作系统或其他应用程序的服务。

RESTful API 的关键特性

  • 无状态性: 客户端到服务器的每个 HTTP 请求都必须包含理解和处理该请求所需的所有信息。服务器在请求之间不存储任何客户端上下文。
  • 统一接口: API 使用标准的 HTTP 方法和状态码,使开发人员更容易理解和使用。
  • 可伸缩性: 无状态性和缓存提高了服务器的可伸缩性。
  • 可缓存性: 响应必须明确指示是否可以缓存。

RESTful 示例

电子商务应用程序

在电子商务应用程序中,RESTful API 可以管理产品、客户和订单。

  • GET /products:检索所有产品的列表。
  • POST /products:创建新产品。
  • GET /products/{id}:按 ID 检索特定产品。
  • PUT /products/{id}:按 ID 更新特定产品。
  • DELETE /products/{id}:按 ID 删除特定产品。

社交媒体平台

对于社交媒体平台,RESTful API 可以管理用户、帖子和评论。

  • GET /users:检索所有用户的列表。
  • POST /users:创建新用户。
  • GET /users/{id}:按 ID 检索特定用户。
  • PUT /users/{id}:按 ID 更新特定用户。
  • DELETE /users/{id}:按 ID 删除特定用户。
  • GET /posts:检索所有帖子的列表。
  • POST /posts:创建新帖子。
  • GET /posts/{id}:按 ID 检索特定帖子。

9) 什么是 Promise,也请解释它的状态?

Promise 是一个对象,它可以从异步函数同步返回。它可能有以下三种状态:

  • Fulfilled(已完成):如果 Promise 调用了 onFulfilled() 方法,则 Promise 将处于已完成状态。
  • Rejected(已拒绝):如果 Promise 调用了 onRejceted() 方法,则 Promise 将处于已拒绝状态。
  • Pending(待定):如果 Promise 尚未完成或被拒绝,则 Promise 将处于待定状态。

当且仅当 Promise 未处于待定状态时,它才会被结算(settled)。


10) 如何减少 Web 应用程序的加载时间?

优化 Web 应用程序的加载时间对于提供流畅的用户体验至关重要。

  1. 优化图片大小和格式:使用图片压缩技术并选择合适的图片格式(例如,JPEG、PNG、SVG),在不影响质量的情况下减小文件大小。这可以最大限度地减少下载图片所需的时间。
  2. 压缩和优化内容:在服务器上启用 GZIP 压缩,以减小 CSS、JavaScript、HTML 和其他文本内容的大小。这可以减少网络传输的数据量,从而加快加载速度。
  3. 避免重定向:最小化或消除不必要的 URL 重定向,因为每次重定向都会增加页面加载过程的时间。确保 URL 直接指向最终目的地,以避免不必要的 HTTP 请求。
  4. 缓存网页:实施浏览器缓存和服务器端缓存机制,以存储静态资源,如图片、CSS 和 JavaScript 文件。缓存可以减少重复下载的需求,从而加快返回访问者的加载速度。
  5. 最小化 HTTP 请求:通过合并和最小化 CSS 和 JavaScript 文件,以及减少字体和脚本等外部资源的数量,来减少 HTTP 请求的数量。更少的 HTTP 请求可以加快页面加载速度。
  6. 优化依赖项:定期更新和精简依赖项(如库、框架和插件),以确保它们轻量级且经过性能优化。删除未使用的或不必要的依赖项以减少开销。
  7. 将样式表引用放在顶部:将 CSS 样式表引用放在 HTML 文档的 部分,以启用渐进式渲染。这可确保样式尽早应用于页面,从而防止出现令人讨厌的 FOUC(无样式内容闪烁)。
  8. 将脚本引用放在底部:将 JavaScript 脚本引用放在 HTML 文档的底部,就在 closing
  9. 将 JavaScript 和 CSS 放在外部:将 JavaScript 和 CSS 文件外部化,以利用浏览器缓存。这允许浏览器单独缓存这些资源,从而缩短后续页面访问的加载时间。

通过实施这些优化技术,我们可以显著减少 Web 应用程序的加载时间,从而提高用户满意度和参与度。


11) 什么是持续集成和持续交付 (CI/CD)?

CI/CD 是一种最佳实践,用于开发应用程序,其中代码更改更加频繁和快速。有时,它也被称为**CI\CD 流水线**。它广泛用于 DevOps,也是一种敏捷方法。

持续集成是一种编码理念或部署实践,其中开发人员每天多次将他们的代码集成到共享存储库中。因为现代应用程序需要在不同的平台上开发代码。持续集成的目标是建立一个自动化机制来构建、测试和打包应用程序。

持续交付从 CI 结束的地方开始。它会自动将应用程序交付给选定的基础设施。CD 确保在代码发生任何更改时都能自动交付代码。


12) 设计应用程序最常使用的架构设计有哪些?

理解不同的架构设计模式对于创建健壮、可伸缩且可维护的软件应用程序至关重要。

1. 模型-视图-控制器 (MVC)

  • 模型:代表应用程序的数据和业务逻辑。它处理数据检索、存储和操作。
  • 视图:用户界面组件,用于向用户显示数据。它以特定格式呈现模型的数据。
  • 控制器:作为模型和视图之间的中间件。它处理用户输入,更新模型,并确定显示哪个视图。

示例

使用 Spring MVC(在 Java 中)等 Web 应用程序,其中控制器处理 HTTP 请求,模型代表数据实体,视图将数据呈现给用户。

2. 主从模式 (Master-Slave Pattern)

  • 主:控制系统,分配任务给从属,并处理结果。
  • 从:执行主分配的实际计算或任务。多个从属可以并行工作以提高性能和可靠性。

示例

数据库复制,其中主数据库处理所有写入并将更改传播到从数据库,从数据库处理读取请求。

3. 分层模式 (Layered Pattern)

  • 表示层:处理用户界面和用户交互。
  • 应用程序层:管理应用程序特定的逻辑和数据处理。
  • 业务逻辑层:包含应用程序的核心功能和业务规则。
  • 数据访问层:与数据库或数据存储系统交互。

示例

具有用户界面、业务逻辑和数据访问等独立层的企业应用程序,例如使用 Java EE 平台构建的应用程序。

4. 模型-视图-呈现器 (MVP)

  • 模型:与 MVC 类似,它处理数据和业务逻辑。
  • 视图:将数据呈现给用户,并将用户操作发送给呈现器。
  • 呈现器:作为视图和模型之间的中间件。它从模型检索数据,进行处理,并更新视图。

示例

桌面应用程序和 Android 应用程序,其中呈现器处理用户输入并相应地更新视图。

5. 单体架构 (Monolithic Architecture)

一个单一的、统一的应用程序,其中所有组件都相互连接和相互依赖。这是一种传统的模型,整个应用程序作为一个单元进行开发和部署。

示例

小型到中型应用程序,其中将整个系统作为一个单元进行部署和扩展是可行的,例如 Web 应用程序的早期版本。

6. 事件驱动架构模式 (Event-Driven Architecture Pattern)

  • 事件生产者:根据操作或状态更改生成事件。
  • 事件消费者:监听并响应事件。它们会采取行动或触发其他进程以响应事件。
  • 事件通道:促进生产者和消费者之间的通信。

示例

实时系统,如股票交易平台或物联网应用程序,其中来自传感器的事件会立即得到处理和响应。

通过利用这些架构设计模式,软件开发人员可以构建有组织、可维护且可扩展的应用程序,每种模式都适合不同类型的应用程序和项目需求。


13) 什么是长轮询?

长轮询是一种有效的创建稳定服务器连接的方法,而无需使用 WebSocket 或服务器端事件协议。它运行在传统的客户端-服务器模型的顶层。请注意,Node.js 正在使用相同的技术作为下一个开发模型。

在这种方法中,客户端发送请求,服务器在连接打开期间响应,直到包含新颖的独特信息。一旦服务器响应,就可以提交对客户端的请求。当数据可用时,服务器将返回一个查询。当客户端应用程序停止并且服务器结束请求时,它就会起作用。


14) 解释语义 HTML 的含义,举例说明,以及我们为什么要使用它?

在网页设计中,使用 HTML 元素来指示它们实际含义的想法。它被称为语义 HTML 或**语义标记**。

语义 HTML 是表示网页含义而非仅表示呈现的 HTML。例如,<p> 标签表示其中包含一个段落。它既是语义的也是呈现的,因为用户知道段落是什么,浏览器也知道如何显示它们。另一方面,像 <b><i> 这样的标签不是语义的。它们只表示文本的外观。这些标签不为标记提供任何附加含义。

语义 HTML 标签的示例是**标题标签** <h1> 到 <h6><abbr><cite><tt><code><blockquote><em> 等。还有一些其他的语义 HTML 标签用于构建符合标准的网站。

我们应该出于以下原因使用语义 HTML:

  • 它提供了关于其使用的文档的额外信息。它也有助于沟通。
  • 语义标签使浏览器清楚地了解页面的含义及其内容。
  • 它提供了关于这些标签内容的,超越了它们在页面上外观的信息。
  • 它为我们提供了更多用于设置页面内容样式的钩子。
  • 语义标签的清晰度也传达给搜索引擎,以确保正确的结果集用于正确的查询。

15) JavaScript 中的 null 与 undefined 有何区别?

Null:Null 表示一个变量被赋值为**null** 值。如果将其与typeof 运算符一起使用,它会返回**object** 作为结果。我们不应该将变量赋值为 null,因为程序员使用它来表示一个没有值的变量。请注意,JavaScript 永远不会自动将值赋给 null。

Undefined:Undefined 表示变量已声明但未为其分配任何值。它可能是变量本身不存在。如果将其与 typeof 运算符一起使用,它将返回 undefined 的结果。它在 JSON 中无效。

注意:Null 和 undefined 都是原始类型。

让我们通过一个例子来理解。

执行上述代码时,会生成以下输出:

从上面的输出中,我们可以观察到 var1 的值为 undefined,其类型也为 undefined。因为我们没有为变量 var1 赋值。值 null 被赋给了变量 var2。它打印其类型为 object。由于 null 是一个赋值值,我们可以将其赋值给一个变量。因此,JavaScript 将 null 和 undefined 相对平等地对待,因为它们都代表一个空值。


16) GraphQL 与 REST 的主要区别是什么?

REST 和GraphQL都是 API 设计架构,可用于开发 Web 服务,尤其适用于数据驱动的应用程序。

GraphQLREST
GraphQL 是一种 API 设计架构,但它采用了更灵活的方法。REST 是一种健壮的方法和 API 设计架构,用于实现 Web 服务。
它遵循**客户端驱动**架构。它遵循**服务器驱动**架构。
它不处理专用资源。它处理专用资源。
它有一个**单一**的端点,接受动态参数。它有**多个**端点。
它提供**无状态**服务器和**结构化**的资源访问。它提供**无状态**服务器和**灵活**的受控资源访问。
它本质上是**弹性的**。它本质上**不僵化**。
它仅支持**JSON** 格式。它还支持XMLJSON、HTML、YAML 等格式。
客户端通过**查询**语言定义其所需的响应数据。数据通过**URI** 表示为 HTTP 上的资源。
它在多种协议(如**HTTP**、MQTT**、AMQP**)中提供**同步**和**异步**通信。它仅通过**HTTP** 提供**同步**通信。
其设计基于**HTTP**(状态、方法和 URI)。其设计基于**消息交换**。
它在所有平台上提供**高**一致性。在所有平台上实现高一致性很困难。
开发速度**快**。开发速度**慢**。

17) 比较 fail-fast 和 fail-safe 迭代器?

比较基础快速失败迭代器安全失败迭代器
操作它**直接**在集合本身上操作。它在集合的**克隆副本**上操作。
Exception在迭代过程中修改对象时,它会抛出 ConcurrentModificationException。它不抛出异常。
克隆对象在迭代过程中不创建克隆对象。在迭代过程中创建副本或克隆对象。
内存利用此过程需要低内存。此过程需要更多内存。
修改它不允许在迭代期间修改。它允许在迭代期间修改。
性能它很快。它比快速失败稍慢。
示例HashMapArrayListVectorHashSet 等。CopyOnWriteArrayListConcurrentHashMap 等。

18) Java 中的连接泄漏是什么?我们该如何修复它?

在 Java 中,连接泄漏是指开发人员忘记关闭 JDBC 连接的情况。这是最常见的 Java 开发中遇到的连接泄漏类型,特别是在使用连接池(如 DBCP)时。我们可以通过关闭连接和特别注意错误处理代码来修复它。


19) Servlet 中有哪些不同的会话管理方法?

会话是客户端和服务器之间的对话状态,可以包含客户端和服务器之间的多个请求和响应。因此,HTTP 和 Web 服务器都是无状态的,维持会话的唯一方法是将有关会话的唯一信息(会话 ID)在每个请求和响应之间传递。我们可以使用以下方法来维护会话:

1. 用户身份验证:用户身份验证涉及根据凭据(用户名和密码)验证用户的身份。成功验证后,用户的会话会通过会话令牌或 Cookie 来维持。

工作原理:成功登录后,服务器会生成一个会话令牌并将其发送给客户端。此令牌包含在后续请求中以维护会话。可以使用 HTTP 基本身份验证、基于表单的身份验证或 OAuth 等身份验证机制。

2. HTML 隐藏字段:HTML 表单中的隐藏字段可用于在客户端和服务器之间存储和发送会话信息。

工作原理:将隐藏字段添加到具有会话特定数据的 HTML 表单中。提交表单时,隐藏数据将连同可见表单数据一起发送回服务器,允许服务器识别会话。

局限性:此方法仅限于使用表单的场景,并且需要谨慎处理以避免安全问题(如篡改)。

3. Cookie:Cookie 是存储在客户端的小块数据,并在每个 HTTP 请求中发送到服务器。

工作原理:服务器创建一个会话 ID,并通过 Cookie 发送给客户端。客户端存储 Cookie,并在后续请求中包含它。服务器使用 Cookie 中的会话 ID 来检索会话信息。

优点:Cookie 是自动的,并且可以透明地工作,而无需更改 URL 或表单。

局限性:用户可以在其浏览器中禁用 Cookie,这可能会影响会话管理。

4. URL 重写:URL 重写涉及将会话信息附加到 Web 资源的 URL。

工作原理:会将会话 ID 作为查询参数附加到应用程序的 URL 中。例如,http://example.com/page?sessionid=12345。每个请求都包含 URL 中的会话 ID,允许服务器跟踪会话。

优点:即使禁用了 Cookie 也能正常工作。

局限性:需要修改 URL 并确保在所有链接和表单中都包含会话 ID。它还可能在浏览器历史记录和日志中暴露会话 ID。

5. 会话管理 API:Java Servlet API 通过 HttpSession 接口提供对会话管理的内置支持。

工作原理:当客户端发出请求时,服务器会检查会话是否存在。如果不存在,则创建一个新会话,并分配一个唯一的会话 ID,该 ID 通过 Cookie 或 URL 重写发送给客户端。服务器使用会话 ID 来检索和管理会话数据。

优点:通过提供创建、访问和使会话无效的标准方法,简化了会话管理。它抽象了用于维护会话的底层机制(Cookie、URL 重写)。


20) ServletContext 与 ServletConfig 有何区别?

ServletContextServletConfig
ServletContext 代表运行在特定JVM上的整个 Web 应用程序,并且对所有 Servlet 都是通用的。ServletConfig 对象代表单个 Servlet。
它就像一个与整个应用程序关联的全局参数。它就像一个与特定 Servlet 关联的局部参数。
它具有应用程序范围的作用域,因此在 web.xml 文件中的 servlet 标签之外定义。它在 web.xml 文件中的 servlet 部分内定义为键值对,因此它具有 Servlet 范围的作用域。
getServletContext() 方法用于获取上下文对象。getServletConfig() 方法用于获取配置对象。
获取文件的 MIME 类型或与应用程序会话相关的信息是使用 ServletContext 对象存储的。用户的购物车特定于特定用户,因此在这里我们可以使用 ServletConfig。

21) 什么是 RequestDispatcher?

RequestDispatcher 是一个接口,用于将请求转发到应用程序中可以成为HTMLJSP 或另一个Servlet 的另一个资源。我们还可以使用它将另一个资源的内容包含在响应中。该接口包含 forward() 和 include() 两个方法。

RequestDispatcher 类的常用方法

forward() 方法

语法

目的:将当前 Servlet 的请求转发到另一个资源以进行进一步处理。目标资源接管请求处理。

用法:通常在目标资源需要完全处理请求时使用,例如将请求委托给另一个 Servlet 进行专门处理。

include() 方法

语法

目的:将另一个资源的内容包含在当前响应中。在包含的内容处理完成后,控制权将返回给调用 Servlet 以继续处理。

用法:适用于将内容(如页眉、页脚或导航栏)动态包含到响应中。

Full-Stack Developer Interview Questions Java

22) 构造函数注入和 setter 注入之间有什么区别?

构造器注入Setter 注入
没有部分依赖注入。可以进行部分依赖注入。
如果两者都已定义,它不会覆盖 setter 注入的值。如果两者都已定义,它会覆盖构造函数注入的值。
如果发生任何修改,它将始终创建一个新实例。如果我们对它进行了任何更改,它不会创建新实例。
使用构造函数注入对于许多属性来说更好。使用setter 注入对于少数属性来说更好。
它使 bean 类对象不可变。它使 bean 类对象可变。

23) Spring MVC 框架中有多少种处理异常的方法?

Spring MVC 框架提供以下几种处理异常的方法:

  • 基于控制器:我们可以在控制器类中定义异常处理方法。
  • 全局异常处理:异常处理Spring 中一项横切关注点。
  • HandlerExceptionResolver:DispatcherServlet 的应用程序上下文中声明的任何实现 HandlerExceptionResolver 的 Spring Bean 都将用于拦截和处理 MVC 系统中抛出且未被控制器处理的任何异常。

24) Hibernate 相较于 JDBC 有哪些优势?

Hibernate 相较于JDBC 有以下优势:

  • Hibernate 删除了 JDBC API 附带的样板代码。
  • 它支持继承、关联和集合,而 JDBC API 不支持这些。
  • 它隐式地提供事务管理
  • 我们不需要编写大量的try-catch 块代码。
  • 在 Hibernate 中,HQL 更面向对象,更接近 Java 编程语言。
  • 与 JDBC 相比,它提供了更好的性能,因为 Hibernate 支持缓存,而 JDBC 不支持查询缓存。

25) 什么是回调地狱?如何解决它?

回调地狱是 JavaScript 中一种现象,在这种现象中,开发人员试图一起执行多个异步操作。嵌套回调函数的方式,使代码容易出错、难以阅读且难以维护。

我们可以通过以下方法轻松解决它:

将大型函数分解为小型函数

  • 将大型、复杂的函数分解为更小、更易于管理的函数。这有助于通过将代码组织成逻辑单元来提高代码的可读性和可维护性。
  • 使用模块化将特定任务或操作封装到单独的函数中,使代码更易于理解和维护。

使用 Promise

  • Promise 提供了一种更清晰、更结构化的方式来处理 JavaScript 中的异步操作。
  • 而不是嵌套回调,我们可以使用 then() 链接 Promise 来按顺序处理异步任务。
  • Promise 通过 catch() 方法提供更好的错误处理,允许我们集中处理错误。

使用Async/Await

  • Async/await 是一项现代 JavaScript 功能,可以进一步简化异步代码。
  • 它允许我们以同步风格编写异步代码,使其更容易理解和维护。
  • 通过将函数标记为 async,我们可以使用 await 关键字暂停执行,直到 Promise 被解析或拒绝,从而无需使用回调函数。

26) Java 中的双花括号初始化是什么?在哪里使用?

在 Java 中,双花括号初始化是两个独立过程的组合。其中涉及两个连续的花括号 **{{**。

第一个花括号代表**匿名内部类**的创建。请记住,在这种情况下,第二个花括号将不被考虑。这就像创建一个匿名内部类

第二个花括号代表我们已经在类中看到的**初始化块**,用于初始化。当我们为匿名内部类使用初始化块时,它就变成了 Java 双花括号初始化。该内部类有一个指向外部类的引用。我们可以使用 **this** 指针来引用。

它用于初始化集合,因为使用双花括号初始化更容易初始化常量集合。双花括号初始化的示例如下:


27) 如何避免 Java 中的死锁?

避免不必要的锁:我们应该只在需要时才使用锁。不必要的锁使用会导致死锁情况。建议使用无锁数据结构。如果可能,保持代码无锁。例如,不要使用同步的ArrayList,而是使用ConcurrentLinkedQueue

避免嵌套锁:另一种避免死锁的方法是,如果我们已经将锁分配给一个线程,就不要将锁分配给多个线程。因为我们必须避免将锁分配给多个线程。

使用 Thread.join() 方法:如果两个线程无限期地等待对方完成,我们可能会遇到死锁。如果一个线程必须等待另一个线程完成,最好使用 join 并设置您希望等待线程完成的最大时间。

使用锁顺序:始终为每个锁分配一个数字值。在获取具有较高数字值的锁之前,先获取具有较低数字值的锁。

锁超时:我们还可以为线程获取锁指定时间。如果线程未能获取锁,它必须等待特定时间,然后重试获取锁。


28) 什么是临界区?

临界区是多线程中的一段代码,必须由任何线程独占修改。临界区受到信号量或互斥锁的保护。在 Java 中,有两种方法可以保护临界区:

  • 使用Synchronized关键字:synchronized 关键字提供内置锁定,允许一次只有一个线程执行 synchronized 块或方法。这确保了线程安全,并防止共享资源的并发访问,从而保护临界区免受并发修改。
  • 使用Reentrant 锁ReentrantLock 类提供显式锁定机制,允许更精细地控制锁定和解锁。它提供了诸如中断锁和超时等功能,与 synchronized 块相比提供了更大的灵活性。Reentrant 锁通过一次只允许一个线程获取锁来保护临界区,确保独占访问和线程安全。

29) 什么是数值提升?

将较小的数值类型转换为较大的数值类型称为**数值提升**。在这种类型中,byte、char 和 short 值将转换为 int 值。int 值在必要时将转换为 long 值。long 和 float 值在需要时将转换为 double 值。


30) Java 中的 SOLID 原则是什么?

在 Java 中,SOLID 原则是一种面向对象的概念,应用于软件结构设计。它由**Robert C. Martin**(也称为**Uncle Bob**)构思。这五项原则改变了面向对象编程的世界,也改变了编写软件的方式。它还确保软件是模块化的,易于理解、调试和重构。

SOLID 首字母缩写代表:

  • 单一职责原则 (SRP):类应该只有一个改变的原因,确保它们是专注且可维护的。此原则促进高内聚和低耦合,从而更容易理解和修改单个组件。
  • 开闭原则 (OCP):软件实体应该对扩展开放,对修改关闭。通过设计可以扩展而无需更改其核心功能的类,代码库变得更加灵活和更能抵抗变化。
  • 里氏替换原则 (LSP):子类型应该可以被替换为其基类型,而不会影响程序的正确性。此原则确保多态性按预期运行,并且派生类遵守基类定义的契约。
  • 接口隔离原则 (ISP):客户端不应被迫依赖于他们不使用的接口。通过将接口分成更小、更具体的接口,此原则可以防止不相关的组件耦合,并促进更清晰、更易于维护的代码。
  • 依赖倒置原则 (DIP):依赖倒置原则 (DIP):高层模块不应依赖于低层模块。两者都应依赖于抽象,从而促进松散耦合,并使代码库更灵活,更易于测试和维护。