如何使用Java Jersey将路径后缀映射到查询参数?

时间:2011-05-24 09:35:42

标签: java rest jersey

背景:我们之前使用Jersey构建了一个RESTful API,我们将uri /items.json映射到id的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',那么该属性就会正确填充。)

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

您需要另一个使用@PathParam注释的参数,并且需要在@Path注释中(在方法或类上)指定如何将这些位绑定在一起。例如,要处理类似/items/foobar42/data.json的路径,您可以执行此操作:

@GET
@Path("/items/{item}/data.json")
@Produces(MediaType.APPLICATION_JSON)
public Response getItemsJSON(@PathParam("item") String itemId,
        @DefaultValue("id") @QueryParam("selector") String selector) {
    // Now you've got an itemId and a possible selector...
}

尝试使用过滤器进行所有映射...这对我来说似乎很难,因为有一个很好的声明方式来代替它。您甚至可以在@Path中指定正则表达式,以便匹配更复杂的变量部分;我在自己的代码中这样做,以创建一个可以服务于整个分层文件系统的方法。

(请注意,{中的}支撑@Path项应与@PathParam注释中的名称匹配,并且您可以从路径中匹配多个项目必要的;只需使用几个@PathParam - 带注释的参数。)