
在现代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版本。
首先,我们需要一个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()
}注意事项:
在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免费学习笔记(深入)”;
现在我们可以创建JAX-RS资源类和普通的CDI Bean,并演示它们之间的依赖注入。
这个类作为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<String> entity = gymDAO.getDevices(); // 调用注入的DAO方法
return Response.status(Status.OK).entity(entity).build();
}
}这个类是一个简单的数据访问对象(DAO),它是一个CDI Bean,可以被其他CDI Bean注入。
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<String> getDevices() {
// 模拟数据访问
List<String> devices = new ArrayList<>();
devices.add("Device A");
devices.add("Device B");
return devices;
}
}完成上述配置和代码编写后,你可以通过Gradle运行你的应用:
gradle run
当应用启动成功后,你将看到Jetty服务器在端口9000上运行。然后,你可以使用浏览器或任何HTTP客户端访问:
http://localhost:9000/rest/test
你应该会收到一个JSON响应,其中包含GymDAO返回的设备列表,例如:
["Device A", "Device B"]
这表明Jetty、Jersey和Weld已成功集成,并且CDI的依赖注入机制正常工作。
本文提供了一个在Jetty嵌入式服务器中集成Jersey JAX-RS和Weld CDI的完整教程。关键在于正确配置Gradle依赖,特别是引入jetty-cdi和jersey-cdi2-se,以及在ServletContextHandler中通过CdiServletContainerInitializer和EnhancedListener来初始化CDI容器。
关键要点回顾:
遵循这些步骤,你就可以成功构建一个功能齐全、模块化的嵌入式Java REST应用,充分利用CDI提供的强大依赖注入能力。
以上就是Jetty、Jersey与Weld:构建嵌入式Java REST应用的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号