如何使用 Java Jersey 将路径后缀映射到查询参数?
背景:我们不久前使用 Jersey 构建了一个 RESTful API,其中我们将 uri /items.json 映射到 ids 的 json 数组,将 /items/{id}.json 映射到单个项目的 json 对象。现在我们想要为每个项目创建一个包含一些元数据的列表,并希望使用像 /items.data.json 这样的选择器,类似于 apache sling。
到目前为止:我刚刚扩展了 UriConnegFilter 来解析 uri 以获取其他后缀,如下所示:
public class UriSelectorFilter extends UriConnegFilter {
protected List<String> selectors; // this list is populated in the constructor
public ContainerRequest filter(ContainerRequest request) {
super.filter(request);
// search for suffix in last path segment, see http://java.net/projects/jersey/sources/svn/content/trunk/jersey/jersey-server/src/main/java/com/sun/jersey/api/container/filter/UriConnegFilter.java?rev=5034
final String[] suffixes = segment.getPath().split("\\.");
for (int i = suffixes.length - 1; i >= 1; i--) {
final String suffix = suffixes[i];
if(selectors.contains(suffix)) {
request.getQueryParameters().putSingle("selector", suffix);
final int index = path.lastIndexOf('.' + suffix);
path = new StringBuilder(path).delete(index, index + suffix.length() + 1).toString();
suffixes[i] = "";
}
}
if (length != path.length()) {
request.setUris(
request.getBaseUri(),
request.getRequestUriBuilder().replacePath(path).build());
}
return request;
}
}
此过滤器工作完美,它找到我的 uri 的选择器部分并向请求对象添加查询参数。但在我的资源中,我添加了一个 @QueryParam 属性,该属性仅填充默认值,而不填充添加的查询值:
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getItemsJSON(@DefaultValue("id") @QueryParam("selector") String selector) {
// query param is not filled with the selector that was found in the UriSelectorFilter
}
有人建议我如何向我的资源提供检测到的选择器吗?有没有比使用 QueryParam 更好的方法? (注意:如果我将查询添加到我的网址,如“?selector=something”,则该属性将正确填充。)
非常感谢任何帮助。
Background: we have build a RESTful API using Jersey a while ago where we map the uri /items.json to a json array of ids and /items/{id}.json to the json object of a single item. Now we want to create a list with some meta data for each item and would like to use a selector like /items.data.json, similar to apache sling.
So far: I just extended the UriConnegFilter to parse the uri for additional suffixes, something like this:
public class UriSelectorFilter extends UriConnegFilter {
protected List<String> selectors; // this list is populated in the constructor
public ContainerRequest filter(ContainerRequest request) {
super.filter(request);
// search for suffix in last path segment, see http://java.net/projects/jersey/sources/svn/content/trunk/jersey/jersey-server/src/main/java/com/sun/jersey/api/container/filter/UriConnegFilter.java?rev=5034
final String[] suffixes = segment.getPath().split("\\.");
for (int i = suffixes.length - 1; i >= 1; i--) {
final String suffix = suffixes[i];
if(selectors.contains(suffix)) {
request.getQueryParameters().putSingle("selector", suffix);
final int index = path.lastIndexOf('.' + suffix);
path = new StringBuilder(path).delete(index, index + suffix.length() + 1).toString();
suffixes[i] = "";
}
}
if (length != path.length()) {
request.setUris(
request.getBaseUri(),
request.getRequestUriBuilder().replacePath(path).build());
}
return request;
}
}
This filter works perfect, it finds the selector part of my uri and adds a query param to the request object. But in my Resource I added a @QueryParam attribute, which is only filled with the default value and not the added query value:
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getItemsJSON(@DefaultValue("id") @QueryParam("selector") String selector) {
// query param is not filled with the selector that was found in the UriSelectorFilter
}
Does anybody have a suggestion how I can provide my resource with the selector that was detected? Is there a better way than using a QueryParam? (Note: if I add the query to my url like '?selector=something' then the attribute is filled correctly.)
Any help is very appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您需要另一个用
@PathParam
注释的参数,并且需要在您的@Path
注释(在方法或类上)中指定如何将这些位绑定在一起。例如,要处理像/items/foobar42/data.json
这样的路径,您可以这样做:尝试使用过滤器进行所有映射......这对我来说似乎很困难,因为有一个很好的声明这样做的方法。您甚至可以在 @Path 中指定正则表达式,以允许匹配更复杂的变量部分;我在自己的代码中这样做是为了创建一个可以为整个分层文件系统提供服务的方法。
(请注意,
@Path
中的{
braced}
项应与@PathParam
注释中的名称匹配,如果需要,您可以从路径中匹配多个项目;只需使用几个@PathParam
注释的参数。)You need another argument that is annotated with
@PathParam
, and you need to specify in your@Path
annotation (on the method or class) how to bind these bits together. For example, to deal with a path like/items/foobar42/data.json
you might do this:Trying to do all the mapping with a filter… that seems difficult to me given that there's a nice declarative way of doing it instead. You can even specify a regular expression in the
@Path
to allow for matching a more complex variable section; I do that in my own code to create a method that can serve a whole hierarchical filesystem.(Note that the
{
braced}
item in the@Path
should match the name in the@PathParam
annotation, and you can have multiple items matched from the path if necessary; just use several@PathParam
-annotated arguments.)