java - JAX-RS:提供 "default"子资源定位器

标签 java regex rest jax-rs restlet

我正在使用 JAX-RS 开发 RESTful API。我的 API 的简化版本如下:

GET /appapi/v1.0/users
POST /appapi/v1.1/users

... ... and so on

如您所见,该模式遵循 {api_name}/v{major_version}.{minor_version}/{rest_of_the_path}

我有一个额外的要求:

If the version is not specified, then the latest version should be used by default - i.e.,

GET/appapi/users 应等同于 GET/appapi/v1.1/users(假设 1.1 是 users 的最新版本)。

这就是我使用 JAX RS 实现此功能的方式。

@Path("/appapi")
public class AppApiRootResource {

    @Path("/{version: [v]\\d+[[.]\\d+]?}/")
    public AppApiSubResource getVersionedSubResource
                            (@PathParam("version") String version){
        System.out.println("Version: "+version);
        String versionString = version.substring(1); //Discard the leading 'v'
        String majorVersion = "";
        String minorVersion = "0";
        if(versionString.contains(".")){
            String [] splits = versionString.split(".");
            majorVersion = splits[0];
            minorVersion = splits[1];
        } else {
            majorVersion = versionString;
        }

        return SubResourceFactory.getSubResource(majorVersion, minorVersion);

    }

    @Path("/{^([v]\\d+[[.]\\d+]?)}/") //Is This Correct??
    public AppApiSubResource getDefaultApiResource(){
        /*
         * Need help defining the regular expression here 
         * so that this is used for anything that doesn't match
         * the "version" regexp above
         */
        System.out.println("API version not specified; Using default version");
        return SubResourceFactory.getLatestVersionSubResource();
    }
}

我的子资源类定义如下。我有这个类的子类来处理 API 的多个版本。 SubResourceFactory 的实现与本讨论的目的无关。它只返回 AppApiSubResource 或其子类的实例

public class AppApiSubResource {


    /**
     * Create a new user
     */
    @POST
    @Path("users")
    @Consumes(MediaType.APPLICATION_XML)
    public Response createUser(String newUser, @Context UriInfo uriInfo) {
        URI uri = uriInfo.getAbsolutePathBuilder().path("10")).build();       
        return Response.created(uri).build();
    }

    /**
     * Get a user
     */
    @GET
    @Path("users/{id}")
    @Produces(MediaType.APPLICATION_XML)
    public Response getUser(@PathParam("id") String userId
            ) {

        return Response.ok().entity("<user></user>").build();
    }
}

Problem statement:

  • If I comment out getDefaultApiResource(), then things work as expected when there is a version specifier in the API. However, if I un-comment getDefaultApiResource(), it is always being invoked, irrespective of whether I have the v1.0 in the request or not.
  • Also, if I un-comment getDefaultApiResource(), I get a 404 when I do a GET /appapi/users (i.e, without the version specifier); but things work fine if I use GET /appapi/v1.0/users (i.e., with a version specifier)

那么,如何设置子资源定位器路径/正则表达式,以便在请求中没有版本说明符时调用该方法?

我正在使用 ReSTLet 框架,但这个问题与实现无关。

最佳答案

getDefaultApiResource 总是被调用的原因是它的 URI 模式与 getVersionedSubResource 的正则表达式相同,并且当多个模式与请求 URI 匹配时,最长的模式(字面意思是字符数最多的模式)获胜。 (“version:”不被视为模式的一部分。)请参阅 JAX-RS specification 的第 3.7.2 节。了解所有详细信息。

我从未尝试过这个,但我认为 @Path("") 会做你想要的。

顺便说一句,您的正则表达式似乎不太正确:

[v]\\d+[[.]\\d+]?

这表示“小写 v,后跟一个或多个数字,可以选择后跟单个句点、数字或加号。”应该是:

[v]\\d+([.]\\d+)?

关于java - JAX-RS:提供 "default"子资源定位器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13857896/

相关文章:

java - 如何使用 AsyncRestTemplate 拦截 AsyncClientHttpRequest?

java - 从一系列随机字母中找到单词?

java - 带数字的antlr4语法字符串

java - 执行同步 PUT 请求时改造中的 EOFException

rest - 404 状态代码是否适用于插入时不存在的实体?

java - 将字符串拆分为指定长度的 block (最后一个除外)

regex - bash if 语句中的模式匹配

java - 括号内带有 % 符号的模式匹配

Java Regex - 不是空字符串,只有数字,8 个字符长

java - 直接从 Java 中的 REST API 响应流将大型 JSON 保存为文本