spring 云 config-server .properties content-negotiation 失败

spring cloud config-server .properties content-negotiation failing

对我来说 content-negotiation 机制从 Angel.SR5Angel.SR6 切换到 Spring 云 Brixton.RC1Brixton.RC2 后,.properties 在 Spring 云配置服务器中不工作。

当我使用 gradlew bootRunjava -jar ... 启动服务时出现问题。它在我的集成测试中工作(参见下面的工作Integration-Test)。

使用场景:

我想访问应用程序 my-service 的配置文件 testing 中的配置,所以我正在调用 http://localhost:8888/my-service/testing.properties

预期结果:

some.property=1234
some.other.property=hello there

实际结果:

没有Accept-Header:

<!DOCTYPE html>
<html>
    <head>
        <title>Error 406</title>
    </head>
    <body>
        <h1>Error 406: Not Acceptable</h1>
        <br/>
        Could not find acceptable representation
    </body>
</html>

Accept-Headerapplication/json:

{
    "timestamp": 1461140158009,
    "status": 406,
    "error": "Not Acceptable",
    "exception": "org.springframework.web.HttpMediaTypeNotAcceptableException",
    "message": "Could not find acceptable representation",
    "path": "/config/my-service/default.properties"
}

正如您从示例中看到的那样,content-negotiation 机制似乎适用于 error-handling,但对于配置访问却并非如此。

工作Integration-Test:

下面是我写的Spock-Test

@WebIntegrationTest({"server.port=0", "management.port=0"})
@ActiveProfiles("testing")
@ContextConfiguration(loader = SpringApplicationContextLoader.class, classes = ConfigurationServiceApplication.class)
class ConfigurationAccessTest extends Specification {

    @Autowired
    TestserverInfo testserverInfo

    def "testing profile returns testing properties"() {
        given:
        RestTemplate rest = new TestRestTemplate(null, null)
        Properties properties = new Properties()

        when:
        String result = rest.getForObject( testserverInfo.getBasePath() + "/my-service-testing.properties", String.class );
        properties.load( new StringReader(result) )

        then:
        properties['test'] == 'Testing Profile World'
        properties['my.long.testing.property'] == 'Testing Profile Property'
    }

到目前为止我已经做过的事情:

  1. 在所有提到的 Spring Cloud Config Server
  2. 版本中工作 的这种情况写了上面的 Spock-Test
  3. 根据我对 Spring MVC 中 content-negotiation 的了解,检查 ConfigServerMvcConfiguration 是否存在任何明显的配置错误
  4. 自己提供一个 WebMvcConfigurer 并初始化 content-negotiation 就像上面提到的配置 class:

    @EnableWebMvc
    @Configuration
    public class ConfigMvcConfiguration extends WebMvcConfigurerAdapter {
        private final Logger logger =  LoggerFactory.getLogger(ConfigMvcConfiguration.class);
    
        @Override
        public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
            configurer.mediaType("properties", MediaType.valueOf("text/plain"));
            configurer.mediaType("yml", MediaType.valueOf("text/yaml"));
            configurer.mediaType("yaml", MediaType.valueOf("text/yaml"));
            logger.info("media-types added");
        }
    }
    

任何人都可以重现此问题或提供任何解决方法的指导吗?

写完这个问题后,我意识到:我在追鬼。 在检查我自己编写的集成测试时,我发现我试图使用错误的 url-schema 访问属性。

TLDR

我试图使用 URL

访问属性
http://localhost:8888/config/my-service/testing.properties   <-- wrong
rather than
http://localhost:8888/config/my-service-testing.properties   <-- correct

详情

可以使用以下 url 模式访问 JSON 格式的属性(不使用标签时):

http://<host>:<port>/<contextPath>/<application>/<profile>

如果想要以 json 以外的格式访问属性,她必须使用另一个 url-schema(同样是没有标签的示例)

http://<host>:<port>/<contextPath>/<application>-<profile>.<format>

将 properties/yml/yaml 格式设为当前支持的格式。

又是一个小错误,让事情变得复杂。