【问题标题】:Spring-Boot @RequestMapping and @PathVariable with regular expression matchingSpring-Boot @RequestMapping 和 @PathVariable 与正则表达式匹配
【发布时间】:2015-05-04 23:31:07
【问题描述】:

我正在尝试将 WebJars-Locator 与 Spring-Boot 应用程序一起使用来映射 JAR 资源。根据他们的website,我创建了一个这样的 RequestMapping:

@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/webjars-locator/{webjar}/{partialPath:.+}")
public ResponseEntity<ClassPathResource> locateWebjarAsset(@PathVariable String webjar, @PathVariable String partialPath)
{

问题在于 partialPath 变量应该包含第三个斜线之后的任何内容。然而,它最终会限制映射本身。此 URI 映射正确:

http://localhost/webjars-locator/angular-bootstrap-datetimepicker/datetimepicker.js

但是这个根本没有映射到处理程序,只是返回一个 404:

http://localhost/webjars-locator/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.css

根本区别只是路径中应该由正则表达式(“.+”)处理但在该部分有斜杠时似乎不起作用的组件数量。

如果有帮助,会在日志中提供:

2015-03-03 23:03:53.588 INFO 15324 --- [main] swsmmaRequestMappingHandlerMapping:映射“{[/webjars-locator/{webjar}/{partialPath:.+}],methods=[GET] ,params=[],headers=[],consumes=[],produces=[],custom=[]}" 到公共 org.springframework.http.ResponseEntity app.controllers.WebJarsLocatorController.locateWebjarAsset(java.lang.String, java.lang.String) 2

Spring-Boot 中是否有某种隐藏设置可以在 RequestMappings 上启用正则表达式模式匹配?

【问题讨论】:

  • 我创建了一个示例项目来重现该问题。此 URL 无效http://localhost:8080/webjars-locator/angular-bootstrap/datetimepicker/datetimepicker.js。但是,http://localhost:8080/gradle-spring-mvc-web-project/webjars-locator/angular-bootstrap/datetimepicker.js 工作正常。 @robross - 请确认。
  • 我绝对肯定哪些项目正确解析,哪些没有。但是,我确实注意到示例中有一个字符拼写错误并修复了它。对此感到抱歉。
  • @Mithun,您的项目似乎与我的有所不同。我不需要将我的“项目”的路径放在 URL 中。

标签: regex spring spring-mvc spring-boot webjars


【解决方案1】:

文档中的原始代码没有为额外的斜线做好准备,抱歉!

请改用此代码:

@ResponseBody
@RequestMapping(value="/webjarslocator/{webjar}/**", method=RequestMethod.GET)
public ResponseEntity<Resource> locateWebjarAsset(@PathVariable String webjar, 
        WebRequest request) {
    try {
        String mvcPrefix = "/webjarslocator/" + webjar + "/";
        String mvcPath = (String) request.getAttribute(
                HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
        String fullPath = assetLocator.getFullPath(webjar, 
                mvcPath.substring(mvcPrefix.length()));
        ClassPathResource res = new ClassPathResource(fullPath);
        long lastModified = res.lastModified();
        if ((lastModified > 0) && request.checkNotModified(lastModified)) {
            return null;
        }
        return new ResponseEntity<Resource>(res, HttpStatus.OK);
    } catch (Exception e) {
        return new ResponseEntity<>(HttpStatus.NOT_FOUND);
    }
}

我也会很快提供 webjar 文档的更新。

2015/08/05 更新:添加了 If-Modified-Since 处理

【讨论】:

  • 您想在响应中添加Last-Modified 标题属性以避免每次加载页面时转移资源。 URLConnection conn = classPathResource.getURL().openConnection(); 然后使用headers.setContentLength(conn.getContentLengthLong());headers.setLastModified(conn.getLastModified());
  • @ciri-cuervo:好点子!我已经相应地更新了代码。感谢您的反馈!
  • 我认为它不适用于 return null,因为 Spring 会发送 200 OK 响应状态并且站点不会加载资源。如果在 headers 中设置 Last-Modified 属性,Spring 会在请求中找到 If-Modified-Since 时自动回复 304 Not Modified(而不是资源)。看我的例子:WebJarsLocatorController.java
  • 我已经用 Chrome 对其进行了测试,它似乎做得很好。根据我在文档中阅读的内容, checkNotModified() 将透明地设置适当的响应标头(包括状态)。来源:docs.spring.io/spring/docs/current/javadoc-api/org/…
【解决方案2】:

您似乎无法使用PathVariable 来匹配“url 的剩余部分”。您必须使用 ant 样式的路径模式,即此处所述的“**”:

Spring 3 RequestMapping: Get path value

然后您可以获取请求对象的整个 URL 并提取“剩余部分”。

【讨论】:

  • 我已阅读文档。我知道它没有明确声明 @PathVariable 只能应用于路径中的一个元素,但似乎情况就是这样。在文档中我找不到匹配多个路径元素的正则表达式示例。
  • 正则表达式不匹配多个路径变量。只有一个。我提供的链接直接将您带到这样的示例。类似的例子可以在整个网络上找到。我怀疑 Spring Boot 是罪魁祸首。无论如何,我用一个元素进行了测试,但也没有用。
  • 我不明白,你有一个带有正则表达式的PathVariable,你希望它匹配“integration/bootstrap/3/dataTables.bootstrap.css”,即多个 路径元素。您提供的链接显示了它如何匹配 one 路径元素。是的,在这种情况下它确实有效。
  • 也许另一种表达方式是,你的正则表达式不能匹配'/'。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-29
  • 2015-05-30
  • 2019-01-30
  • 1970-01-01
  • 1970-01-01
  • 2022-01-22
  • 2016-02-16
相关资源
最近更新 更多