0

0

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

心靈之曲

心靈之曲

发布时间:2025-10-23 10:14:11

|

998人浏览过

|

来源于php中文网

原创

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

本教程详细阐述了如何在嵌入式jetty服务器中正确集成jersey rest服务和weld cdi,以解决常见的依赖注入失败问题。通过优化gradle依赖配置,并采用jetty cdi模块推荐的`cdiservletcontainerinitializer`和`enhancedlistener`进行cdi上下文初始化,确保了`@inject`注解能够正常工作,从而实现一个功能完善、支持cdi的独立rest应用。

1. 引言:Jetty、Jersey与Weld CDI集成挑战

在Java SE环境中构建一个独立的、支持RESTful API并具备依赖注入(CDI)功能的Web服务器时,嵌入式Jetty、Jersey(JAX-RS实现)和Weld(CDI实现)是常见的技术组合。然而,如果不正确配置CDI上下文,可能会遇到Unsatisfied dependencies等依赖注入失败的问题,导致应用程序无法正常启动或运行。本教程将提供一个经过验证的解决方案,指导您如何正确地将这三者集成。

2. Gradle依赖配置优化

正确的依赖是成功集成的基石。原始配置可能包含一些冗余或不兼容的依赖。以下是针对Jakarta EE 9+环境,推荐的精简且必要的Gradle依赖配置:

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环境支持
    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集成模块,针对Jakarta EE 9+ (CDI 2.0 SE)
    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()
}

关键点说明:

Voicenotes
Voicenotes

Voicenotes是一款简单直观的多功能AI语音笔记工具

下载
  • org.eclipse.jetty:jetty-cdi: 这是Jetty官方提供的CDI集成模块,它负责将Jetty的生命周期与CDI容器(如Weld)的生命周期关联起来。
  • org.jboss.weld.servlet:weld-servlet-core: 提供了Weld在Servlet环境下的核心支持。
  • org.glassfish.jersey.media:jersey-cdi2-se: 这是Jersey针对Jakarta EE 9+(CDI 2.0 SE)的CDI集成模块,确保Jersey能够正确发现并使用CDI管理的资源类和Bean。
  • 我们利用了Maven/Gradle的传递性依赖特性,精简了列表,避免了手动添加所有子依赖。

3. Jetty服务器与Weld CDI集成设置

正确初始化CDI上下文是解决依赖注入问题的核心。传统的通过Weld实例直接设置监听器和BeanManager的方式在嵌入式Jetty中可能无法与Jersey的CDI集成模块协同工作。应采用Jetty CDI模块推荐的ServletContainerInitializer机制。

修改后的StartApp.java主类如下:

package it.gym;

import org.eclipse.jetty.cdi.CdiDecoratingListener;
import org.eclipse.jetty.cdi.CdiServletContainerInitializer;
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.servlet.EnhancedListener;

public class StartApp {

    public static void main(String[] args) {
        // Weld的初始化不再直接在main方法中进行,而是通过ServletContainerInitializer
        // Weld weld = new Weld();
        // WeldContainer container = weld.initialize();

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

        // 关键的CDI集成配置
        // 1. 设置CDI集成模式为CdiDecoratingListener
        context.setInitParameter(
                CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE,
                CdiDecoratingListener.MODE);
        // 2. 添加Jetty CDI的ServletContainerInitializer
        context.addServletContainerInitializer(new CdiServletContainerInitializer());
        // 3. 添加Weld的EnhancedListener,确保Weld在Servlet环境中正确启动和关闭
        context.addServletContainerInitializer(new EnhancedListener());

        // Jersey Servlet配置
        final ServletHolder servletHolder = new ServletHolder(ServletContainer.class);
        servletHolder.setInitOrder(1);
        servletHolder.setInitParameter(
                "jersey.config.server.provider.packages",
                "it.gym.rest"); // 确保指向包含REST资源的包

        context.addServlet(servletHolder, "/rest/*");

        server.setHandler(context);

        try {
            server.start();
            server.join();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 确保Weld容器在应用关闭时也正确关闭 (如果手动初始化,这里需要weld.shutdown())
            // 但通过ServletContainerInitializer方式,通常由容器自动管理
        }
    }
}

