[spring-projects/spring-boot]spring.resources.cache.period 不起作用

2024-04-10 910 views
0

Spring Boot 2.1.4.RELEASE

据我所知,该财产spring.resources.cache.period永远无法做任何事情。 ResourceProperties.Cache.Cachecontrol.toHttpCacheControl将始终返回一个对象,因此永远不会采用此 else 分支。

一个可能的解决方法是确保在未设置属性的情况下toHttpCacheControl返回。null

回答

8

缓存周期配置为 CacheControl 的 MaxAge。还有一个测试断言它已设置。

您能否分享一个我们可以运行的示例来重现您遇到的问题,而不是描述技术解决方案?

8

抱歉,这是 WebMVC,而不是 WebFlux。它是用 spring-boot-starter-web 复制的,没有配置,单个静态文件,并且...period属性设置为有效的东西。

9

我们应该用这个设置重现什么?目前正在通过的测试也涵盖了 MVC 。我们可以忽略技术分析而专注于功能吗?

8

我专注于功能。尽管可能存在任何测试,但它实际上不起作用。这是明确的复制:https://gist.github.com/OrangeDog/8899a0b33561c3aa2100d9fe94a40f3f

$ curl -i http://localhost:8080/test.js
HTTP/1.1 200
Last-Modified: Mon, 08 Apr 2019 11:53:35 GMT
Accept-Ranges: bytes
Content-Type: application/javascript
Content-Length: 0
Date: Mon, 08 Apr 2019 12:15:09 GMT
4

感谢您的复制。

3

@snicoll 我正在研究这个错误。感谢您指出 MVC 的测试,这确实很有帮助。我想我发现了一个重大缺陷。

请参阅:https ://github.com/spring-projects/spring-boot/blob/cd914aaa4d7507b4e7fd66c65701335745a49303/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ servlet/WebMvcAutoConfigurationTests.java#L803-L812

handlerMap.keySet 上有一个 for 循环(handlerMap 本身是一个 Map<String, Object>)。所以实际上我们正在迭代 keySet,它是一个 Set。因此,我们没有将 ResourceHttpRequestHandler 存储在处理程序中,而是只拥有密钥(一个字符串)。

因为这:

            if (handler instanceof ResourceHttpRequestHandler) {

始终为 false,这意味着永远不会评估断言。

一旦我们通过迭代值而不是键来修复测试。由于以下断言而失败,因此目前无法信任。

固定测试的输出:

Java.lang.AssertionError: 
Expecting values:
  <[PT5S,
    CacheControl [max-age=5, must-revalidate, no-transform, public, private, proxy-revalidate],
    CacheControl [max-age=5, must-revalidate, no-transform, public, private, proxy-revalidate],
    CacheControl [max-age=5, must-revalidate, no-transform, public, private, proxy-revalidate],
    CacheControl [max-age=5, must-revalidate, no-transform, public, private, proxy-revalidate],
    CacheControl [max-age=5, must-revalidate, no-transform, public, private, proxy-revalidate]]>
in fields:
  <["maxAge",
    "mustRevalidate",
    "noTransform",
    "cachePublic",
    "cachePrivate",
    "proxyRevalidate"]>
but were:
  <[null,
    CacheControl [must-revalidate, no-transform, public, private, proxy-revalidate],
    CacheControl [must-revalidate, no-transform, public, private, proxy-revalidate],
    CacheControl [must-revalidate, no-transform, public, private, proxy-revalidate],
    CacheControl [must-revalidate, no-transform, public, private, proxy-revalidate],
    CacheControl [must-revalidate, no-transform, public, private, proxy-revalidate]]>
in <CacheControl [must-revalidate, no-transform, public, private, proxy-revalidate]>.
Comparison was performed on all fields
1

我尝试创建一个解决方案,但目前我不确定这是否是最好的结果:基本上现在归结为测试的断言:

图像

可以返回:CacheControl [max-age=5、must-revalidate、no-transform、public、private、proxy-revalidate]吗?

我在以下位置准备了代码:https://github.com/spring-projects/spring-boot/compare/master...eiselems :tryToFixCaching

一旦我们更深入地讨论了这个问题,我就会提出一个 PR。该代码以某种方式从 WebFluxAutoconfiguration 迁移(已经这样做了)

6

更改后@OrangeDog做的POC项目返回

curl -i http://localhost:8080/test.js

HTTP/1.1 200
Last-Modified: Sat, 04 May 2019 19:19:45 GMT
Cache-Control: max-age=86400
Accept-Ranges: bytes
Content-Type: application/javascript
Content-Length: 0
Date: Sat, 04 May 2019 19:23:05 GMT
Proxy-Connection: keep-alive
Connection: keep-alive

你能指派我来处理这个问题吗?

0

@eiselems 感谢您调查此问题的原因。 GitHub 不允许我们直接将问题分配给您,但我会将其分配给spring-contributor这将阻止其他人拾取它。如果你想为你所拥有的东西提交 PR,那就太好了!

3

@philwebb 真的很期待提出公关。还是想和webflux做一些比较。我认为如果两种实现都以相同的方式处理该标志,那就最好了。

0

@bclozel 只是为了让我做对了。您还支持在 Spring 中修复它(而不是在启动时解决它)。固定方式:

春天

  • 在没有设置 CacheControl 的情况下,根据 cachePeriod (如果可用)创建适当的 CacheControl。我们需要考虑所有情况,例如 -1、0、任何正持续时间

春季启动:

  • 设计它,以便生成 CacheControl 的 null 值并将其与 cachePeriod 一起传递给 Spring,然后 Spring 会计算出它
  • 更新测试以验证值是否正确传递到 Spring 并验证生成的“有效”http 标头(如果可能)

也许在接下来的几天里我很乐意从事这方面的工作。我想我会看看如何用 Spring 创建一个问题,然后在这里引用它。

1

在查看了 Spring 源代码之后回来,幸运的是 Spring 似乎没有错误(至少在我看来)。

https://github.com/spring-projects/spring-framework/blob/master/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistration.java#L169-L174

它已经正确设置了所有内容并处理 null 情况。问题就像@OrangeDog 已经说过的那样,Boot 实际上永远不会给出 CacheControl null

因此,为了解决这个问题,最好确保将 null 作为 CacheControl 传递,以防万一没有设置任何内容,并按原样传递 cachePeriod。然后 Spring 应该弄清楚(请参阅:https://github.com/spring-projects/spring-framework/blob/master/spring-webmvc/src/main/java/org/springframework/web/servlet/support/WebContentGenerator .java#L240-L254)。

我会尝试更新我已经打开的 PR,看看我会得到什么。

8

结束有利于#16730