英文:
Spring request mapping with regex like in javax.ws.rs
问题
我正尝试将此Google App Engine Maven服务器存储库重写为Spring。
我在URL映射方面遇到了问题。
Maven存储库服务器的标准URL如下:
-
以斜杠结尾的URL指向一个文件夹,例如:
http://127.0.0.1/testDir/ http://127.0.0.1/testDir/testDir2/
-
所有其他(结尾没有斜杠)的URL指向文件,例如:
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
之前使用了@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调度程序。
英文:
I'm trying rewrite this Google App Engine maven server repository to Spring.
I have problem with URL mapping.
Maven repo server standard looks like this:
-
URL with slash at the end, points to a folder, example:
http://127.0.0.1/testDir/ http://127.0.0.1/testDir/testDir2/
-
all others (without slash at the end) point to files, example:
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
Original app mapping for directories and for files.
There were used annotations @javax.ws.rs.Path
which supports regexy differently than Spring.
I tried bunch of combinations, for example something like this:
@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;
}
But I can't figure out how to do this in right way in Spring application.
I'd like to avoid writing a custom servlet dispatcher.
答案1
得分: 1
// 一个类似的问题曾经困扰过我,与一个使用Maven端点的Spring实现有关。
// 对于文件端点,你可以这样做
/**
* 用于Jar文件的示例Maven端点
*/
@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) {
// 与之前一样从requestUri中提取groupId
...
}
英文:
I had a similar problem once, also regarding a Spring implementation of a maven endpoint.
For the file endpoints, you could do something like this
/**
* 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) {
...
}
This gives you the artifactId
and the version
, but for the groupId
you would need to do some string parsing. You can get the current requestUri
with the help of the ServletUriComponentsBuilder
String requestUri = ServletUriComponentsBuilder.fromCurrentRequestUri().build().toUri().toString();
// requestUri = /api/v1/com/my/groupId/an/artifact/v1/an-artifact-v1.jar
For the folder endpoints, I'm not sure if this will work, but you can give it a try
@GetMapping("/**/{artifactId}/{version}")
public ResponseEntity<String> getJar(@PathVariable("artifactId") String artifactId, @PathVariable("version") String version) {
// groupId extracted as before from the requestUri
...
}
答案2
得分: 0
不了解你的 Java 代码,但如果你逐个验证路径,只需检查字符串是否以 "/" 结尾,对于文件夹,字符串以 "/" 结尾,而对于文件,则不是。
\/{1}$
这个正则表达式只检查字符串是否以 "/" 结尾。如果匹配成功,表示是文件夹;如果匹配不成功,表示是文件。
英文:
Don't know about your java code, but if you are verifying one path at a time, you can just check if the string ends in "/" for a folder and the ones that don't are files
\/{1}$
this regular expression just checks that the string ends with "/" if there is a match, you have a folder, if there is not, you have a file
答案3
得分: 0
以下是翻译好的内容:
原始代码中,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", "你希望对文件执行的操作类型",
"directory", "你希望对目录执行的操作类型"
);
@GetMapping(path = "/{type:file|directory}")
public String myFileOperationControl(@PathVariable String type) {
return "Test" + managedEntities.get(type);
}
然后根据你的业务逻辑继续进行。如果有任何问题,请随时告诉我。
**注意:** 根据你的需求简单地增强端点即可。
英文:
Well there is no other specific standard in Spring then the way you have used it. However if you can customize URL then I have a special way to differentiate directory and files. That will increase the scalibility and readability of application and will reduce lot of code for you.
Your Code as of now
@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;
}
Change above code to as below in your controller class
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));
}
And proceed further the way you want to per your business logic. Let me know if you have any questions.
Note: Please simply enhance endpoint per your need.
答案4
得分: 0
Spring不允许匹配跨越多个路径段。路径段是路径分隔符(/)上的分隔值。因此,没有正则表达式组合可以实现此目的。虽然Spring 5允许仅在路径末尾使用**或{*foobar}来捕获foobar uri模板变量以在响应式堆栈中跨越多个路径段,但我认为这对您可能没有用。
您的选择有限。我认为如果可能的话,最好的选择是使用不同于/的分隔符,并且您可以使用正则表达式。
另一个选择(虽然有些混乱)是拥有一个捕获所有(**)的端点,然后从请求中读取路径并确定它是文件路径还是目录路径,并执行相应的操作。
英文:
Spring doesn't allow matching to span multiple path segments. Path segments are delimited values of path on path separator (/). So no regex combination will get you there. Spring 5 although allows the span multiple path segments only at the end of path using ** or {*foobar} to capture in foobar uri template variable for reactive stack but I don't think that will be useful for you.
Your options are limited. I think the best option if possible is to use different delimiter than / and you can use regex.
Other option ( which is messy ) to have catch all (**) endpoint and read the path from the request and determine if it is file or directory path and perform actions.
答案5
得分: -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;
}
Results for URIs from the question:
test2 /testDir/
test2 /testDir/testDir2/
test1 testFile.jar
test1 testFile.jar.sha1
test1 testFile2.pom
test1 testFile2.pom.md5
<details>
<summary>英文:</summary>
Try this solution:
```java
@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;
}
Results for URIs from the question:
test2 /testDir/
test2 /testDir/testDir2/
test1 testFile.jar
test1 testFile.jar.sha1
test1 testFile2.pom
test1 testFile2.pom.md5
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论