JAX-RS的介绍与使用

JAX-RS

简介

JAX-RS是Java API for RESTful Web Service的缩写,它是在Java中实现RESTful API的通用标准,是一组由Java EE提供的接口和注解。与传统的 servlet 模型相比,JAX-RS提供了一种可行的、更为简便、移植性更好的方式来在Java内实现RESTful服务。JAX-RS 提供的一些关键功能部件包括:

  • 一组用于声明资源类及其所支持数据类型的注释
  • 一组允许应用程序开发者访问运行时上下文的接口
  • 用于集成定制内容处理程序的可扩展框架

与JDBC类似,JAX-RS只是定义了在Java中实现RESTful API的一些标准,但是没有自己实现。具体的实现需要依赖于对应的来源,常见的JAX-RS的实现包括下面一些:

  • Apache CXF:是一个开源的Web服务框架
  • Jersey:由Sun提供的JAX-RS的参考实现框架,注意提出JAX-RS标准的也是Sun
  • RESTEasy:JBoss的实现
  • Restlet:由Jerome Louvel和Dave Pawson开发,是最早的REST框架
  • Apache Wink:是一个处于Apache软件基金会孵化器中的项目,其服务模块实现了JAX-RS规范

规范内容

在JavaEE中包含了JAX-RS中主要使用的接口和注解,它们都位于在包javax.ws.rs.* 下。JAX-RS提供了一些标注将资源类或者POJO类封装为Web资源,常用的标注包括:

  • @Path:标注资源类或方法的相对路径,如果标注在方法上,则表示具体的请求路径

  • @GET, @PUT, @POST, @DELETE:标注方法使用的HTTP请求的类型,分别对应 4 种 HTTP 方法,分别用于检索、更新、创建和删除资源的操作。在RESTful API中,请求方式+请求路径才能唯一定义一个API

    • 若要创建资源,应该使用 POST 方法

    • 若要检索某个资源,应该使用 GET 方法

    • 若要更改资源状态或对其进行更新,应该使用 PUT 方法

    • 若要删除某个资源,应该使用 DELETE 方法

  • @Produces:标注返回的MIME媒体类型,可以使用枚举类来指定,也可以使用字符串同时指定多种返回类型

    1
    2
    3
    4
    5
    @Produces(MediaType.TEXT_PLAIN)

    @Produces(MediaType.APPLICATION_JSON)

    @Produces({"application/json", "application/xml"})
  • @Consumes:标注可接受请求的MIME媒体类型,使用方式和@Produces相同,含义则正好相反

  • Param相关注解:标注方法的参数来自于HTTP请求的不同位置。在方法参数上标注对应注解之后,参数就能够获取到对应的值

    • @PathParam:标识参数来自于URL的路径

    • @QueryParam:标识参数来自于URL的查询参数

    • @HeaderParam:标识参数来自于HTTP请求的头信息

    • @CookieParam:标识参数来自于HTTP请求的Cookie

    • @FormParam:获取Post请求中表单中的数据

    • @BeanParam:获取请求参数中的数据,并用实体Bean进行封装

  • @Context:用于解析上下文参数,通过该注解可以获得UriInfo、ServletConfig、ServletContext、HttpServletRequest、HttpServletResponse和HttpHeaders等信息

Jersey的使用

Jersey是JAX-RS的一种实现,下面简单介绍相关的使用方式。

首先需要创建一个JavaWeb项目,具体创建方式可以参考JavaWeb笔记(2)-Tomcat的使用 - EverNorif。创建好Web项目之后,在pom.xml中引入如下依赖:

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
<!-- JAX-RS -->
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.1.1</version>
</dependency>
<!-- Jersey 2.34 -->
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.34</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.34</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.34</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.34</version>
</dependency>

之后在web.xml中配置如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<!-- 配置加载资源类 指定资源所在的包路径 -->
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.syh</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>

其中这里需要注意两个配置,第一个就是在servlet标签中的init-param中的value,这里需要设置的我们对应类资源的包。另一个是在servlet-mapping中的url-pattern,后续访问时会使用到这个值。

配置完成之后,就可以写一个简单的资源类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.syh;


import javax.ws.rs.*;

@Path("/message")
public class HelloWorld {

@GET
public String getMessage(){
return "Hello World!";
}

@POST
@Path("/{text}")
public String postMessage(@PathParam("text") String text){
System.out.println("post...");
System.out.println(text);
return "success";
}
}

这表示我们现在有Message的资源,通过Get方法可以进行访问。启动Web项目之后,则可以访问如下的链接:http://localhost:8080/<context-path>/rest/message,就会得到Hello World信息。这里的/rest就是在web.xml中的配置,/message则是在资源类中Path注解的值。同时也可以发送对应的post请求:http://localhost:8080/<context-path>/rest/message/<text>,之后在控制台就会输出对应的text的内容

结合SpringBoot使用

在开发Web项目时,我们更多会使用SpringBoot。而在SpringBoot中结合使用JAX-RS,能帮助我们更方便的创建RESTful风格的API。在SpringBoot中引入Jersey的依赖要简单许多,可以直接通过starter进行引入:

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>

引入依赖之后,我们可以创建如下的资源类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.syh.resource;

import org.springframework.stereotype.Component;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

@Component
@Path("message")
public class MessageResource {

@GET
@Path("sayHello")
@Produces(MediaType.APPLICATION_JSON)
public String sayHello(@QueryParam("msg") String msg){
System.out.println("get hello: " + msg);
return "success:" + msg;
}
}

其中message表示资源路径,sayHello表示访问路径。

为了在SpringBoot中使用Jersey,我们需要进行相关的配置。Springboot中对Jersey的配置有三种方式:第一种方式创建一个自定义的ResourceConfig;第二种方式,是返回一个ResourceConfig类型的@Bean,第三种方式,配置一组ResourceConfigCustomizer对象。这里我们使用第一种方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.syh.config;

import com.syh.resource.MessageResource;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.context.annotation.Configuration;

import javax.ws.rs.ApplicationPath;

@Configuration
@ApplicationPath("resource")
public class JerseyConfiguration extends ResourceConfig {
public JerseyConfiguration(){
register(MessageResource.class);
}
}

首先这个配置类继承了ResourceConfig,并且使用@Configuration进行标注。在这个类中我们需要完成资源类的注册,注册后的资源才能够进行访问。Springboot默认把Jersey的根路径映射在/*上;如果要更改默认的根路径设置,对于自定义的ResourceConfig方式来说,可以在类上面添加一个@ApplicationPath注解即可。当然也可以在application.yaml中添加配置来改变项目的根路径:

1
2
3
spring:
jersey:
application-path: resource

至此我们就完成了Jersey在SpringBoot中的结合。启动项目之后,可以访问对应的资源,使用链接http://localhost:8080/resource/message/sayHello?msg=hahaha,这样就能够访问到对应的资源,在控制台中也会打印出对应的提示信息。

参考文章

  1. JAX-RS - wikipedia
  2. IBM JAX-RS 入门
  3. Jersey (JAX-RS) 教程
  4. SpringBoot2 整合 JAX-RS
  5. Jersey框架入门学习

JAX-RS的介绍与使用
http://example.com/2023/03/01/JAX-RS的介绍与使用/
作者
EverNorif
发布于
2023年3月1日
许可协议