[spring-projects/spring-boot]配置单独的管理上下文时缺少资源处理配置

2024-05-09 735 views
5

如果我们配置management.server.port并且这个不等于,则server.port通过spring.web.resources.chain.strategy.content.*生成哈希不起作用,并且我们无法在文件上获得正确的哈希。如果文档中有一些关于此的信息,请提示我。否则,这里有一个如何重现它的示例:

如果您启动这个 docker-compose 文件,所有内容都会为您配置,并且例如中的资产散列/css/**确实有效。使用 Chrome/Firefox 中的开发者控制台查看http://localhost:8080/loginstyle.css例如,可以看到该例如 确实有哈希值,如果我们添加,MANAGEMENT_SERVER_PORT=8081我们看不到哈希值。该common.$hash.css文件可以被忽略,它不会被放置/css/**,并且将通过 webpack 生成。

version: '2.4'
services:
  mariadb:
    image: mariadb:10.5
    ports:
      - '3308:3306'
    environment:
      - MYSQL_DATABASE=urlaubsverwaltung
      - MYSQL_USER=urlaubsverwaltung
      - MYSQL_PASSWORD=urlaubsverwaltung
      - MYSQL_RANDOM_ROOT_PASSWORD=yes
  mailhog:
    image: mailhog/mailhog:v1.0.0
    ports:
      - '1025:1025'
      - '8025:8025'
  uv:
    image: synyx/urlaubsverwaltung:latest
    ports:
      - '8080:8080'
    environment:
      - SPRING_MAIL_HOST=mailhog
      - SPRING_MAIL_PORT=1025
      - UV_MAIL_SENDER=test@lala.de
      - UV_MAIL_ADMINISTRATOR=test@lala.de
      - UV_MAIL_APPLICATION-URL=http://localhost:8080
      - SPRING_DATASOURCE_URL=jdbc:mariadb://mariadb:3306/urlaubsverwaltung
      - UV_SECURITY_AUTH=default

但知道我是否添加文件management.server.port的哈希值/css/**,例如不会生成

version: '2.4'
services:
  mariadb:
    image: mariadb:10.5
    ports:
      - '3308:3306'
    environment:
      - MYSQL_DATABASE=urlaubsverwaltung
      - MYSQL_USER=urlaubsverwaltung
      - MYSQL_PASSWORD=urlaubsverwaltung
      - MYSQL_RANDOM_ROOT_PASSWORD=yes
  mailhog:
    image: mailhog/mailhog:v1.0.0
    ports:
      - '1025:1025'
      - '8025:8025'
  uv:
    image: synyx/urlaubsverwaltung:latest
    ports:
      - '8080:8080'
    environment:
      - SPRING_MAIL_HOST=mailhog
      - SPRING_MAIL_PORT=1025
      - UV_MAIL_SENDER=test@lala.de
      - UV_MAIL_ADMINISTRATOR=test@lala.de
      - UV_MAIL_APPLICATION-URL=http://localhost:8080
      - SPRING_DATASOURCE_URL=jdbc:mariadb://mariadb:3306/urlaubsverwaltung
      - UV_SECURITY_AUTH=default
      - MANAGEMENT_SERVER_PORT=8081

我们在给定 docker 容器中添加的默认应用程序属性可以在此处查看https://github.com/synyx/urlaubsverwaltung/blob/master/src/main/resources/application.properties#L30

如果这是一种常见行为,以及我们如何实现散列 css 文件并拆分服务器和管理端口,您是否能为我们提供任何信息?

提示:这与 docker 无关。我通过 ide、“java -jar ...”等有相同的行为:-)

回答

5

我花了一些时间尝试重现这个问题,到目前为止还没有成功。这是一个示例项目:https://github.com/bclozel/gh-25113

通过该项目,您可以运行java -jar target/gh25113-0.0.1-SNAPSHOT.war并看到:

为了重写模板中的 URL,Spring BootResourceUrlEncodingFilter向应用程序上下文贡献了一个。我最好的猜测是您的自定义设置(也许是这样?)在配置单独的管理端口时阻止此过滤器参与。

此时我怀疑您的设置有错误。如果您认为这是 Spring Boot 中的错误,请在我的示例之上进行构建,以最小程度地重现此问题。

谢谢!

6

感谢您的示例@bclozel!我会尽快查看并向您提供反馈。

我们还禁用了jsp precompile您在帖子中提到的配置,没有成功。

我很快就会更深入地了解。

0

@bclozel 感谢您的示例项目。我无法重现您的示例项目,http://localhost:8080包含 CSS 资源和哈希后缀。

命令的示例curl请求java -jar target/gh25113-0.0.1-SNAPSHOT.war

注意: jsessionid=87F1FDB8CC4C56A613914C475F0EB70A 不是预期的哈希值

curl localhost:8080 -v
*   Trying 127.0.0.1:8080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 
< Set-Cookie: JSESSIONID=87F1FDB8CC4C56A613914C475F0EB70A; Path=/; HttpOnly
< Content-Type: text/html;charset=UTF-8
< Content-Language: en-US
< Content-Length: 164
< Date: Wed, 10 Feb 2021 21:28:49 GMT
< 

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="/css/style.css;jsessionid=87F1FDB8CC4C56A613914C475F0EB70A" />
</head>
<body>
TEST
</body>
* Connection #0 to host localhost left intact
</html>

您能提供您的curl 的输出吗?

非常感谢!

8

抱歉,我错过了重现中的重要部分:声明ResourceUrlEncodingFilter如参考文档中所述

现在我的样本显示:

$ http :8080
HTTP/1.1 200
Connection: keep-alive
Content-Language: en-FR
Content-Length: 197
Content-Type: text/html;charset=UTF-8
Date: Thu, 11 Feb 2021 12:33:31 GMT
Keep-Alive: timeout=60
Set-Cookie: JSESSIONID=2C1498FBEAE8EFCFD37409F7FB0A79A3; Path=/; HttpOnly

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="/css/style-1688c8210b6509d702b1adb96bc4d0f3.css;jsessionid=2C1498FBEAE8EFCFD37409F7FB0A79A3" />
</head>
<body>
TEST
</body>
</html>

谢谢,

1

感谢您的示例@bclozel。我首先查看了它并定义了 ,ResourceUrlEncodingFilter应用程序将不会启动,因为我们为电子邮件使用 Freemarker 模板,并且FreeMarkerServletWebConfiguration已经ResourceUrlEncodingFilter为我们定义了 。因此,在不知不觉中,我们已经有了ResourceUrlEncodingFilter豆子。这也可以并且有意义,因为哈希值就在那里。

但现在到了奇怪的部分。如果我通过应用程序运行应用mvn spring-boot:run程序不会启动,因为重复ResourceUrlEncodingFilter看到:

Description:

The bean 'resourceUrlEncodingFilter', defined in class path resource [org/synyx/urlaubsverwaltung/web/jsp/ConfigurationJsp.class], could not be registered. A bean with that name has already been defined in class path resource [org/springframework/boot/autoconfigure/freemarker/FreeMarkerServletWebConfiguration.class] and overriding is disabled.

这一点也不奇怪。因为我们现在有重复的 bean。好的。

但是,如果我构建一个战争并让它运行,一切都会正常,没有重复的 bean,并且哈希值就在那里。但如果我management.server.port再次添加,哈希值就会消失。

FreeMarkerServletWebConfiguration那么,如果我添加 ,会做什么或不做什么或其他什么management.server.port

在我们开始在这个兔子洞中进行调试之前,也许您能给我们一些提示:)

2

我不明白为什么spring-boot:run这里作为战争运行是不同的。我的建议是在启用调试的情况下以两种方式运行应用程序,并收集和比较自动配置报告。也许在一种情况下配置了某些东西,而在另一种情况下则没有配置?

9

我不明白为什么spring-boot:run这里作为战争运行是不同的。我的建议是在启用调试的情况下以两种方式运行应用程序,并收集和比较自动配置报告。也许在一种情况下配置了某些东西,而在另一种情况下则没有配置?

我也这么想。明天会看看。感谢您的帮助输入!

9

嗨@bclozel,在 WebMvcAutoConfiguration 和 ResourceUrlProvider 中进行了大量的摆弄之后,我可以确认一切都按预期工作!

我们的应用程序在 3.0.0 版本中使用 springfox-boot-starter,并且在不同端口上运行管理服务器似乎存在问题。

我不知道为什么,但在https://github.com/spring-projects/spring-framework/blob/master/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlProvider .java#L140只有可用的 beans,例如resourceHandlerMapping使用/swagger-ui/**-pattern 代替/**

我检查了 springfox 自动配置。在https://github.com/springfox/springfox/blob/master/springfox-boot-starter/src/main/java/springfox/boot/starter/autoconfigure/SwaggerUiWebMvcConfigurer.java#L20中有一个额外的ResourceHandler的注册。我不明白为什么在同一端口上运行管理服务器可以工作,而在不同的端口上则不能。

非常感谢小伙伴的支持!

4

我用 SpringDoc 替换了 SpringFox,并且具有完全相同的行为,请参阅https://github.com/synyx/urlaubsverwaltung/tree/springdoc,如果我删除 springfox 和 springdoc,一切都会按预期工作。那么为什么要management.server.port对这个库进行更改以及有何更改?!我不明白。

@bclozel 如果我添加,是否有不同的 RessourceHandler management.server.port,因此链不能散列?

6

此时,我们似乎已经确定这可能是这些库的问题,而不是 Spring Boot 的问题。

在我们有更好的理解之前,我将保留这个问题。

请提供所需的信息:两种变体的自动配置报告(带有哈希值和不带有哈希值)。这应该可以帮助我们缩小问题根源的范围。

9

嘿@bclozel,我在你的最小示例(https://github.com/bclozel/gh-25113/pull/1)中添加了一个 PR,该示例显示,当

@Configuration
public class ResourceHandlerConfiguration implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        registry.addResourceHandler("/something/**");
    }
}

当!=时,通过哈希添加 ResourceHandlerWebMvcConfigurer不起作用。对我来说,这不像是默认行为,或者?management.server.portserver.port

如果您调试到https://github.com/spring-projects/spring-framework/blob/master/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlProvider.java#L140management.server.port a与server.port您只看到两次模式不同/something/**,如果您将 更改management.server.port为等于server.port,则会出现以下模式:/something/**/webjars/**/**