关键点说明:

  • CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE: 这个初始化参数告诉Jetty的CDI模块如何处理CDI集成,CdiDecoratingListener.MODE指示使用装饰器监听器模式。
  • context.addServletContainerInitializer(new CdiServletContainerInitializer()): 注册Jetty CDI的初始化器。它会在Servlet容器启动时被调用,负责发现并启动CDI容器。
  • context.addServletContainerInitializer(new EnhancedListener()): 注册Weld提供的增强型监听器。这个监听器是Weld在Servlet环境中正确启动和管理其生命周期的推荐方式。
  • jersey.config.server.provider.packages: 确保此参数指向您的JAX-RS资源类所在的包,以便Jersey能够发现它们。

4. 示例REST资源与CDI Bean

以下是使用@Inject进行依赖注入的REST资源类和CDI Bean的示例,它们将在上述配置下正常工作。

GymEndpoint.java (REST资源类):

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 // 将REST资源本身也声明为CDI管理的Bean
public class GymEndpoint {

    @Inject // 通过CDI注入GymDAO实例
    private GymDAO gymDAO;

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

GymDAO.java (CDI Bean):

package it.gym.dao;

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

import jakarta.enterprise.context.RequestScoped;

@RequestScoped // 将此DAO类声明为CDI管理的Bean
public class GymDAO {

    public GymDAO() {
        // 构造函数,CDI容器会负责实例化
    }

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

关键点说明:

  • @RequestScoped: 确保GymEndpoint和GymDAO都被CDI容器发现并管理。当一个HTTP请求到来时,CDI会为@RequestScoped的Bean创建一个新的实例,并在请求结束后销毁。
  • @Inject: 这是CDI的核心注解,用于请求容器注入一个符合条件的Bean实例。

5. 运行与验证

完成上述配置和代码修改后,运行StartApp的main方法。 当服务器启动后,您可以通过访问http://localhost:9000/rest/test来验证您的REST服务。如果一切配置正确,您应该会收到一个包含设备列表的JSON响应(例如["Device A", "Device B"]),而不是依赖注入失败的错误。

6. 注意事项与总结

  • 版本兼容性:确保所有Jetty、Jersey、Weld和Jakarta EE API依赖的版本兼容。本教程使用的版本是针对Jakarta EE 9+环境的。如果您的项目使用更早的Java EE或Jakarta EE版本,相应的依赖(尤其是Jersey的CDI模块,如jersey-cdi1x)可能需要调整。
  • 传递性依赖:Jetty和Jersey的CDI模块会引入大部分必要的Jakarta EE API和Weld核心库。避免手动添加重复的API依赖,以免造成版本冲突。
  • beans.xml:在某些CDI环境中,需要在META-INF或WEB-INF目录下放置一个空的beans.xml文件来显式激活CDI。但在大多数Weld SE和Servlet环境中,如果类带有CDI注解,Weld会自动发现它们。如果遇到Bean未被发现的问题,可以尝试添加此文件。
  • 日志配置:为了更好地调试,确保您的logback.xml或log4j2.xml配置正确,以便查看CDI容器和Jersey的详细启动日志。

通过遵循本教程的步骤,您将能够成功地在嵌入式Jetty服务器中集成Jersey REST服务和Weld CDI,构建一个健壮且易于维护的独立Java应用程序。关键在于理解并正确配置Jetty CDI模块和Weld Servlet监听器,让它们协同工作,从而实现无缝的依赖注入。

热门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服务能力。

158

2025.11.26

json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

419

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

535

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

311

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

77

2025.09.10

eclipse教程
eclipse教程

php中文网为大家带来eclipse教程合集,eclipse是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。php中文网还为大家带来eclipse的相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

191

2023.06.14

eclipse怎么设置中文
eclipse怎么设置中文

eclipse设置中文的方法:除了设置界面为中文外,你还可以为Eclipse添加中文插件,以便更好地支持中文编程。例如,你可以安装EBNF插件来支持中文变量名,或安装Chinese Helper来提供中文帮助文档。本专题为大家提供eclipse设置中文相关的各种文章、以及下载和课程。

795

2023.07.24

c语言编程软件有哪些
c语言编程软件有哪些

c语言编程软件有GCC、Clang、Microsoft Visual Studio、Eclipse、NetBeans、Dev-C++、Code::Blocks、KDevelop、Sublime Text和Atom。更多关于c语言编程软件的问题详情请看本专题的文章。php中文网欢迎大家前来学习。

596

2023.11.02

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

158

2026.01.28

热门下载

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

精品课程

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

共23课时 | 3万人学习

C# 教程
C# 教程

共94课时 | 7.8万人学习

Java 教程
Java 教程

共578课时 | 52.4万人学习

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

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