0

0

Jetty 服务器 404 错误诊断与 Servlet 上下文处理器配置详解

心靈之曲

心靈之曲

发布时间:2025-11-23 15:07:01

|

738人浏览过

|

来源于php中文网

原创

Jetty 服务器 404 错误诊断与 Servlet 上下文处理器配置详解

本文旨在解决 jetty 服务器启动后出现 404 not found 错误的问题。核心在于正确配置和关联 servletcontexthandler 与 server 实例。许多开发者在初始化 servletcontexthandler 后,忘记将其附加到 server 上,导致请求无法被正确路由。教程将详细解释如何通过 server.sethandler(handler); 方法确保 servlet 上下文处理器被服务器识别并处理传入的请求,从而避免 404 错误,确保应用程序正常运行。

1. Jetty 404 Not Found 错误概述

在使用 Jetty 构建 Web 应用程序时,开发者可能会遇到服务器启动成功但访问特定路径时返回 404 Not Found 错误的情况。这通常意味着 Jetty 服务器未能将传入的请求路由到正确的处理程序(Handler)或 Servlet。当请求到达服务器时,Jetty 会尝试根据其配置的处理器链来匹配请求路径。如果没有任何处理器被配置来处理该路径,或者处理器虽然存在但未被正确地附加到服务器实例上,那么服务器就无法找到对应的资源,从而返回 404 状态码

2. 核心问题:处理器未附加到服务器

在 Jetty 的架构中,Server 实例是核心,它负责监听端口、接收连接并分派请求。而具体的请求处理逻辑,例如 Servlet 上下文、静态文件服务等,都是通过各种类型的 Handler 来实现的。ServletContextHandler 是一种常见的 Handler,用于定义一个 Web 应用程序的上下文,包括其上下文路径、Servlet 映射等。

许多开发者在初始化 ServletContextHandler 后,可能会遗漏一个关键步骤:将其附加到 Server 实例上。以下是一个常见的错误示例代码片段:

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;

public class MyJettyApp {
    public static void main(String[] args) throws Exception {
        Server server = new Server(8080); // 创建 Jetty 服务器实例

        // 创建 ServletContextHandler,并指定上下文路径
        ServletContextHandler handler = new ServletContextHandler(server, "/example");

        // 配置 Jersey ResourceConfig
        ResourceConfig config = new ResourceConfig();
        config.packages("api"); // 扫描 'api' 包下的 JAX-RS 资源
        // config.register(new CORSConfig()); // 假设有一个CORS配置

        // 创建 ServletHolder,包装 Jersey ServletContainer
        ServletHolder holder = new ServletHolder(new ServletContainer(config));
        // 将 ServletHolder 映射到 /api/* 路径
        handler.addServlet(holder, "/api/*");

        // !!! 错误点:这里缺少将 handler 附加到 server 的代码 !!!

        try {
            server.start(); // 启动服务器
            server.join();  // 阻塞主线程,直到服务器停止
        } finally {
            server.stop();    // 停止服务器
            server.destroy(); // 销毁服务器资源
        }
    }
}

在上述代码中,ServletContextHandler 被创建,并且其内部配置了 Jersey Servlet,但这个 handler 实例并没有被告知给 server 实例。因此,当请求到达 localhost:8080/api 或 localhost:8080/example/api 时,Jetty 服务器并不知道应该由哪个处理器来处理这些请求,最终导致 404 错误。

3. 正确配置 Jetty Servlet 上下文处理器

解决上述 404 问题的关键在于,在 server.start() 之前,明确地将 ServletContextHandler 附加到 Server 实例上。这可以通过调用 server.setHandler(handler); 方法来实现。

PathFinder
PathFinder

AI驱动的销售漏斗分析工具

下载

修正后的代码示例如下:

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;

