Jakarta RESTful Web Services介绍

Jakarta RESTful Web Services( )详解 一、简介 是 Jakarta EE 规范的一部分,用于构建符合 REST 架构风格的 Web 服务。

Jakarta RESTful Web Services(jakarta.ws.rs)详解

一、简介

jakarta.ws.rs 是 Jakarta EE 规范的一部分,用于构建符合 REST 架构风格的 Web 服务。它是 JAX-RS(Java API for RESTful Web Services)的 Jakarta 命名空间版本,前身是 Java EE 的 javax.ws.rs。

JAX-RS 提供了一套基于注解的简洁方式,来定义资源类、处理 HTTP 请求、生成响应,以及集成内容协商、过滤器、拦截器、异常处理等高级特性。它是 Jakarta EE 中开发 REST API 的标准方式,兼容实现包括 Jersey、RESTEasy、Apache CXF 等。

二、核心包结构

jakarta.ws.rs 包结构主要如下:

  • jakarta.ws.rs.core:核心类型,如 Response、UriInfo、MediaType 等。
  • jakarta.ws.rs.client:JAX-RS 客户端 API。
  • jakarta.ws.rs.container:服务器端容器相关 API,如过滤器、拦截器。
  • jakarta.ws.rs.ext:扩展 SPI,如自定义实体解析器。
  • jakarta.ws.rs:顶级注解接口定义,如 @Path、@GET、@POST 等。

三、基本注解与使用

JAX-RS 使用一系列注解将普通的 Java 类变成 Web 服务端点。常见注解如下:

1. 资源路径注解:@Path

@Path("/hello")
public class HelloResource {
    @GET
    public String sayHello() {
        return "Hello, World!";
    }
}
  • @Path 可用于类和方法,指定请求路径。
  • 支持路径参数,如 /users/{id}。

2. HTTP 方法注解

  • @GET:处理 GET 请求。
  • @POST:处理 POST 请求。
  • @PUT:处理 PUT 请求。
  • @DELETE:处理 DELETE 请求。
  • @HEAD、@OPTIONS、@PATCH 也支持。
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response createUser(User user) {
    // 保存用户逻辑
    return Response.status(Response.Status.CREATED).build();
}

3. 请求参数绑定注解

  • @PathParam:绑定路径参数。
  • @QueryParam:绑定查询参数。
  • @HeaderParam:绑定请求头参数。
  • @FormParam:绑定表单字段。
  • @CookieParam:绑定 Cookie 值。
@GET
@Path("/{id}")
public Response getUser(@PathParam("id") int id) {
    User user = findUserById(id);
    return Response.ok(user).build();
}

4. 消费与生产内容类型

  • @Consumes:声明请求体支持的媒体类型。
  • @Produces:声明响应体产生的媒体类型。
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response createUser(User user) {
    save(user);
    return Response.ok(user).build();
}

四、Response 与 ResponseBuilder

JAX-RS 的 Response 类型用于自定义返回信息。

return Response.status(200)
               .entity("Success")
               .header("X-Custom-Header", "value")
               .build();

常见状态码:

  • 200 OK
  • 201 Created
  • 204 No Content
  • 400 Bad Request
  • 401 Unauthorized
  • 404 Not Found
  • 500 Internal Server Error

五、JAX-RS 客户端 API(jakarta.ws.rs.client)

除了服务器端,JAX-RS 也提供了标准的 REST 客户端 API。

Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://localhost:8080/api/hello");
String response = target.request(MediaType.TEXT_PLAIN).get(String.class);

支持链式构造、请求构造器、实体封装等高级操作:

User user = new User("Tom", 25);
Response response = target
    .request()
    .post(Entity.entity(user, MediaType.APPLICATION_JSON));

六、内容协商

JAX-RS 支持基于 Accept 和 Content-Type 头部自动匹配请求与响应格式。

@GET
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public User getUser() {
    return new User("Tom", 25);
}

客户端发送请求时设置 Accept:

Accept: application/xml

服务端会自动返回 XML。

七、异常处理

可以通过定义 ExceptionMapper<T extends Throwable> 处理全局异常:

@Provider
public class NotFoundExceptionMapper implements ExceptionMapper<NotFoundException> {
    @Override
    public Response toResponse(NotFoundException ex) {
        return Response.status(Response.Status.NOT_FOUND)
                       .entity("Resource not found")
                       .build();
    }
}

八、拦截器与过滤器

过滤器主要用于修改请求或响应;拦截器则用于拦截实体的读写过程。

1. 过滤器

@Provider
public class LoggingFilter implements ContainerRequestFilter {
    public void filter(ContainerRequestContext requestContext) {
        System.out.println("Incoming request: " + requestContext.getUriInfo().getRequestUri());
    }
}

2. 拦截器

@Provider
public class LoggingReaderInterceptor implements ReaderInterceptor {
    public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException {
        InputStream in = context.getInputStream();
        // 可读取输入流日志
        return context.proceed();
    }
}

九、实体提供者(MessageBodyReader/Writer)

自定义类型的序列化与反序列化:

@Provider
@Produces("application/custom")
public class MyWriter implements MessageBodyWriter<MyObject> {
    // 实现 writeTo() 方法
}

用于扩展非标准类型(如 YAML、ProtoBuf)的处理方式。

十、部署与运行

