0

0

在嵌入式Jetty中集成Jersey REST服务与Weld CDI的指南

DDD

DDD

发布时间:2025-10-23 11:51:21

|

683人浏览过

|

来源于php中文网

原创

在嵌入式Jetty中集成Jersey REST服务与Weld CDI的指南

本教程详细介绍了如何在java se环境中,使用嵌入式jetty服务器、jersey框架构建restful服务,并无缝集成weld cdi实现依赖注入。文章将重点阐述正确的gradle依赖配置以及jetty与weld cdi的集成方式,以解决常见的依赖注入问题,确保应用程序的稳定运行和模块化设计。

在嵌入式Jetty中集成Jersey REST服务与Weld CDI

在构建独立的Java SE应用程序时,我们常常需要一个轻量级的Web服务器来暴露RESTful API,并结合依赖注入框架来管理组件生命周期。本文将指导您如何在嵌入式Jetty服务器中,有效集成Jersey(JAX-RS实现)和Weld(CDI实现),以构建一个功能完善且易于维护的REST服务。

1. 项目依赖管理

正确的依赖配置是成功集成的基石。为了确保Jetty、Jersey和Weld之间的兼容性,我们需要引入一系列特定的库。以下是推荐的Gradle配置,它精简了不必要的依赖,并引入了关键的jetty-cdi模块来简化集成:

plugins {
    id 'application'
    id 'java'
    id 'eclipse'
}

repositories {
    mavenCentral()
}

dependencies {
    // 日志框架
    implementation 'org.slf4j:slf4j-api:2.0.4'
    implementation 'ch.qos.logback:logback-classic:1.4.5'

    // Jetty 服务器核心与Servlet支持
    implementation 'org.eclipse.jetty:jetty-servlet:11.0.12'
    // Jetty CDI集成模块,关键所在
    implementation 'org.eclipse.jetty:jetty-cdi:11.0.12'

    // Weld Servlet环境核心,提供CDI Servlet生命周期监听器
    implementation 'org.jboss.weld.servlet:weld-servlet-core:4.0.3.Final'

    // Jersey RESTful框架核心与Servlet容器集成
    implementation 'org.glassfish.jersey.containers:jersey-container-servlet-core:3.0.4'
    // Jersey CDI 2.0 SE集成模块,与Weld 4.x版本兼容
    implementation 'org.glassfish.jersey.media:jersey-cdi2-se:3.0.4'
    // Jersey JSON处理支持
    implementation 'org.glassfish.jersey.media:jersey-media-json-jackson:3.0.4'

    // 测试依赖
    testImplementation 'org.junit.jupiter:junit-jupiter:5.7.2'
}

application {
    mainClass = 'it.gym.StartApp'
}

tasks.named('test') {
    useJUnitPlatform()
}

依赖说明:

  • jetty-cdi:这是Jetty官方提供的CDI集成模块,它负责协调Jetty的Servlet容器与CDI运行时(如Weld)的生命周期。
  • weld-servlet-core:提供Weld在Servlet环境中的支持,包括必要的监听器。
  • jersey-cdi2-se:Jersey针对CDI 2.0的独立(SE)环境集成模块。请注意,这里的版本(3.0.4)与weld-servlet-core(4.0.3.Final)是相互兼容的,它们都基于CDI 2.0规范。如果需要使用CDI 3.0(Jakarta EE 9+),则需要选择更高版本的Jersey和Weld模块。

2. 嵌入式Jetty服务器与CDI集成配置

Jetty服务器的配置是实现CDI注入的关键环节。传统的Servlet监听器配置方式无法正确地让Weld管理Jersey资源类中的注入点。我们需要利用jetty-cdi提供的机制。

以下是主应用程序类StartApp的示例,展示了如何启动Jetty并正确集成Weld CDI:

package it.gym;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.glassfish.jersey.servlet.ServletContainer;
import org.jboss.weld.environment.se.Weld;
import org.jboss.weld.environment.se.WeldContainer;

// 导入正确的CDI集成类
import org.eclipse.jetty.cdi.CdiServletContainerInitializer;
import org.eclipse.jetty.cdi.CdiDecoratingListener;
import org.jboss.weld.environment.servlet.EnhancedListener;

public class StartApp {

    public static void main(String[] args) {
        // 1. 初始化Weld SE容器 (虽然Weld Servlet会接管,但初始化SE容器可以确保BeanManager可用)
        Weld weld = new Weld();
        WeldContainer container = weld.initialize(); // 此处初始化Weld SE容器

        final Server server = new Server(9000);
        final ServletContextHandler context = new ServletContextHandler(
                ServletContextHandler.SESSIONS);
        context.setContextPath("/");

        // 2. 配置Jetty与Weld CDI的集成
        // 设置CDI集成模式为装饰器监听器模式
        context.setInitParameter(
                CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE,
                CdiDecoratingListener.MODE);
        // 添加Jetty CDI容器初始化器
        context.addServletContainerInitializer(new CdiServletContainerInitializer());
        // 添加Weld增强型监听器,确保Weld在Servlet上下文中的正确生命周期管理
        context.addServletContainerInitializer(new EnhancedListener());

        // 3. 配置Jersey Servlet
        final ServletHolder servletHolder = new ServletHolder(
                ServletContainer.class);
        servletHolder.setInitOrder(1);
        // 指定Jersey扫描JAX-RS资源类的包路径
        servletHolder.setInitParameter(
                "jersey.config.server.provider.packages",
                "it.gym"); // 替换为您的资源类所在的基础包

        context.addServlet(servletHolder, "/rest/*"); // 将Jersey Servlet映射到/rest/*路径

        server.setHandler(context);

        try {
            server.start();
            server.join();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 确保Weld容器在应用关闭时也关闭
            weld.shutdown();
        }
    }
}