public class MyJettyApp {
    public static void main(String[] args) throws Exception {
        Server server = new Server(8080); // 创建 Jetty 服务器实例

        // 创建 ServletContextHandler,并指定上下文路径
        // 注意:这里的上下文路径是针对整个 Web 应用的根路径,例如 "/example"
        ServletContextHandler handler = new ServletContextHandler(ServletContextHandler.SESSIONS);
        handler.setContextPath("/example"); // 设置上下文路径

        // 配置 Jersey ResourceConfig
        ResourceConfig config = new ResourceConfig();
        config.packages("api"); // 扫描 'api' 包下的 JAX-RS 资源
        // config.register(new CORSConfig()); // 假设有一个CORS配置

        // 创建 ServletHolder,包装 Jersey ServletContainer
        ServletHolder holder = new ServletHolder(new ServletContainer(config));
        // 将 ServletHolder 映射到 /api/* 路径
        // 注意:这里的 /api/* 是相对于上下文路径 /example 的,
        // 所以最终访问路径是 /example/api/*
        handler.addServlet(holder, "/api/*");

        // !!! 关键修正:将 handler 附加到 server !!!
        server.setHandler(handler);

        try {
            server.start(); // 启动服务器
            server.join();  // 阻塞主线程,直到服务器停止
        } finally {
            server.stop();    // 停止服务器
            server.destroy(); // 销毁服务器资源
        }
    }
}

