将来自 REST 调用的 @PathParam 值存储在列表或数组中

Posted

技术标签:

【中文标题】将来自 REST 调用的 @PathParam 值存储在列表或数组中【英文标题】:Store @PathParam values from REST call in a list or array 【发布时间】:2015-01-15 12:25:40 【问题描述】:

我的函数如下所示:

    @PUT
    @Path("property/uuid/key/value")
    @Produces("application/xml")    
    public Map<String,ValueEntity> updateProperty(@Context HttpServletRequest request,
            @PathParam("key") String key,
            @PathParam("value") String value,
            @PathParam("uuid") String uuid) throws Exception 
                                       ...
                             

我必须修改它,所以它接受来自 REST 调用的不定(或多个)键值对列表,类似于

@Path("property/uuid/key1/value1/key2/value2/key3/value3/...")

是否可以将它们存储在数组或列表中,所以我不列出几十个@PathParams和参数,以避免这种情况:

@PathParam("key1") String key1,
@PathParam("key2") String key2,
@PathParam("key3") String key3,

【问题讨论】:

【参考方案1】:

解决方法:

@Path("/foo/bar/other: .*
public Response foo(@PathParam("other") VariableStrings vstrings) 

   String[] splitPath = vstrings.getSplitPath();



VariableStrings 类:

public class VariableStrings 

   private String[] splitPath;

   public VariableStrings(String unparsedPath) 
     splitPath = unparsedPath.split("/");
   

Path segment sequence to vararg array in JAX-RS / Jersey?

另一个将可选参数映射到 Map 的示例:

@GET
@ Produces("application/xml", "application/json", "plain/text")
@ Path("/location/locationIdpath:.*")
public Response getLocation(@PathParam("locationId") int locationId, @PathParam("path") String path) 
    Map < String, String > params = parsePath(path);
    String format = params.get("format");
    if ("xml".equals(format)) 
        String xml = "<location<</location<<id<</id<" + locationId + "";
        return Response.status(200).type("application/xml").entity(xml).build();
     else if ("json".equals(format)) 
        String json = " 'location' :  'id' : '" + locationId + "'  ";
        return Response.status(200).type("application/json").entity(json).build();
     else 
        String text = "Location: id=" + locationId;
        return Response.status(200).type("text/plain").entity(text).build();
    


private Map < String, String > parsePath(String path) 
    if (path.startsWith("/")) 
        path = path.substring(1);
    
    String[] pathParts = path.split("/");
    Map < String, String > pathMap = new HashMap < String, String > ();
    for (int i = 0; i < pathParts.length / 2; i++) 
        String key = pathParts[2 * i];
        String value = pathParts[2 * i + 1];
        pathMap.put(key, value);
    
    return pathMap;

【讨论】:

【参考方案2】:

可能是重新思考此设计的好机会。通过使用/s,我们在某种程度上表示,每个/ 都在尝试定位不同的资源。键/值对(在 URL 的上下文中)主要用于查询参数或矩阵参数。

如果/property/uuid是一个主资源的路径,我们只是想提供一些参数给客户端访问这个资源,那么我们可以允许矩阵参数或查询参数

矩阵参数(在请求网址中)看起来像

/12345;key1=value1;key2=value2;key3=value3

获取值的资源方法可能类似于

@GET
@Path("/property/uuid")
public Response getMatrix(@PathParam("uuid") PathSegment pathSegment) 
    StringBuilder builder = new StringBuilder();

    // Get the uuid value
    System.out.println("Path: " + pathSegment.getPath());

    MultivaluedMap matrix = pathSegment.getMatrixParameters();
    for (Object key : matrix.keySet()) 
        builder.append(key).append(":")
               .append(matrix.getFirst(key)).append("\n");
    
    return Response.ok(builder.toString()).build();

PathSegment

查询参数(在请求网址中)可能类似于

/12345?key1=value1&key2=value2&key3=value3

获取值的资源方法可能类似于

@GET
@Path("/property/uuid")
public Response getQuery(@PathParam("uuid") String uuid, 
                         @Context UriInfo uriInfo) 

    MultivaluedMap params = uriInfo.getQueryParameters();
    StringBuilder builder = new StringBuilder();
    for (Object key : params.keySet()) 
        builder.append(key).append(":")
               .append(params.getFirst(key)).append("\n");
    
    return Response.ok(builder.toString()).build();

UriInfo

不同的是,矩阵参数可以嵌入到路径段中,而查询参数必须放在 URL 的末尾。您还可以注意到语法上的一些差异。


一些资源

Query String (Wikipedia) When to use query parameters versus matrix parameters? URL matrix parameters vs. request parameters

更新

同时查看方法签名中的PUT,您似乎正在尝试使用路径作为您尝试更新的值来更新资源,因为我在您的方法中没有看到任何参数实体体。放置时,您应该在实体主体中发送表示,而不是作为路径段参数。

【讨论】:

非常感谢。我调整了你的建议,效果很好。

以上是关于将来自 REST 调用的 @PathParam 值存储在列表或数组中的主要内容,如果未能解决你的问题,请参考以下文章

用 GraphQL 替换 REST 调用

在 REST 调用中使用 URI 作为参数值的最佳实践

在节点中创建 REST API 时,如何将来自对外部网站的请求的 http 响应流式传输到原始 api 调用?

来自 html 的 REST API 调用不起作用

用 Java 技术创建 RESTful Web 服务/@Path@Produces@PathParam

使用来自 Spring Security 的密码来验证 REST 调用