Spring Boot 中的 @PathVariable 在 URL 中带有斜杠

@PathVariable in SpringBoot with slashes in URL

我必须在 SpringBoot 应用程序中使用 @PathValiable 从 URL 获取参数。这些参数通常有 斜杠 。我无法控制用户在 URL 中输入的内容,所以我想获取他输入的内容,然后我可以处理它。

我已经在这里查看了材料和答案,我认为对我来说好的解决方案不是要求用户以某种方式对输入的参数进行编码。

SpringBoot代码简单:

@RequestMapping("/modules/{moduleName}")
@ResponseBody
public String moduleStrings (@PathVariable("moduleName") String moduleName) throws Exception {

  ...

}

因此 URL 例如如下:

http://localhost:3000/modules/...

问题是参数 moduleName 经常有斜杠。 例如,

metadata-api\cb-metadata-services OR
app-customization-service-impl\modules\expand-link-schemes\common\app-customization-service-api

所以用户肯定可以输入:

http://localhost:3000/modules/metadata-api\cb-metadata-services

是否可以在 /modules/ 之后获取用户在 URL 中输入的所有内容?

如果有人告诉我处理此类问题的好方法是什么。

这段代码获取完整路径:

@RequestMapping(value = "/modules/{moduleBaseName}/**", method = RequestMethod.GET)
@ResponseBody
public String moduleStrings(@PathVariable String moduleBaseName, HttpServletRequest request) {
    final String path =
            request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE).toString();
    final String bestMatchingPattern =
            request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE).toString();

    String arguments = new AntPathMatcher().extractPathWithinPattern(bestMatchingPattern, path);

    String moduleName;
    if (null != arguments && !arguments.isEmpty()) {
        moduleName = moduleBaseName + '/' + arguments;
    } else {
        moduleName = moduleBaseName;
    }

    return "module name is: " + moduleName;
}

根据 P.J.Meisch 的回答,我找到了适合我的案例的简单解决方案。它还允许在 URL 参数中考虑 几个斜杠 。它也不允许像以前的答案那样使用反斜杠。

@RequestMapping(value = "/modules/**", method = RequestMethod.GET)
@ResponseBody
public String moduleStrings(HttpServletRequest request) {

    String requestURL = request.getRequestURL().toString();

    String moduleName = requestURL.split("/modules/")[1];

    return "module name is: " + moduleName;

}

这是学校作业还是什么?为什么要在路径中放置自由文本?相反,为什么不使用参数变量呢?

我不确定让用户输入包含自由文本的复杂网址是个好主意。其一,用户很难记住复杂的 url,因此它不是用户友好的。其次,他们可以做一些奇怪的事情。

取而代之的是让他们访问一个主页,该主页可能包含链接(或类似的链接)以将他们带到其他页面。如果他们需要输入自由文本,请给他们一个用于添加数据的文本框,一个可以单击的按钮,它会发出类似于 ajax 包含数据的调用。该路径将包含除自由文本之外的所有内容。你可以这样做...

@RequestMapping(value = "/modules/{moduleBaseName}", method = RequestMethod.GET)
@ResponseBody
public String moduleStrings(@PathVariable String moduleBaseName,
                            @RequestParam(value = "moduleName", required = false) String moduleName 
                            HttpServletRequest request) 
{
    return "module name is: " + moduleName;
}

然后在客户端,您只需将 ajax 调用中的数据属性设置为包含 "moduleName" 属性的 json。像这样。

var params = {};
params.moduleName = userEnteredText;
jQuery.ajax({
    type: "GET",
    url: 'http://localhost:3000/modules'.json'),
    dataType: "json",
    data: params,
    async: true,
    success: function(data) { callback(data); },
    error: function() { alert("Error!!!"); }
});
import org.springframework.web.util.UriUtils;

@RequestMapping(value = "/modules/**", method = RequestMethod.GET)
@ResponseBody
public String moduleStrings(HttpServletRequest request) {
    final String url = request.getRequestURL().toString();
    final String modules = url.split("/modules")[1];
    final String safeModules = UriUtils.decode(modules, StandardCharsets.UTF_8);
        
    return "replaces %20 with space";
}