代码解释:

  1. Server server = new Server(8080);: 初始化 Jetty 服务器,监听 8080 端口。
  2. ServletContextHandler handler = new ServletContextHandler(ServletContextHandler.SESSIONS);: 创建一个 ServletContextHandler 实例。ServletContextHandler.SESSIONS 参数表示启用会话管理
  3. handler.setContextPath("/example");: 为此 Web 应用程序设置上下文路径。这意味着所有属于此 handler 的 Servlet 都将以 /example 作为其 URL 的前缀。例如,如果 Servlet 映射到 /api/*,则完整的访问路径将是 /example/api/*。
  4. ResourceConfig config = new ResourceConfig(); config.packages("api");: 这是 Jersey (JAX-RS) 的配置部分,用于告诉 Jersey 在哪个包中查找 RESTful 资源类。
  5. ServletHolder holder = new ServletHolder(new ServletContainer(config));: 创建一个 ServletHolder,它是一个 Servlet 的包装器。这里包装的是 Jersey 的 ServletContainer,它是处理 JAX-RS 请求的核心 Servlet。
  6. *`handler.addServlet(holder, "/api/");**: 将ServletHolder添加到ServletContextHandler中,并将其映射到/api/*路径。这意味着任何以/example/api/` 开头的请求都将由这个 Jersey Servlet 处理。
  7. server.setHandler(handler);: 这是解决 404 问题的关键行。 它告诉 Jetty 服务器,当有请求到来时,应该使用这个 handler 来处理。Server 实例可以接受一个或多个 Handler。如果只有一个主 Handler,可以直接使用 setHandler()。

4. 关键概念解析

  • Server: Jetty 服务器的顶层实例,负责网络连接、线程池管理以及将请求分派给合适的处理器。
  • Handler: Jetty 的核心组件,用于处理 HTTP 请求。Jetty 提供了多种类型的 Handler,例如 ServletContextHandler、ResourceHandler、DefaultHandler 等。Handler 之间可以组合成链或树形结构。
  • ServletContextHandler: 一个特殊的 Handler,用于模拟传统的 Servlet 容器环境。它定义了一个 Web 应用程序的上下文路径,管理着该上下文下的所有 Servlet、过滤器、监听器等。
  • ServletHolder: Servlet 实例的包装器,它负责管理 Servlet 的生命周期(初始化、服务、销毁)以及其映射路径。
  • ResourceConfig (Jersey): Jersey 框架的配置类,用于定义 JAX-RS 应用程序的资源类、提供者、特性等。
  • ServletContainer (Jersey): Jersey 提供的 Servlet 实现,它作为标准 Servlet 容器与 JAX-RS 运行时之间的桥梁。

5. 注意事项与最佳实践

  • 处理器链管理: 如果你需要配置多个 Handler(例如,一个用于静态文件,一个用于 Servlet 应用),你应该使用 HandlerCollection 或 HandlerList 来组织它们,并将这个集合作为主 Handler 设置给 Server。
    HandlerCollection handlers = new HandlerCollection();
    handlers.setHandlers(new Handler[] { yourContextHandler, yourResourceHandler, new DefaultHandler() });
    server.setHandler(handlers);
  • 上下文路径与 Servlet 路径: 务必区分 ServletContextHandler 的上下文路径(setContextPath())和 ServletHolder 的 Servlet 路径(addServlet())。前者定义了整个 Web 应用的根,后者定义了应用内部 Servlet 的具体映射。
  • 资源扫描: 对于 Jersey 应用,确保 config.packages("api") 中的包名是正确的,并且实际的 JAX-RS 资源类(带有 @Path 注解的类)位于该包或其子包中。
  • 端口与防火墙: 确认 Jetty 监听的端口(例如 8080)没有被其他应用程序占用,并且防火墙允许外部访问该端口。
  • 日志调试: 在开发过程中,启用 Jetty 的详细日志可以帮助诊断问题。日志会显示请求的处理流程,包括哪个 Handler 接收了请求,以及请求是否成功匹配到 Servlet。
  • 服务器生命周期: server.start()、server.join()、server.stop() 和 server.destroy() 是服务器生命周期的关键方法。start() 启动服务器,join() 阻塞当前线程直到服务器停止,stop() 优雅地关闭服务器,destroy() 释放服务器占用的资源。确保在应用程序退出时正确调用 stop() 和 destroy()。

6. 总结

Jetty 服务器出现 404 Not Found 错误,尤其是在 Servlet 或 RESTful API 配置后,最常见的原因是 ServletContextHandler 没有被正确地附加到 Server 实例上。通过在 server.start() 之前调用 server.setHandler(handler);,可以确保 Jetty 服务器能够识别并处理由该 handler 管理的请求。理解 Server、Handler 和 ServletContextHandler 之间的关系,并遵循正确的配置流程,是构建稳定可靠 Jetty 应用程序的关键。在遇到问题时,系统地检查配置、上下文路径、Servlet 映射以及利用日志进行调试,将有助于快速定位并解决问题。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
PHP API接口开发与RESTful实践
PHP API接口开发与RESTful实践

本专题聚焦 PHP在API接口开发中的应用,系统讲解 RESTful 架构设计原则、路由处理、请求参数解析、JSON数据返回、身份验证(Token/JWT)、跨域处理以及接口调试与异常处理。通过实战案例(如用户管理系统、商品信息接口服务),帮助开发者掌握 PHP构建高效、可维护的RESTful API服务能力。

179

2025.11.26

servlet生命周期
servlet生命周期

Servlet生命周期是指Servlet从创建到销毁的整个过程。本专题为大家提供servlet生命周期的各类文章,大家可以免费体验。

393

2023.08.08

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

765

2023.08.10

http500解决方法
http500解决方法

http500解决方法有检查服务器日志、检查代码错误、检查服务器配置、检查文件和目录权限、检查资源不足、更新软件版本、重启服务器或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

495

2023.11.09

http请求415错误怎么解决
http请求415错误怎么解决

解决方法:1、检查请求头中的Content-Type;2、检查请求体中的数据格式;3、使用适当的编码格式;4、使用适当的请求方法;5、检查服务器端的支持情况。更多http请求415错误怎么解决的相关内容,可以阅读下面的文章。

450

2023.11.14

HTTP 503错误解决方法
HTTP 503错误解决方法

HTTP 503错误表示服务器暂时无法处理请求。想了解更多http错误代码的相关内容,可以阅读本专题下面的文章。

3571

2024.03.12

http与https有哪些区别
http与https有哪些区别

http与https的区别:1、协议安全性;2、连接方式;3、证书管理;4、连接状态;5、端口号;6、资源消耗;7、兼容性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2913

2024.08.16

Python异步编程与Asyncio高并发应用实践
Python异步编程与Asyncio高并发应用实践

本专题围绕 Python 异步编程模型展开,深入讲解 Asyncio 框架的核心原理与应用实践。内容包括事件循环机制、协程任务调度、异步 IO 处理以及并发任务管理策略。通过构建高并发网络请求与异步数据处理案例,帮助开发者掌握 Python 在高并发场景中的高效开发方法,并提升系统资源利用率与整体运行性能。

37

2026.03.12

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

136

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.9万人学习

PHP入门速学(台湾同胞版)
PHP入门速学(台湾同胞版)

共10课时 | 1.3万人学习

韩顺平 2016年 最新PHP基础视频教程
韩顺平 2016年 最新PHP基础视频教程

共47课时 | 10.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号