0

0

Jetty、Jersey与Weld:构建嵌入式Java REST应用

霞舞

霞舞

发布时间:2025-10-23 08:37:12

|

632人浏览过

|

来源于php中文网

原创

Jetty、Jersey与Weld:构建嵌入式Java REST应用

1. 引言:构建嵌入式Java REST应用

在现代java应用开发中,构建轻量级、自包含的restful服务越来越受欢迎。通过将web服务器(如jetty)嵌入到java se应用中,我们可以创建一个无需外部部署即可运行的独立服务。结合jersey作为jax-rs(java api for restful web services)的实现,以及weld作为cdi(contexts and dependency injection)的实现,可以构建出功能强大且易于管理的rest服务。本文将深入探讨如何正确配置和集成这三者,以解决常见的依赖注入问题,特别是针对jetty 11和jersey 3版本。

2. 项目初始化与Gradle依赖配置

首先,我们需要一个Java项目,并使用Gradle来管理依赖。以下是一个精简且正确的build.gradle配置,它包含了Jetty、Jersey、Weld以及日志所需的最小依赖集。

plugins {
    id 'application'
    id 'java'
    id 'eclipse' // 可选,用于生成Eclipse项目文件
}

repositories {
    mavenCentral()
}

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

    // Jetty 嵌入式服务器
    implementation 'org.eclipse.jetty:jetty-servlet:11.0.12'
    implementation 'org.eclipse.jetty:jetty-cdi:11.0.12' // 关键:Jetty的CDI集成模块

    // Weld CDI 实现
    implementation 'org.jboss.weld.servlet:weld-servlet-core:4.0.3.Final' // Weld Servlet集成核心

    // Jersey JAX-RS 实现
    implementation 'org.glassfish.jersey.containers:jersey-container-servlet-core:3.0.4'
    implementation 'org.glassfish.jersey.media:jersey-cdi2-se:3.0.4' // 关键:Jersey与CDI的集成模块
    implementation 'org.glassfish.jersey.media:jersey-media-json-jackson:3.0.4' // JSON支持

    // 测试依赖 (可选)
    testImplementation 'org.junit.jupiter:junit-jupiter:5.7.2'
}

application {
    // 定义应用主类
    mainClass = 'it.gym.StartApp'
}

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

注意事项:

  • jetty-cdi: 这是Jetty专门用于与CDI容器集成的模块,它简化了CDI生命周期的管理。
  • jersey-cdi2-se: 这是Jersey用于与CDI 2.x(或更高版本,如Jakarta EE 9+中的CDI 3.x)集成的模块。它确保了JAX-RS资源类中的@Inject注解能够被CDI容器正确处理。
  • 版本匹配: 确保Jetty、Jersey和Weld的版本兼容。此处示例使用的是Jetty 11.0.12、Jersey 3.0.4和Weld 4.0.3.Final,这些版本通常与Jakarta EE 9兼容。
  • 传递性依赖: 很多核心API(如jakarta.enterprise:jakarta.enterprise.cdi-api和jakarta.ws.rs:jakarta.ws.rs-api)会被上述依赖传递性地引入,因此无需显式声明。

3. 核心应用启动与CDI集成

在StartApp主类中,我们将配置并启动Jetty服务器,同时正确地初始化Weld CDI容器,并将其与Jetty和Jersey关联起来。这是解决“Unsatisfied dependencies”错误的关键部分。

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) {
        // 1. 创建Jetty服务器实例,监听端口
        final Server server = new Server(9000);

        // 2. 创建ServletContextHandler,用于配置Servlet和上下文路径
        final ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
        context.setContextPath("/"); // 设置根上下文路径

        // 3. 关键步骤:正确集成Weld CDI与Jetty
        // 使用CdiServletContainerInitializer和EnhancedListener进行CDI集成
        // 这是Weld推荐的与Jetty 11+集成的方式,它能自动发现和管理CDI Bean
        context.setInitParameter(
                CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE,
                CdiDecoratingListener.MODE);
        context.addServletContainerInitializer(new CdiServletContainerInitializer());
        context.addServletContainerInitializer(new EnhancedListener());

        // 4. 配置Jersey ServletContainer
        final ServletHolder servletHolder = new ServletHolder(ServletContainer.class);
        servletHolder.setInitOrder(1); // 确保Servlet在启动时初始化

        // 告知Jersey扫描哪些包来查找JAX-RS资源类
        servletHolder.setInitParameter(
                "jersey.config.server.provider.packages",
                "it.gym.rest"); // 替换为你的REST资源类所在的包

        // 5. 将Jersey Servlet添加到上下文,并设置URL映射
        context.addServlet(servletHolder, "/rest/*"); // 所有/rest/*的请求都由Jersey处理

        // 6. 设置Jetty服务器的处理器
        server.setHandler(context);

        // 7. 启动Jetty服务器
        try {
            server.start();
            server.join(); // 阻塞主线程,直到服务器停止
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1); // 启动失败时退出应用
        } finally {
            // 确保服务器在应用关闭时停止
            if (server.isRunning()) {
                try {
                    server.stop();
                } catch (Exception e) {
                    System.err.println("Error stopping Jetty server: " + e.getMessage());
                }
            }
        }
    }
}

