JAX-RS规范介绍

JAX-RS 规范详解 一、什么是 JAX-RS? JAX-RS(Java API for RESTful Web Services)是 Jakarta EE(原 Java EE)提供的一套用于构建 RESTful Web 服务的 API 规范。它定义了一套用于将 Java 类映射为 Web 资源的方法,广泛用于微服务 …

JAX-RS 规范详解

一、什么是 JAX-RS?

JAX-RS(Java API for RESTful Web Services)是 Jakarta EE(原 Java EE)提供的一套用于构建 RESTful Web 服务的 API 规范。它定义了一套用于将 Java 类映射为 Web 资源的方法,广泛用于微服务、前后端分离架构和 API 开发。

JAX-RS 在 Jakarta EE 9 中迁移到了 jakarta.ws.rs 命名空间,之前为 javax.ws.rs


二、设计目标

JAX-RS 的设计目标包括:

  • 简化 RESTful 服务开发
  • 注解驱动的声明式编程模型
  • 与 HTTP 方法和资源 URI 紧密集成
  • 易于扩展(拦截器、过滤器、实体提供者)
  • 支持内容协商(Content Negotiation)
  • 规范与实现分离,支持多种实现(如 Jersey、RESTEasy、Apache CXF)

三、核心注解和说明

1. @Path

定义类或方法处理的 URI 路径。

@Path("/users")
public class UserResource {
    @GET
    public String listUsers() {
        return "List of users";
    }
}
  • 支持动态路径参数 /users/{id}
  • 类上的 @Path 是基础路径,方法上的路径会拼接。

2. HTTP 方法注解

这些注解表明方法响应特定的 HTTP 动作:

  • @GET:获取资源
  • @POST:创建资源
  • @PUT:更新资源
  • @DELETE:删除资源
  • @PATCH:部分更新
  • @HEAD / @OPTIONS:特殊用途
@GET
@Path("/{id}")
public String getUser(@PathParam("id") int id) {
    return "User with ID: " + id;
}

3. 参数注解

用于绑定 HTTP 请求数据:

注解来源
@PathParamURL 路径
@QueryParamURL 查询参数
@HeaderParamHTTP Header
@CookieParamCookie 值
@MatrixParamURL 矩阵参数
@FormParam表单字段
@Context注入上下文信息对象(如 UriInfo, HttpHeaders
@GET
@Path("/search")
public String search(@QueryParam("q") String query) {
    return "Searching for: " + query;
}

4. @Produces@Consumes

用于声明处理的媒体类型(MIME types)。

@GET
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
public User getUser(@PathParam("id") int id) {
    return userService.find(id);
}

@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response addUser(User user) {
    userService.save(user);
    return Response.ok().build();
}

支持类型如:

  • MediaType.APPLICATION_JSON
  • MediaType.APPLICATION_XML
  • MediaType.TEXT_PLAIN
  • 自定义类型,如 application/vnd.myapp+json

四、响应构造器 jakarta.ws.rs.core.Response

Response 是一个强类型响应类,用于定制状态码、实体、头部等。

return Response.status(Response.Status.CREATED)
               .entity(user)
               .header("Location", "/users/123")
               .build();

常用状态码

状态码含义
200OK
201Created
204No Content
400Bad Request
401Unauthorized
404Not Found
500Internal Server Error

五、内容协商(Content Negotiation)

通过 HTTP 的 AcceptContent-Type 头部,服务端可以自动处理客户端请求的内容格式。

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

客户端:

curl -H "Accept: application/xml" http://localhost:8080/api/user

六、异常处理:ExceptionMapper

可通过实现 ExceptionMapper<T> 捕获并转换异常为 HTTP 响应。

@Provider
public class GenericExceptionMapper implements ExceptionMapper<Throwable> {
    public Response toResponse(Throwable ex) {
        return Response.status(500)
                       .entity("Error: " + ex.getMessage())
                       .type(MediaType.TEXT_PLAIN)
                       .build();
    }
}

注册后自动生效。

七、请求过滤器与拦截器

1. 请求/响应过滤器(ContainerRequestFilter / ContainerResponseFilter

用于处理请求前后逻辑,例如日志、认证、CORS。

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

2. 实体拦截器(ReaderInterceptor / WriterInterceptor

拦截 HTTP 实体读写,用于加密、压缩等。

@Provider
public class GzipWriterInterceptor implements WriterInterceptor {
    public void aroundWriteTo(WriterInterceptorContext ctx) throws IOException {
        // wrap output stream with gzip
        ctx.proceed();
    }
}

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

可自定义如何序列化与反序列化 Java 对象与 HTTP 实体。

@Provider
@Consumes("application/myformat")
public class MyFormatReader implements MessageBodyReader<MyObject> {
    public MyObject readFrom(...) {
        // 读取并解析输入流
    }
}

九、客户端 API(jakarta.ws.rs.client

JAX-RS 提供标准 REST 客户端:

Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://localhost:8080/api/users/1");
User user = target.request(MediaType.APPLICATION_JSON).get(User.class);

POST 示例:

User newUser = new User("Alice", 30);
Response response = client.target("http://localhost:8080/api/users")
    .request()
    .post(Entity.entity(newUser, MediaType.APPLICATION_JSON));

十、完整示例:用户资源类

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

    private static Map<Integer, User> users = new HashMap<>();
    private static AtomicInteger idCounter = new AtomicInteger();

    @GET
    public Collection<User> getAll() {
        return users.values();
    }

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

    @POST
    public Response createUser(User user) {
        int id = idCounter.incrementAndGet();
        user.setId(id);
        users.put(id, user);
        return Response.status(201).entity(user).build();
    }

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

    @DELETE
    @Path("/{id}")
    public Response deleteUser(@PathParam("id") int id) {
        users.remove(id);
        return Response.noContent().build();
    }
}

对应实体类:

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

    // Constructors, getters, setters
}

十一、与 Jakarta EE 其他技术集成

  • JPA:用于持久化实体对象
  • CDI:用于依赖注入与生命周期管理
  • Bean Validation:用于输入校验(如 @NotNull, @Size

示例:

@POST
public Response addUser(@Valid User user) {
    em.persist(user); // EntityManager 注入的
    return Response.status(201).entity(user).build();
}

十二、部署方式

1. Jakarta EE 容器

将资源类打包为 .war 部署到如 GlassFish、Payara、WildFly。

2. 使用 Jersey 独立部署

public class Main {
    public static void main(String[] args) {
        ResourceConfig config = new ResourceConfig().packages("com.example.api");
        HttpServer server = GrizzlyHttpServerFactory.createHttpServer(
            URI.create("http://localhost:8080/api/"), config);
    }
}

十三、小结

特性支持情况
注解驱动 REST API
内容协商
参数绑定与注入
异常处理
请求/响应拦截器
自定义序列化/反序列化
客户端访问 API
与 CDI / JPA / Bean Validation 集成

继续阅读

探索更多技术文章

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

全部文章 返回首页