我正在使用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}

我还有其他要求:


  如果未指定版本,则默认情况下应使用最新版本-即,


GET /appapi/users应等效于GET /appapi/v1.1/users(假定1.1是用户的最新版本)。

这就是我使用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();
    }
}


我的Sub-Resource类的定义如下。我有此类的子类来处理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();
    }
}



  问题陈述:
  
  
  如果我注释掉getDefaultApiResource(),则当API中有版本说明符时,一切都会按预期进行。但是,如果我取消注释getDefaultApiResource(),则无论是否在请求中包含v1.0,都会始终调用它。
  另外,如果取消注释getDefaultApiResource(),则在执行GET /appapi/users时得到404(即,没有版本说明符);但是如果我使用GET /appapi/v1.0/users(例如,使用版本说明符),一切正常
  


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

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

最佳答案

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

我从来没有尝试过,但我认为@Path(“”)会做您想要的。

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

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


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

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

09-11 18:11