0

JAX-RSを使用してRESTfulAPIを開発しています。私の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がユーザーの最新バージョンであると想定)。

これが、JAXRSを使用してこれを実装した方法です。

@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();
    }
}

問題文:

  • コメントアウトするgetDefaultApiResource()と、APIにバージョン指定子がある場合、期待どおりに機能します。ただし、コメントgetDefaultApiResource()を解除すると、リクエストにv1.0が含まれているかどうかに関係なく、常に呼び出されます。
  • また、コメントを外すと、 (つまり、バージョン指定子なしで)getDefaultApiResource()実行すると404が返されます。GET /appapi/usersしかし、私が使用すればGET /appapi/v1.0/users(つまり、バージョン指定子を使用して)問題なく動作します

では、リクエストにバージョン指定子がないときにメソッドが呼び出されるように、サブリソースロケーターパス/正規表現を設定するにはどうすればよいですか?

Restletフレームワークを使用していますが、この質問は実装に依存しません。

4

1 に答える 1

2

getDefaultApiResourceが常に呼び出される理由は、そのURIパターンがgetVersionedSubResourceの正規表現と同じであり、複数のパターンが要求URIに一致する場合、最も長いパターン(文字通り最も文字数の多いパターン)が優先されるためです。(「バージョン:」はパターンの一部とは見なされません。)すべての詳細については、JAX-RS仕様のセクション3.7.2を参照してください。

私はこれを試したことがありませんが、@ Path( "")はあなたが望むことをするだろうと思います。

ちなみに、あなたの正規表現は完全に正しくないようです:

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

これは、「小文字のvの後に、1つ以上の数字が続き、オプションで1つのピリオド、数字、またはプラス記号が続く」という意味です。そのはず:

[v]\\d+([.]\\d+)?
于 2012-12-13T11:55:54.750 に答える