JAX-RS 与 Jersey

最后更新: 2024-07-01 19:46:18 +0800 +0800
tags: Java | Jax-Rs | Jersey | Web
原文以英文撰写。您正在阅读AI翻译版本。

JAX-RS 是 jakarta.ws.rs 包中用于 HTTP 资源的 Jakarta 标准 API 和规范。 它定义注解、请求和响应类型、客户端 API、提供程序以及服务器发送事件支持。 Jersey 是符合该规范的 JAX-RS 实现。

JAX-RS 不同于 JAX-WS,后者关注 XML Web 服务。

定义资源 #

在编译期添加 Jakarta REST API,并在运行期添加 JAX-RS 实现。 资源类使用 @Path;方法使用 HTTP 方法注解,并可以增加相对路径:

java
@Path("/users")
@Produces(MediaType.APPLICATION_JSON)
public class UserResource {
    @GET
    @Path("/{id}")
    public User get(@PathParam("id") long id) {
        return service.find(id);
    }

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public Response create(User input) {
        User created = service.create(input);
        return Response.created(
                URI.create("/users/" + created.id())).entity(created).build();
    }
}

Application 子类可以使用 @ApplicationPath("/api") 注解。 外围容器或实现决定请求如何到达 JAX-RS 运行时。

绑定请求 #

为非请求体方法参数添加注解,标明其来源:

  • @PathParam、@QueryParam 和 @MatrixParam 读取 URI 组件。
  • @HeaderParam、@CookieParam 和 @FormParam 读取标头、Cookie 和表单数据。
  • @Context 注入 JAX-RS 上下文对象。
java
@GET
public Response search(
        @QueryParam("q") String query,
        @QueryParam("limit") @DefaultValue("20") int limit) {
    return Response.ok(service.search(query, limit)).build();
}

未注解的资源方法参数通常是请求实体。其 Java 类型必须受到 MessageBodyReader 支持; 例如,从 JSON 绑定到对象需要已安装的 JSON 提供程序。声明 @Consumes 以使契约明确。 InputStream 可以接受原始实体,但单独的核心 JAX-RS 不会解析 multipart/form-data; 应使用受支持的多部分提供程序,例如 Jersey 的 multipart 模块。

使用 @BeanParam 将多个参数绑定组合到一个 bean:

java
public class PageRequest {
    @QueryParam("offset") @DefaultValue("0") int offset;
    @QueryParam("limit") @DefaultValue("20") int limit;
}

将其作为 @BeanParam PageRequest page 使用。可以显式验证输入, 也可以使用运行时提供的 Jakarta Validation 集成。

生成响应和错误 #

方法可以直接返回实体,也可以返回 Response 来显式控制状态、标头和实体。 @Produces 参与内容协商。返回适当的状态和稳定的错误表示;不要向客户端暴露堆栈跟踪。

抛出 WebApplicationException(例如 NotFoundException 或 BadRequestException)会提供 HTTP 响应。 对于应用程序异常,编写 ExceptionMapper<T> 并使用 @Provider 标注:

java
@Provider
public class IllegalArgumentMapper
        implements ExceptionMapper<IllegalArgumentException> {
    public Response toResponse(IllegalArgumentException error) {
        return Response.status(Response.Status.BAD_REQUEST)
                .entity(Map.of("error", error.getMessage())).build();
    }
}

运行时会选择适用的映射器,其异常类型是所抛异常的最近超类型。 如果没有适用映射器,则根据容器集成生成服务器错误响应。

使用 Jersey 部署 #

Jersey 实现 JAX-RS 契约,但本身不接受 TCP 连接。在 servlet 容器中, 添加 org.glassfish.jersey.containers:jersey-container-servlet, 注册 org.glassfish.jersey.servlet.ServletContainer,并配置资源包扫描或 ResourceConfig。

对于嵌入式服务器,创建 ResourceConfig 并将其传递给受支持的 Jersey 容器。 尽可能让应用代码依赖 jakarta.ws.rs,并将 Jersey 特定配置隔离在部署边界。

评论

在 GitHub 上阅读或评论(发表评论需要登录)