核心集成点解析:

立即学习Java免费学习笔记(深入)”;

  • CdiServletContainerInitializer: 这是Jetty CDI模块提供的一个ServletContainerInitializer,它负责在Servlet容器启动时初始化CDI环境。
  • CdiDecoratingListener.MODE: 设置CDI集成模式,通常与CdiServletContainerInitializer配合使用。
  • EnhancedListener: Weld Servlet模块提供的增强型监听器,它进一步完善了Weld在Servlet环境中的生命周期管理。
  • 通过这种方式,Weld容器的生命周期与Jetty ServletContext的生命周期紧密绑定,从而确保CDI能够正确地发现和管理应用中的所有CDI Bean,包括JAX-RS资源类中@Inject的依赖。

4. 定义REST资源与CDI Bean

现在我们可以创建JAX-RS资源类和普通的CDI Bean,并演示它们之间的依赖注入。

4.1 REST资源类 (GymEndpoint.java)

这个类作为REST服务的入口点,负责处理HTTP请求,并注入业务逻辑层的CDI Bean。

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 // JAX-RS资源类默认是单例,但在此处声明为请求作用域,以便CDI管理其生命周期
public class GymEndpoint {

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

    @GET // 处理HTTP GET请求
    @Path("/test") // 映射到 /rest/test 路径
    public Response test() {
        List entity = gymDAO.getDevices(); // 调用注入的DAO方法
        return Response.status(Status.OK).entity(entity).build();
    }
}
  • @Path: 定义资源类的基础URI路径和方法的子路径。
  • @RequestScoped: 确保GymEndpoint实例在每个HTTP请求的生命周期内有效,并由CDI容器管理。
  • @Inject: 这是CDI的核心注解,用于声明依赖。Weld容器会查找并提供GymDAO的一个实例。

4.2 CDI Bean (GymDAO.java)

这个类是一个简单的数据访问对象(DAO),它是一个CDI Bean,可以被其他CDI Bean注入。

OpenArt
OpenArt

在线AI绘画艺术图片生成器工具

下载
package it.gym.dao;

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

import jakarta.enterprise.context.RequestScoped; // 声明为请求作用域的CDI Bean

@RequestScoped
public class GymDAO {

    public GymDAO() {
        // 构造函数,CDI容器在创建实例时调用
    }

    public List getDevices() {
        // 模拟数据访问
        List devices = new ArrayList<>();
        devices.add("Device A");
        devices.add("Device B");
        return devices;
    }
}
  • @RequestScoped: 声明GymDAO是一个CDI Bean,并且其生命周期与HTTP请求绑定。每次请求都会获得一个新的GymDAO实例(如果需要)。

5. 运行与验证

完成上述配置和代码编写后,你可以通过Gradle运行你的应用:

gradle run

当应用启动成功后,你将看到Jetty服务器在端口9000上运行。然后,你可以使用浏览器或任何HTTP客户端访问:

http://localhost:9000/rest/test

你应该会收到一个JSON响应,其中包含GymDAO返回的设备列表,例如:

["Device A", "Device B"]

这表明Jetty、Jersey和Weld已成功集成,并且CDI的依赖注入机制正常工作。

6. 总结与注意事项

本文提供了一个在Jetty嵌入式服务器中集成Jersey JAX-RS和Weld CDI的完整教程。关键在于正确配置Gradle依赖,特别是引入jetty-cdi和jersey-cdi2-se,以及在ServletContextHandler中通过CdiServletContainerInitializer和EnhancedListener来初始化CDI容器。

关键要点回顾:

  • jetty-cdi和jersey-cdi2-se是实现Jetty、Jersey和Weld无缝集成的核心依赖。
  • 使用CdiServletContainerInitializer和EnhancedListener是Jetty 11+中推荐的CDI集成方式,它替代了手动添加Weld监听器和设置BeanManager属性的方法。
  • 确保JAX-RS资源类和CDI Bean都使用正确的Jakarta EE注解(如jakarta.ws.rs.*和jakarta.inject.*)。
  • jersey.config.server.provider.packages初始化参数必须指向包含你的JAX-RS资源类的正确包路径。

遵循这些步骤,你就可以成功构建一个功能齐全、模块化的嵌入式Java REST应用,充分利用CDI提供的强大依赖注入能力。

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

835

2023.06.15

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

740

2023.07.05

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

736

2023.07.31

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

397

2023.08.01

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

399

2023.08.02

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

446

2023.08.02

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

430

2023.08.02

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

16926

2023.08.03

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

43

2026.01.16

热门下载

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

精品课程

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

共23课时 | 2.6万人学习

C# 教程
C# 教程

共94课时 | 6.9万人学习

Java 教程
Java 教程

共578课时 | 47.2万人学习

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

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