JAX-RS 可部署在 Jakarta EE 容器(如 Payara、WildFly),也可用独立容器运行,如使用 Jersey + Jetty:

ResourceConfig config = new ResourceConfig();
config.packages("com.example.resources");

HttpServer server = GrizzlyHttpServerFactory.createHttpServer(
    URI.create("http://localhost:8080/api/"), config);

十一、完整示例项目

@Path("/users")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class UserResource {

    private static final Map<Integer, User> userDb = new HashMap<>();

    @GET
    public List<User> listUsers() {
        return new ArrayList<>(userDb.values());
    }

    @GET
    @Path("/{id}")
    public Response getUser(@PathParam("id") int id) {
        User user = userDb.get(id);
        if (user == null) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }
        return Response.ok(user).build();
    }

    @POST
    public Response createUser(User user) {
        int id = userDb.size() + 1;
        user.setId(id);
        userDb.put(id, user);
        return Response.status(Response.Status.CREATED).entity(user).build();
    }

    @PUT
    @Path("/{id}")
    public Response updateUser(@PathParam("id") int id, User updated) {
        if (!userDb.containsKey(id)) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }
        updated.setId(id);
        userDb.put(id, updated);
        return Response.ok(updated).build();
    }

    @DELETE
    @Path("/{id}")
    public Response deleteUser(@PathParam("id") int id) {
        User removed = userDb.remove(id);
        if (removed == null) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }
        return Response.noContent().build();
    }
}

对应的 User 类:

public class User {
    private int id;
    private String name;
    private int age;

    // getters and setters
}

十二、异步响应式编程

Jakarta RS 2.1 引入了响应式支持,可以通过 CompletionStage 和 Reactive Streams 实现异步处理:

import jakarta.ws.rs.*;
import jakarta.ws.rs.core.*;
import java.util.concurrent.*;

@Path("/async")
public class AsyncResource {

    @GET
    @Path("/users/{id}")
    public CompletionStage<Response> getUserAsync(@PathParam("id") String id) {
        return CompletableFuture
            .supplyAsync(() -> userService.findById(id))
            .thenApply(user -> {
                if (user == null) {
                    return Response.status(404).build();
                }
                return Response.ok(user).build();
            });
    }

    // Server-Sent Events (SSE)
    @GET
    @Path("/events")
    @Produces(MediaType.SERVER_SENT_EVENTS)
    public void streamEvents(
            @Context SseEventSink eventSink,
            @Context Sse sse) {
        executor.submit(() -> {
            for (int i = 0; i < 10; i++) {
                eventSink.send(sse.newEvent("message", "Event " + i));
                try { Thread.sleep(1000); } catch (InterruptedException e) {}
            }
            eventSink.close();
        });
    }
}

异步优势

场景同步处理异步处理
I/O 密集型线程阻塞,资源利用率低非阻塞,高并发支撑
外部服务调用等待响应,吞吐量受限释放线程,回调处理
长连接 (SSE)每个连接占用线程事件驱动,轻量化

十三、Jakarta RS 与 Spring 生态对比

特性Jakarta RSSpring Web MVC/WebFlux
规范性质标准(Jakarta EE)框架实现
注解风格@Path, @GET, @POST@RequestMapping, @GetMapping
依赖注入CDI / Jakarta InjectSpring IoC Container
响应式CompletionStage / Reactive Streams(2.1+)WebFlux 原生支持
与 Jakarta 生态集成原生支持需 Spring Boot Starter
微服务适配良好(Quarkus/Micronaut)Spring Boot 生态完善
学习曲线中等(需理解 Jakarta 规范)平缓(文档丰富、社区大)

选型建议

  • 遗留系统升级:Jakarta RS(从 javax 到 jakarta 命名空间迁移)
  • 云原生微服务:Quarkus + Jakarta RS(启动快、内存小、原生编译)
  • 全功能企业应用:Spring Boot(生态最全、社区最大)
  • 低延迟/高吞吐:Quarkus 原生模式或 Spring WebFlux(响应式)

十四、总结与建议

  • jakarta.ws.rs 提供构建 REST API 的全面能力,是 Jakarta EE 中极具实用性的 API。
  • 建议结合 Jersey、RESTEasy 等实现,搭配 CDI、JPA 等 Jakarta 技术构建完整的企业级应用。
  • REST API 文档可结合 OpenAPI(Swagger)自动生成。
  • JAX-RS 更适合无状态服务设计,适合现代微服务架构风格。
  • 在云原生趋势下,Quarkus 等框架让 Jakarta RS 焕发新生,值得关注。

Swagger/OpenAPI 集成

现代 REST API 开发中,自动化文档生成已成为标配。Swagger(OpenAPI)通过注解描述 API 接口,配合 Swagger UI 提供交互式文档:

工具用途集成方式
swagger-core注解定义JAX-RS 资源类注解
swagger-ui可视化界面静态 Web 资源嵌入
openapi-generator代码生成从 spec 生成客户端/服务端代码

Swagger 的优势在于文档与代码同源,API 变更时文档自动同步,避免了文档过时的常见问题。对于团队协作和外部接入,Swagger UI 的交互式测试功能大大降低了 API 的调用门槛。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「java」更多文章

  1. 《Spring Boot 入门》18.3 打包与运行
  2. 《Spring Boot 入门》18.2 实现
  3. 《Spring Boot 入门》18.1 需求与设计