47.2.2. 从请求 URI 注入数据
概述
设计 RESTful Web 服务的最佳实践之一是每个资源都应该具有唯一 URI。开发人员可以使用这个原则为底层资源实施提供良好的信息。当为资源设计 URI 模板时,开发人员可以构建模板,使其包含可注入到资源实施中的参数信息。开发人员还可以利用查询和矩阵参数将信息传送到资源实现中。
从 URI 的路径获取数据
获取资源信息的最常见机制之一是通过为资源创建 URI 模板时使用的变量。这可以通过 javax.ws.rs.PathParam
注解来实现。@PathParam
注释具有一个参数,用于标识要注入数据的 URI 模板变量。
在 例 47.1 “从 URI 模板变量注入数据” 中,@PathParam
注释指定 URI 模板变量 颜色
的值被注入到 itemColor
字段中。
例 47.1. 从 URI 模板变量注入数据
import javax.ws.rs.Path; import javax.ws.rs.PathParam ... @Path("/boxes/{shape}/{color}") class Box { ... @PathParam("color") String itemColor; ... }
@PathParam
注释支持的数据类型与 “支持的数据类型”一节 中描述的数据类型不同。@PathParam
注释注入数据的实体必须是以下类型之一:
PathSegment
该值将是路径中匹配部分的最后一个片段。
List<PathSegment>
该值将是与指定模板参数匹配的路径片段对应的 PathSegment 对象列表。
-
原语,如
int
、char
或long
-
具有接受单个
String
参数的构造器的对象 -
具有静态
valueOf ()
方法的对象,它接受单个String
参数
使用查询参数
在 Web 上传递信息的常见方法是使用 URI 中的 查询参数。查询参数会出现在 URI 的末尾,并由问号(?
)分隔至 URI 的资源位置部分。它们由一个或多个名称值对组成,其中 name 和 值由等号(=
)分隔。当指定多个查询参数时,对通过分号(;
)或 符号( 和 )相互分离
。例 47.2 “带有查询字符串的 URI” 显示带有查询参数的 URI 的语法。
例 47.2. 带有查询字符串的 URI
http://fusesource.org?name=value;name2=value2;...
您可以使用 分号或 符号分隔查询参数,但不能同时使用这两者。
javax.ws.rs.QueryParam
注解提取查询参数的值并将其注入 JAX-RS 资源。该注释采用单个参数,用于标识提取值并注入到指定字段、bean 属性或参数中的查询参数。@QueryParam
注释支持 “支持的数据类型”一节 中描述的类型。
例 47.3 “使用查询参数中的数据的资源方法” 显示一个资源方法,用于将查询参数 id
的值注入到方法的 id
参数中。
例 47.3. 使用查询参数中的数据的资源方法
import javax.ws.rs.QueryParam; import javax.ws.rs.PathParam; import javax.ws.rs.POST; import javax.ws.rs.Path; ... @Path("/monstersforhire/") public class MonsterService { ... @POST @Path("/{type}") public void updateMonster(@PathParam("type") String type, @QueryParam("id") String id) { ... } ... }
要处理 HTTP POST
到 /monstersforhire/daikaiju?id=jonas the updateMonster ()
方法 的类型
被设置为 daikaiju
,并将 id
设置为 jonas
。
使用列表参数
URI 列表参数(如 URI 查询参数)是 name/value 对,可以提供选择资源的额外信息。与查询参数不同,列表参数可在 URI 中的任何位置显示,它们使用分号(;
)从 URI 的分层路径段中分离。/mostersforhire/daikaiju;id=jonas 有一个名为 id
和 /monstersforhi/japan; type
=daikaiju/flying;wingspan=40 的两个列表,称为 name 和 wingspan
。
当计算资源 URI 时,不会评估列表参数。因此,用来处理请求 URI /monstersforhire/japan;type=daikaiju/flying;wingspan=40 是 /monstersforhire/japan/flying 的资源的 URI /monstersforre/japan/flying。
matrix 参数的值注入使用 javax.ws.rs.MatrixParam
注解的字段、参数或 bean 属性。该注释采用单个参数,用于标识提取值并注入到指定字段、bean 属性或参数中的 list 参数的名称。@MatrixParam
注释支持 “支持的数据类型”一节 中描述的类型。
例 47.4 “使用列表参数中的数据的资源方法” 显示一个资源方法,用于将列表参数 类型和
id
的值注入到方法的参数中。
例 47.4. 使用列表参数中的数据的资源方法
import javax.ws.rs.MatrixParam; import javax.ws.rs.POST; import javax.ws.rs.Path; ... @Path("/monstersforhire/") public class MonsterService { ... @POST public void updateMonster(@MatrixParam("type") String type, @MatrixParam("id") String id) { ... } ... }
要处理 HTTP POST
到 /monstersforhire;type=daikaiju;id=whale the updateMonster ()
方法的 类型设置为
daikaiju
,并将 id
设置为 whale
。
JAX-RS 同时评估 URI 中的所有列表参数,因此它无法对 URI 中的列表参数位置实施限制。例如 /monstersforhire/japan;type=daikaiju/flying;wingspan=40 , /monstersforhire/japan/flying;type=daikaiju;wingspan=40, 和 /monstersforhire/japan; type=daikaiju;wingspan=40/flying 均被视为使用 JAX-RS API 实施的 RESTful Web 服务。
禁用 URI decoding
默认情况下,所有请求 URI 都会被解码。因此 URI /monster/night%20stalker 和 URI /monster/night stalker 等效。自动 URI 解码使得将 ASCII 字符设置之外的字符作为参数轻松发送。
如果您不想自动解码 URI,您可以使用 javax.ws.rs.Encoded
注解来取消激活 URI decoding。该注解可用于在以下级别取消激活 URI decoding:
-
使用
@Encoded
注释对类进行类进行分类,可停用课堂上所有参数、字段和 bean 属性的 URI 解码。 -
方法级别的使用
@Encoded
注释的方法取消激活了类的所有参数的 URI 解码。 -
参数/字段使用
@Encoded
注释定义参数或字段将停用 URI 解码类的所有参数。
例 47.5 “禁用 URI decoding” 显示 getMonster ()
方法不使用 URI decoding 的资源。addMonster ()
方法仅禁用 type
参数的 URI decoding。
例 47.5. 禁用 URI decoding
@Path("/monstersforhire/") public class MonsterService { ... @GET @Encoded @Path("/{type}") public Monster getMonster(@PathParam("type") String type, @QueryParam("id") String id) { ... } @PUT @Path("/{id}") public void addMonster(@Encoded @PathParam("type") String type, @QueryParam("id") String id) { ... } ... }
错误处理
如果在尝试使用某一 URI 注入注解 WebApplicationException 异常时,会发生错误来注入数据。WebApplicationException 异常的状态设置为 404
。