我还添加了带有和不带有不同端口的调试输出及其差异。

with-resource-handler-and-management-the-same.log with-resource-handler-and-management- different-management-server-port.log diff-different-and-same-menagement-server-port.log

1

想了想,我又试了一次,为什么不降级到最新版本呢?因为我感觉这是一个 Spring Boot bug。我只能使用 Spring Boot 2.4.2 和 2.3.8 重现该错误。使用 2.4.1 和 2.3.7 并补充说,行为management.server.port不等于server.port预期。

我在您的示例中添加了另一个 PR,其中我将应用程序降级到 2.4.1,请参阅https://github.com/bclozel/gh-25113/pull/2

6

感谢您在这里提供帮助,这是一个很难弄清楚的问题。

为了重现这个问题,我们需要以下内容:

  1. 具有执行器和单独管理上下文的 Spring Boot 应用程序
  2. 配置的资源链(此处用于基于内容的哈希)
  3. 单独WebMvcConfigurer添加新的资源处理注册

示例应用程序在这里

这是发生的事情:

  1. 自定义资源处理注册已注册
  2. 子应用程序上下文发布刷新上下文事件
  3. 自动ResourceUrlProvider 检测资源处理程序并注册位置,然后锁定自身以防止进一步修改。此时,Spring Boot 资源注册尚未注册,并且在解析资源的 URL 时会在运行时被忽略。
  4. 之后,Spring Boot 注册其资源处理配置;另一个刷新的事件已发布,但为时已晚,因为ResourceUrlProvider现在不允许进一步修改。

预期的顺序是切换 4) 和 3),以便检测到 Spring Boot 的资源处理配置。

我认为这可能与#24748 有关(并且由于这是一个转发端口,因此是其父问题)。奇怪的是,我可以使用 和 重现此回归2.4.22.3.8.RELEASE但不能2.2.13.RELEASE在最初应用 #24745 的地方重现。

似乎拥有父/子上下文设置涉及在父级中处理资源处理配置之前触发一个事件。我们需要更多时间来找出到底是什么问题 - 我将立即更新我的示例应用程序。

谢谢!

9

早上好@bclozel,与你一起度过了一段愉快的旅程。感谢您的时间和支持! :)

7

虽然 Spring Boot 中可能发生了一些变化,以某种方式改变了这些父/子上下文事件的顺序,但我们发现这里的主要问题是组件ResourceUrlProvider不应该考虑不是由其自己的应用程序上下文发送的事件。

我们将关闭此问题并将其标记为由 spring-projects/spring-framework#26561(以及用于向后移植的 spring-projects/spring-framework#26562)取代。

这将在 Spring Boot 2.4.4 中修复,因为它将支持即将发布的 Spring Framework 5.3.5 版本。