spring 云 config-server .properties content-negotiation 失败
spring cloud config-server .properties content-negotiation failing
对我来说 content-negotiation 机制从 Angel.SR5
和 Angel.SR6
切换到 Spring 云 Brixton.RC1
或 Brixton.RC2
后,.properties 在 Spring 云配置服务器中不工作。
当我使用 gradlew bootRun
或 java -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'
}
到目前为止我已经做过的事情:
- 为 在所有提到的
Spring Cloud Config Server
版本中工作 的这种情况写了上面的 Spock-Test
- 根据我对 Spring MVC 中 content-negotiation 的了解,检查
ConfigServerMvcConfiguration
是否存在任何明显的配置错误
自己提供一个 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 格式设为当前支持的格式。
又是一个小错误,让事情变得复杂。
对我来说 content-negotiation 机制从 Angel.SR5
和 Angel.SR6
切换到 Spring 云 Brixton.RC1
或 Brixton.RC2
后,.properties 在 Spring 云配置服务器中不工作。
当我使用 gradlew bootRun
或 java -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'
}
到目前为止我已经做过的事情:
- 为 在所有提到的
Spring Cloud Config Server
版本中工作 的这种情况写了上面的 Spock-Test
- 根据我对 Spring MVC 中 content-negotiation 的了解,检查
ConfigServerMvcConfiguration
是否存在任何明显的配置错误 自己提供一个 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 格式设为当前支持的格式。
又是一个小错误,让事情变得复杂。