1. 简介
JAX-RS(Java API for RESTful Web Services)是一套用于创建 REST API 的 Java 规范。它大量使用注解来简化开发流程,提升开发效率。
在本教程中,我们将使用 JBoss 提供的 JAX-RS 实现框架 —— RESTEasy 来构建一个简单的 RESTful Web 服务。
2. 项目配置
我们将考虑两种常见的部署场景:
- 独立部署(Standalone Setup) – 适用于任意应用服务器
- JBoss AS 部署(JBoss AS Setup) – 仅适用于部署在 JBoss 应用服务器上
2.1. 独立部署
我们以 JBoss WildFly 10 为例,进行独立部署的配置。
WildFly 10 默认集成的是 RESTEasy 3.0.11 版本,但我们将在 pom.xml 中手动升级到 3.0.14 版本。
得益于 resteasy-servlet-initializer 模块,RESTEasy 可以通过 ServletContainerInitializer 接口与支持 Servlet 3.0 的容器进行集成。
以下是 pom.xml 的关键依赖配置:
<properties>
<resteasy.version>3.0.14.Final</resteasy.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-servlet-initializer</artifactId>
<version>${resteasy.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>${resteasy.version}</version>
</dependency>
</dependencies>
jboss-deployment-structure.xml
在 JBoss 中,WAR、JAR 或 EAR 都被视为模块,称为 动态模块。此外,JBoss 还提供了一些预定义的 静态模块,位于 $JBOSS_HOME/modules 目录下。
由于 JBoss 自带了 RESTEasy 的静态模块,若想使用我们自定义的版本,就必须通过 jboss-deployment-structure.xml 来排除默认模块,避免冲突。
配置如下,确保 WAR 中的类和 JAR 能够被优先加载:
<jboss-deployment-structure>
<deployment>
<exclude-subsystems>
<subsystem name="resteasy" />
</exclude-subsystems>
<exclusions>
<module name="javaee.api" />
<module name="javax.ws.rs.api"/>
<module name="org.jboss.resteasy.resteasy-jaxrs" />
</exclusions>
<local-last value="true" />
</deployment>
</jboss-deployment-structure>
2.2. JBoss AS 部署
如果你使用的是 JBoss AS 6 或更高版本,可以直接使用服务器自带的 RESTEasy 库,这样可以简化 pom.xml 配置:
<dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>${resteasy.version}</version>
</dependency>
</dependencies>
⚠️ 注意:此时不再需要 jboss-deployment-structure.xml 文件。
3. 服务端代码实现
3.1. Servlet 3.0 的 web.xml 配置
下面是我们项目中 web.xml 的简化配置示例:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>RestEasy Example</display-name>
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/rest</param-value>
</context-param>
</web-app>
参数 resteasy.servlet.mapping.prefix 用于指定 REST 接口的统一前缀路径。
✅ 你可能注意到我们没有在 web.xml 中显式声明 Servlet,这是因为我们已经在 pom.xml 中引入了 resteasy-servlet-initializer 依赖。RESTEasy 内部通过 org.jboss.resteasy.plugins.servlet.ResteasyServletInitializer
实现了 ServletContainerInitializer 接口,在容器启动时自动注册相关组件。
3.2. Application 类
javax.ws.rs.core.Application 是标准的 JAX-RS 类,用于提供部署信息。我们可以继承它来注册服务:
@ApplicationPath("/rest")
public class RestEasyServices extends Application {
private Set<Object> singletons = new HashSet<Object>();
public RestEasyServices() {
singletons.add(new MovieCrudService());
}
@Override
public Set<Object> getSingletons() {
return singletons;
}
}
📌 该类通过 @ApplicationPath 注解指定 REST API 的根路径,构造函数中注册了具体的资源类。如果返回空集合,则容器会自动扫描带有 JAX-RS 注解的类。
3.3. 实际服务实现类
下面是一个简单的 REST 接口实现类:
@Path("/movies")
public class MovieCrudService {
private Map<String, Movie> inventory = new HashMap<String, Movie>();
@GET
@Path("/getinfo")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Movie movieByImdbId(@QueryParam("imdbId") String imdbId) {
if (inventory.containsKey(imdbId)) {
return inventory.get(imdbId);
} else {
return null;
}
}
@POST
@Path("/addmovie")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response addMovie(Movie movie) {
if (null != inventory.get(movie.getImdbId())) {
return Response
.status(Response.Status.NOT_MODIFIED)
.entity("Movie is Already in the database.").build();
}
inventory.put(movie.getImdbId(), movie);
return Response.status(Response.Status.CREATED).build();
}
}
📌 说明:
- @Path:定义资源路径
- @GET / @POST:定义 HTTP 方法
- @Produces / @Consumes:指定支持的媒体类型
- @QueryParam:从请求参数中提取值
- Response:用于构建 HTTP 响应
4. 总结
在本教程中,我们快速上手了 RESTEasy,并构建了一个简单的 REST API 示例。RESTEasy 提供了强大的功能和灵活的扩展性,非常适合用于构建企业级 RESTful 服务。
本例的完整代码已上传至 GitHub:sample project in GitHub ✅