关键集成点:

MemFree
MemFree

MemFree - 来自知识库和互联网的混合AI搜索,更快获取准确答案

下载
  • context.setInitParameter(CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE, CdiDecoratingListener.MODE);:告知Jetty的CDI集成模块使用CdiDecoratingListener模式来处理Servlet事件。
  • context.addServletContainerInitializer(new CdiServletContainerInitializer());:注册Jetty CDI的Servlet容器初始化器。它会在Web应用启动时扫描并初始化CDI环境。
  • context.addServletContainerInitializer(new EnhancedListener());:注册Weld提供的增强型监听器,这是Weld在Servlet环境中正确启动和管理其BeanManager所必需的。

通过以上配置,Jetty将能够识别并正确启动Weld CDI环境,使得Jersey资源类中的@Inject注解能够正常工作。

3. JAX-RS资源与CDI Bean实现

一旦Jetty和Weld CDI集成正确,您的JAX-RS资源类和CDI Bean就可以像在任何标准EE容器中一样进行开发。

RESTful资源类 (GymEndpoint.java):

package it.gym.rest;

import java.util.List;

import it.gym.dao.GymDAO;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;

@Path("/")
@RequestScoped // 标记为请求作用域的CDI Bean
public class GymEndpoint {

    @Inject // 注入GymDAO实例
    private GymDAO gymDAO;

    @GET
    @Path("/test")
    public Response test() {
        List<String> entity = gymDAO.getDevices();
        return Response.status(Status.OK).entity(entity).build();
    }
}

CDI Bean (GymDAO.java):

package it.gym.dao;

import java.util.ArrayList;
import java.util.List;

import jakarta.enterprise.context.RequestScoped;

@RequestScoped // 标记为请求作用域的CDI Bean
public class GymDAO {

    public GymDAO() {
        // 构造函数,Weld会负责其生命周期
    }

    public List<String> getDevices() {
        // 模拟数据访问
        List<String> devices = new ArrayList<>();
        devices.add("Device A");
        devices.add("Device B");
        return devices;
    }
}

在GymEndpoint中,@Inject注解用于请求GymDAO的实例。由于GymDAO被@RequestScoped注解标记,Weld CDI容器将负责创建、管理并注入GymDAO的实例到GymEndpoint中,从而解决了“Unsatisfied dependencies”的错误。

4. 注意事项

  • 版本兼容性: 确保Jetty、Jersey、Weld以及Jakarta EE API(如jakarta.enterprise:jakarta.enterprise.cdi-api和jakarta.ws.rs:jakarta.ws.rs-api)的版本相互兼容。本文提供的依赖组合经过验证可以在Jetty 11.x下工作。
  • 包扫描: servletHolder.setInitParameter("jersey.config.server.provider.packages", "it.gym");参数至关重要,它告诉Jersey在哪里查找您的JAX-RS资源类。请根据您的项目结构调整此包路径。
  • beans.xml: 对于Weld SE环境,通常不需要显式的beans.xml文件来进行基本的bean发现。然而,如果您需要更高级的CDI配置(如替代、装饰器等),则可能需要在src/main/resources/META-INF/目录下放置一个空的或配置过的beans.xml文件。
  • 错误处理: 在生产环境中,应加入更健壮的错误处理和日志记录机制,而不是简单地打印堆跟踪。

总结

通过本文的指导,您应该已经成功地在嵌入式Jetty服务器中集成了Jersey REST服务和Weld CDI。关键在于正确配置项目依赖,并利用jetty-cdi提供的CdiServletContainerInitializer和EnhancedListener来协调Jetty和Weld的生命周期。这种集成方式不仅解决了CDI依赖注入的问题,还为构建模块化、可维护的独立Java SE REST应用程序奠定了坚实的基础。

热门AI工具

更多
DeepSeek
DeepSeek

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

豆包大模型
豆包大模型

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

通义千问
通义千问

阿里巴巴推出的全能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生命周期的各类文章,大家可以免费体验。

392

2023.08.08

pdf怎么转换成xml格式
pdf怎么转换成xml格式

将 pdf 转换为 xml 的方法:1. 使用在线转换器;2. 使用桌面软件(如 adobe acrobat、itext);3. 使用命令行工具(如 pdftoxml)。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1945

2024.04.01

xml怎么变成word
xml怎么变成word

步骤:1. 导入 xml 文件;2. 选择 xml 结构;3. 映射 xml 元素到 word 元素;4. 生成 word 文档。提示:确保 xml 文件结构良好,并预览 word 文档以验证转换是否成功。想了解更多xml的相关内容,可以阅读本专题下面的文章。

2119

2024.08.01

xml是什么格式的文件
xml是什么格式的文件

xml是一种纯文本格式的文件。xml指的是可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。想了解更多相关的内容,可阅读本专题下面的相关文章。

1166

2024.11.28

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

439

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

601

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

439

2023.07.18

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

24

2026.03.09

热门下载

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

精品课程

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

共23课时 | 4.3万人学习

C# 教程
C# 教程

共94课时 | 11万人学习

Java 教程
Java 教程

共578课时 | 79.9万人学习

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

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