关于Web应用程序中的Spring Cloud Config,我有几个问题。
上下文
我正在使用一个SpringBoot Web应用程序,其中有一个 Root应用程序上下文(父级)和一个 Servlet应用程序上下文(子级),我要添加Spring此应用程序的Cloud Config功能(当然,此应用程序通过http连接到Spring Cloud Config服务器)。
当我用RefreshScope
注释对在Root应用程序上下文中注册的bean进行注释时,一切都按预期进行,当我尝试对在Servlet应用程序上下文中注册的spring bean进行注释时,问题就开始了。 / p>
第一个问题:尝试访问servlet应用程序上下文中带有IllegalStateException
的带注释的Bean时,抛出了@RefreshScope
,以下是stacktrace中有意义的部分:
ERROR: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: No Scope registered for scope name 'refresh'] with root cause
java.lang.IllegalStateException: No Scope registered for scope name 'refresh'
解决方案:通过将 refresh 作用域注册到Servlet应用程序上下文中,可以解决上述错误
@Bean
public CustomScopeConfigurer servletCustomScopeConfigurer(org.springframework.cloud.context.scope.refresh.RefreshScope refreshScope) {
CustomScopeConfigurer customScopeConfigurer = new CustomScopeConfigurer();
customScopeConfigurer.addScope("refresh", refreshScope);
return customScopeConfigurer;
}
问题:假定这种对Web应用程序建模的方法仍然有用(我认为是这样),为什么我找不到任何文档说明必须注册刷新作用域到servlet应用程序上下文,我应该从根应用程序上下文中注册org.springframework.cloud.context.scope.refresh.RefreshScope
bean吗?
第二个问题:一旦我在servlet应用程序上下文中注册了刷新作用域,该应用程序就可以正常启动,并且一切似乎都可以正常工作,但是当我尝试更新时来自可刷新bean的一个属性,我得到了混合的结果,当我刷新一个将在根应用程序上下文中修改bean的属性时,我可以看到该bean正在更新,所以一切都很好,但是当我更新一个可以在其中修改bean的属性时在servlet应用程序上下文中,我可以设置要刷新的bean,但是新的属性值未反映在bean中。
解决方案:经过一些测试,我意识到两种情况下的ConfigurableEnvironment
是不相同的,在某些时候,父级ConfigurableEnvironment
被合并到子级{{1 }}就是在启动时正确初始化servlet上下文中的bean的方式,但是当ConfigurableEnvironment
调用ContextRefresher.refresh()
时,只有父RefreshEndpoint
被更新,子{{1 }}并没有保留旧的值,我现在要做的是在创建Servlet应用程序上下文时注入父级ConfigurableEnvironment
,并且一切正常,相关代码:
ConfigurableEnvironment
问题:再次令我感到惊讶的是,缺少有关Spring应用程序声明父和子应用程序上下文的预期行为的文档,也许我只是没有找到它而它确实存在并且令人惊讶。将父ConfigurableEnvironment
设置为子servlet上下文的方法正确吗?
在默认情况下((父@Bean
public DispatcherServlet dispatcherServlet(ConfigurableEnvironment parentEnvironment) {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.register(WebConfiguration.class);
applicationContext.setEnvironment(parentEnvironment);
dispatcherServlet.setApplicationContext(applicationContext);
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
return dispatcherServlet;
}
未在servlet上下文中设置。)是以下事实:子ConfigurableEnvironment
不会被故意刷新或刷新错误?
如果您仍在阅读本文,谢谢!以上问题的答案将不胜感激!
希望这可以帮助其他人解决这些问题。