使用正则表达式的 Spring 请求映射,如 javax.ws.rs
Posted
技术标签:
【中文标题】使用正则表达式的 Spring 请求映射,如 javax.ws.rs【英文标题】:Spring request mapping with regex like in javax.ws.rs 【发布时间】:2020-07-15 23:21:04 【问题描述】:我正在尝试将this Google App Engine maven server repository 重写为 Spring。
我的网址映射有问题。 Maven repo 服务器标准如下所示:
URL 以斜线结尾,指向一个文件夹,例如:
http://127.0.0.1/testDir/
http://127.0.0.1/testDir/testDir2/
所有其他(末尾不带斜线)指向文件,例如:
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
的注解,它支持的正则表达式与 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 应用程序中以正确的方式执行此操作。
我想避免编写自定义 servlet 调度程序。
【问题讨论】:
您没有在这两种模式中转义/
char。可能是你的问题。
【参考方案1】:
试试这个解决方案:
@GetMapping("**/file:.+?\\..+")
public String processFile(@PathVariable String file, HttpServletRequest request)
return "test1 " + file;
@GetMapping("**/dirName:\\w+")
public String processDirectory(@PathVariable String dirName, HttpServletRequest request)
String dirPath = request.getRequestURI();
return "test2 " + dirPath;
问题中 URI 的结果:
test2 /testDir/
test2 /testDir/testDir2/
test1 testFile.jar
test1 testFile.jar.sha1
test1 testFile2.pom
test1 testFile2.pom.md5
【讨论】:
【参考方案2】:不知道你的java代码,但是如果你一次验证一个路径,你可以检查字符串是否以“/”结尾的文件夹和不是文件的字符串
\/1$
这个正则表达式只是检查字符串是否以“/”结尾,如果有匹配,你有一个文件夹,如果没有,你有一个文件
【讨论】:
【参考方案3】:我曾经遇到过类似的问题,也是关于 Maven 端点的 Spring 实现。
对于文件端点,你可以这样做
/**
* 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)
...
这为您提供了artifactId
和version
,但对于groupId
,您需要进行一些字符串解析。您可以在ServletUriComponentsBuilder
的帮助下获取当前的requestUri
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
...
【讨论】:
【参考方案4】:嗯,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));
然后按照您想要的方式进一步处理您的业务逻辑。如果您有任何问题,请告诉我。
注意:请根据您的需要简单地增强端点。
【讨论】:
【参考方案5】:Spring 不允许匹配跨越多个路径段。路径段是路径分隔符 (/) 上路径的分隔值。所以没有正则表达式组合会让你到达那里。 Spring 5 虽然只允许使用 ** 或 *foobar 在 foobar uri 模板变量中捕获反应堆栈的跨多个路径段,但我认为这对你没有用。
您的选择有限。如果可能的话,我认为最好的选择是使用与 / 不同的分隔符,您可以使用正则表达式。
其他选项(这是混乱的)捕获所有(**)端点并从请求中读取路径并确定它是文件还是目录路径并执行操作。
【讨论】:
以上是关于使用正则表达式的 Spring 请求映射,如 javax.ws.rs的主要内容,如果未能解决你的问题,请参考以下文章