
本文详细介绍了如何在java se环境中,利用嵌入式jetty服务器、jersey框架和weld cdi实现一个功能完备的restful应用。文章聚焦于正确的依赖配置和weld cdi与jetty servlet容器的集成方式,旨在解决常见的依赖注入问题,确保cdi bean能够被正确发现和管理,从而构建一个稳定高效的独立rest服务。
在Java生态中,构建一个轻量级、独立的RESTful服务是常见的需求。结合嵌入式Jetty作为Web服务器、Jersey作为JAX-RS实现以及Weld作为CDI(Contexts and Dependency Injection)容器,可以实现一个功能强大且易于部署的解决方案。然而,正确地集成这三者,尤其是确保CDI的依赖注入机制正常工作,常常是开发者面临的挑战。本文将提供一套经过验证的集成方案,帮助您顺利搭建此类应用。
首先,正确配置项目的依赖是成功的关键。以下是一个推荐的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 服务器核心与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 JAX-RS实现与Servlet容器集成
implementation 'org.glassfish.jersey.containers:jersey-container-servlet-core:3.0.4'
// Jersey 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'
// Jackson JSON处理库
implementation 'com.fasterxml.jackson.core:jackson-core:2.12.7'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.12.7'
// JUnit Jupiter for testing (可选)
testImplementation 'org.junit.jupiter:junit-jupiter:5.7.2'
}
application {
mainClass = 'it.gym.StartApp' // 定义应用主类
}
tasks.named('test') {
useJUnitPlatform()
}注意事项:
接下来,我们需要编写主启动类来初始化Jetty服务器、配置Servlet上下文,并正确地集成Weld CDI。
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.se.Weld;
import org.jboss.weld.environment.se.WeldContainer;
import org.jboss.weld.environment.servlet.EnhancedListener;
public class StartApp {
public static void main(String[] args) {
// 1. 初始化Weld SE容器
// Weld weld = new Weld(); // 在此集成方式下,通常不需要手动初始化Weld SE容器
// WeldContainer container = weld.initialize(); // 而是通过ServletContainerInitializer来完成
final Server server = new Server(9000); // 监听端口9000
final ServletContextHandler context = new ServletContextHandler(
ServletContextHandler.SESSIONS);
context.setContextPath("/"); // 设置应用根路径
// 2. 关键的Weld CDI与Jetty集成配置
// 这是Weld推荐的与Jetty集成的方式,取代了旧的addEventListener和setAttribute方法
context.setInitParameter(
CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE,
CdiDecoratingListener.MODE);
context.addServletContainerInitializer(new CdiServletContainerInitializer());
context.addServletContainerInitializer(new EnhancedListener());
// 3. 配置Jersey ServletContainer
final ServletHolder servletHolder = new ServletHolder(
ServletContainer.class);
servletHolder.setInitOrder(1); // 保证Servlet在其他组件之前初始化
servletHolder.setInitParameter(
"jersey.config.server.provider.packages",
"it.gym.rest"); // 指定Jersey扫描REST资源类的包路径
context.addServlet(servletHolder, "/rest/*"); // 将Jersey Servlet映射到/rest/*路径
server.setHandler(context); // 将上下文处理器设置到服务器
// 4. 启动服务器
try {
server.start();
server.join(); // 阻塞主线程,直到服务器停止
} catch (Exception e) {
e.printStackTrace();
// 确保在异常发生时关闭Weld容器,如果之前手动初始化了
// if (container != null) {
// container.shutdown();
// }
} finally {
// 如果Weld在SE模式下手动初始化,这里需要关闭
// 如果是通过ServletContainerInitializer启动,则由容器管理生命周期
}
}
}CDI 集成重点解释:
为了确保Weld CDI能够正确地发现并管理Bean,以及Jersey能够利用这些Bean进行依赖注入,关键在于ServletContextHandler的配置。
通过这三行配置,我们有效地将Weld CDI容器与Jetty的Servlet容器生命周期绑定,解决了CDI Bean无法被正确发现和注入的问题。
现在,我们可以定义我们的RESTful资源类和CDI Bean,并利用CDI进行依赖注入。
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 // 处理HTTP GET请求
@Path("/test") // 映射到/rest/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; // 声明为请求范围的CDI Bean
@RequestScoped
public class GymDAO {
public GymDAO() {
// CDI Bean通常有一个无参构造器
}
public List<String> getDevices() {
// 模拟数据访问逻辑
return new ArrayList<>();
}
}在GymEndpoint中,我们使用@Inject注解来声明对GymDAO的依赖。由于GymDAO被@RequestScoped注解标记,Weld CDI容器会在每次HTTP请求到达时,自动创建一个GymDAO实例并注入到GymEndpoint中。正确的CDI集成确保了这一过程的无缝执行。
通过遵循本文提供的依赖配置和Jetty启动类中的Weld CDI集成方法,您应该能够成功构建一个基于嵌入式Jetty、Jersey和Weld的独立RESTful应用程序,并有效利用CDI的依赖注入能力。
以上就是嵌入式Jetty、Jersey与Weld CDI集成指南的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号