web-dev-qa-db-ja.com

javax.ws.rsのような正規表現によるSpringリクエストのマッピング

私は このGoogle App Engine mavenサーバーリポジトリ をSpringに書き換えようとしています。

URLマッピングに問題があります。 Mavenリポジトリサーバーの標準は次のようになります。

  1. 末尾にスラッシュが付いたURLはフォルダーを指します。例:

    http://127.0.0.1/testDir/
    http://127.0.0.1/testDir/testDir2/
    
  2. 他のすべてのファイル(末尾にスラッシュなし)はファイルを指します。例:

    http://127.0.0.1/testFile.jar
    http://127.0.0.1/testFile.jar.sha1
    http://127.0.0.1/testDir/testFile2.pom
    http://127.0.0.1/testDir/testFile2.pom.md5
    

directories および files の元のアプリマッピング。

使用された注釈がありました@javax.ws.rs.Pathこれは、regexyをSpringとは異なる方法でサポートします。

私は次のような組み合わせをたくさん試しました:

@ResponseBody
@GetMapping("/{file: .*}")
public String test1(@PathVariable String file) {
    return "test1 " + file;
}

@ResponseBody
@GetMapping("{dir: .*[/]{1}$}")
public String test2(@PathVariable String dir) {
    return "test2 " + dir;
}

しかし、Springアプリケーションでこれを正しく行う方法を理解できません。

カスタムサーブレットディスパッチャーの作成を避けたいのですが。

7
Artur Węgrzyn

Springは、複数のパスセグメントにまたがるマッチングを許可しません。パスセグメントは、パス区切り文字(/)で区切られたパスの値です。そのため、正規表現の組み合わせはありません。 Spring 5では、パスの最後でのみ**または{* foobar}を使用して複数のパスセグメントにまたがることができます。

オプションは限られています。可能であれば、/とは異なる区切り文字を使用するのが最善のオプションだと思います。正規表現を使用できます。

すべての(**)エンドポイントをキャッチし、リクエストからパスを読み取り、それがファイルパスかディレクトリパスかを判断してアクションを実行するためのその他のオプション(乱雑です)。

1
Sagar Veeram

MavenエンドポイントのSpring実装に関しても、同様の問題が1回ありました。

ファイルのエンドポイントについては、次のようなことができます

/**
 * An example Maven endpoint for Jar files
 */
@GetMapping("/**/{artifactId}/{version}/{artifactId}-{version}.jar")
public ResponseEntity<String> getJar(@PathVariable("artifactId") String artifactId, @PathVariable("version") String version) {
   ...
}

これによりartifactIdversionが得られますが、groupIdの場合は文字列の解析が必要になります。 requestUriの助けを借りて、現在のServletUriComponentsBuilderを取得できます

String requestUri = ServletUriComponentsBuilder.fromCurrentRequestUri().build().toUri().toString();
// requestUri = /api/v1/com/my/groupId/an/artifact/v1/an-artifact-v1.jar

フォルダエンドポイントの場合、これが機能するかどうかはわかりませんが、試してみることができます

@GetMapping("/**/{artifactId}/{version}")
public ResponseEntity<String> getJar(@PathVariable("artifactId") String artifactId, @PathVariable("version") String version) {
   // groupId extracted as before from the requestUri
   ...
}
1
Ahmed Sayed

さて、Springには、あなたがそれを使用した方法以外に特定の標準はありません。ただし、URLをカスタマイズできる場合は、ディレクトリとファイルを区別する特別な方法があります。これにより、アプリケーションのスケーラビリティと可読性が向上し、多くのコードが削減されます。

現在のコード

@ResponseBody
@GetMapping("/{file: .*}")
public String test1(@PathVariable String file) {
    return "test1 " + file;
}

@ResponseBody
@GetMapping("{dir: .*[/]{1}$}")
public String test2(@PathVariable String dir) {
    return "test2 " + dir;
}

上記のコードをコントローラークラスで以下のように変更します

private final Map<String, String> managedEntities=ImmutableMap.of(
        "file","Type_Of_Operation_You_want_For_File",
        "directory","Type_Of_Operation_You_want_For_Directory"
        );

@GetMapping(path = "/{type:file|directory}")
public String myFileOperationControl(@PathVariable String type){
        return "Test"+managedEntities.get(type));
        }

そして、ビジネスロジックごとに、希望する方法をさらに進めます。ご不明な点がありましたらお知らせください。

注:必要に応じてエンドポイントを拡張してください。

0
Kunal Vohra

Javaコードについてはわかりませんが、一度に1つのパスを確認する場合は、フォルダの文字列が「/」で終了しているかどうかを確認できます。 tはファイルです

\/{1}$

この正規表現は、一致がある場合は文字列が「/」で終わることを確認するだけです。一致する場合はフォルダがあり、一致しない場合はファイルがあります。

0
xploshioOn