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
1
2
3
4
5
6
7
|
@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
也支持。
1
2
3
4
5
6
|
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response createUser(User user) {
// 保存用户逻辑
return Response.status(Response.Status.CREATED).build();
}
|
3. 请求参数绑定注解
@PathParam
:绑定路径参数。
@QueryParam
:绑定查询参数。
@HeaderParam
:绑定请求头参数。
@FormParam
:绑定表单字段。
@CookieParam
:绑定 Cookie 值。
1
2
3
4
5
6
|
@GET
@Path("/{id}")
public Response getUser(@PathParam("id") int id) {
User user = findUserById(id);
return Response.ok(user).build();
}
|
4. 消费与生产内容类型
@Consumes
:声明请求体支持的媒体类型。
@Produces
:声明响应体产生的媒体类型。
1
2
3
4
5
6
7
|
@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
类型用于自定义返回信息。
1
2
3
4
|
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。
1
2
3
|
Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://localhost:8080/api/hello");
String response = target.request(MediaType.TEXT_PLAIN).get(String.class);
|
支持链式构造、请求构造器、实体封装等高级操作:
1
2
3
4
|
User user = new User("Tom", 25);
Response response = target
.request()
.post(Entity.entity(user, MediaType.APPLICATION_JSON));
|
六、内容协商
JAX-RS 支持基于 Accept
和 Content-Type
头部自动匹配请求与响应格式。
1
2
3
4
5
|
@GET
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public User getUser() {
return new User("Tom", 25);
}
|
客户端发送请求时设置 Accept:
1
|
Accept: application/xml
|
服务端会自动返回 XML。
七、异常处理
可以通过定义 ExceptionMapper<T extends Throwable>
处理全局异常:
1
2
3
4
5
6
7
8
9
|
@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. 过滤器
1
2
3
4
5
6
|
@Provider
public class LoggingFilter implements ContainerRequestFilter {
public void filter(ContainerRequestContext requestContext) {
System.out.println("Incoming request: " + requestContext.getUriInfo().getRequestUri());
}
}
|
2. 拦截器
1
2
3
4
5
6
7
8
|
@Provider
public class LoggingReaderInterceptor implements ReaderInterceptor {
public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException {
InputStream in = context.getInputStream();
// 可读取输入流日志
return context.proceed();
}
}
|
九、实体提供者(MessageBodyReader/Writer)
自定义类型的序列化与反序列化:
1
2
3
4
5
|
@Provider
@Produces("application/custom")
public class MyWriter implements MessageBodyWriter<MyObject> {
// 实现 writeTo() 方法
}
|
用于扩展非标准类型(如 YAML、ProtoBuf)的处理方式。
十、部署与运行
JAX-RS 可部署在 Jakarta EE 容器(如 Payara、WildFly),也可用独立容器运行,如使用 Jersey + Jetty:
1
2
3
4
5
|
ResourceConfig config = new ResourceConfig();
config.packages("com.example.resources");
HttpServer server = GrizzlyHttpServerFactory.createHttpServer(
URI.create("http://localhost:8080/api/"), config);
|
十一、完整示例项目
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
@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
类:
1
2
3
4
5
6
7
|
public class User {
private int id;
private String name;
private int age;
// getters and setters
}
|
十二、总结与建议
jakarta.ws.rs
提供构建 REST API 的全面能力,是 Jakarta EE 中极具实用性的 API。
- 建议结合 Jersey、RESTEasy 等实现,搭配 CDI、JPA 等 Jakarta 技术构建完整的企业级应用。
- REST API 文档可结合 OpenAPI(Swagger)自动生成。
- JAX-RS 更适合无状态服务设计,适合现代微服务架构风格。