gpt4 book ai didi

java - 如何解析 Web servlet 中的 Spring @Value 注释?

转载 作者:行者123 更新时间:2023-11-30 07:10:36 25 4
gpt4 key购买 nike

我有一个 servlet 打包在一个 ear 文件中,我无法让它解析 @Value 注释的属性。

该应用程序分为两部分:打包在 war 文件中的 servlet,然后由打包在 ear 文件中的不同应用程序包含。应用程序提供由 servlet 中的接口(interface)定义的类 (ResourceManager) 的实现,以及包含 @Value 注释字段的属性值的属性文件。

war文件包含:

web.xml:

<servlet>
<servlet-class>... extends MessageDispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:/spring-ws.xml
classpath:/spring-app.xml
</param-value>
</init-param>
</servlet>

spring-ws.xml:

<context:annotation-config/>
<context:property-placeholder location="classpath:/spring-ws.properties"/>

spring-ws.properties 中的值直接从 spring-ws.xml 中引用,并且一切正常。

servlet 类包含:

public class MyServlet extends MessageDispatcherServlet

@Autowired private ResourceManager resourceManager; // original annotation - got this to work
@Value("${app.name:}") private String appName; // added later - cannot get this to work

app.name 是可选的,因此尾随“:”。

ear文件添加(打包在ear lib目录下的jar文件中):

spring-app.xml:

  <context:property-placeholder location="classpath:/spring-app.properties"/>

<bean class="ResourceManagerImpl">
...
</bean>

spring-app.properties:

app.name=myApp

我的第一个问题是 @Autowired 注释:不确定我是否正确地找到了它的底部,但我设法通过将这段代码添加到 servlet 来让它工作:

@Override
protected void initFrameworkServlet() throws ServletException {

AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
bpp.setBeanFactory(getWebApplicationContext().getAutowireCapableBeanFactory());
bpp.processInjection(this);
}

这可能不是解决此问题的最佳方法,但它是我发现的第一个并且它有效,所以我使用它并继续前进。然后我添加了一个带@Value 注释的字段,但我找不到一种方法来完成这项工作。 AutowiredAnnotationBeanPostProcessor 的 javadocs说它也应该处理 @Value 注释,但它似乎没有:appName 属性始终为空(大概是默认值)。

我确实有一个解决方法,使用 beans:

@Autowired @Qualifier("appName") private String appName;

<bean id="appName" class="java.lang.String">
<constructor-arg value="myApp"/>
</bean>

但我确信一定有更好的方法来做到这一点。我读过这篇文章 Difference between applicationContext.xml and spring-servlet.xml in Spring Framework ,但我不确定它是否适用:我认为我这里甚至没有应用程序上下文,只有在 web.xml 中为(单个)servlet 类定义的 servlet 上下文。

我也看到了这个:Spring 3.0.5 doesn't evaluate @Value annotation from properties ,这看起来是同一个问题,但解决方案似乎是将“ ”从应用程序上下文移动到 servlet 上下文,而正如我之前所说,我认为我什至没有此处的应用程序上下文...

最后,我快速简化了问题,删除了单独的应用程序并将所有内容打包成一个 war,但我认为这不是问题所在(尽管显然可能是错误的...): spring 可以解析 app.xml 文件的类路径,因此它必须能够解析 app.properties 文件的类路径。

非常感谢任何帮助,但我想在这一点上它有点学术兴趣,因为我有一个可行的解决方案(使用 bean),而支付账单的人并不真正关心它是如何工作的因为它有效!我只是想知道下次我不必复制(我认为是)有缺陷的解决方法。

使用 spring-ws-core 2.1.4,它通过 maven 依赖项引入 spring 3.2.4。

谢谢

更新 - 已解决

原来解决这个问题的关键是 M Deinum 的评论“你也有一个重复的元素......”。我在同一上下文中有两个单独的 PropertyPlaceholderConfigurer,因此第二个被忽略并且其属性从未使用过。上下文本身(这是一个 servlet 上下文而不是根上下文)或注释处理没有问题。

因此修复只是从 spring-app.xml 中删除属性占位符,并将两个属性文件合并到 spring-ws.xml 中

<context:property-placeholder
location="classpath:/spring-ws.properties,
classpath:/spring-app.properties"/>

TL;DR 的回答在这里 Spring: namespace vs contextConfigLocation init parameters in web.xml也是对如何处理不同上下文的精彩解释!

干杯,

最佳答案

您的 servlet 不是 spring 管理的 bean,它是由 Servlet 容器管理的。因此 @Autowired 首先不起作用的原因。 Spring 只会处理它知道的 bean。

ContextLoaderListener 和您的 servlet(基本上是任何扩展 FrameworkServlet 的 servlet)都有自己的 ApplicationContext 实例。来自 ContextLoaderListener 的那个被 servlet 中构造的上下文用作父级。所以您的 servlet 中确实有一个 ApplicationContext

现在要正确解析此 @Value,您需要有一个 PropertyPlaceHolderConfigurer 来解析占位符。由于 PropertyPlaceHolderConfigurer 是一个 BeanFactoryPostProcessor,它仅在同一上下文中对 bean 进行操作,因此由 ContextLoaderListener 加载/配置的​​ bean 不会对与您的 servlet 上下文相关的 bean 执行任何操作。 (因此您需要将 <context:property-placeholder ... /> 元素添加到 servlet 上下文中)。

你也有一个重复的元素,一般你想避免这种情况,因为它会同时导致问题,要么一个覆盖另一个,要么你会得到占位符无法被 PropertyPlaceHolderConfigurer 中的任何一个解决的异常

您的初始化代码也过于复杂,您不需要 AutowiredAnnotationBeanPostProcessor,只需使用可用的方法即可。

getWebApplicationContext().getAutowireCapableBeanFactory().autowireBean(this);

这也比只有 AutowiredAnnotationBeanPostProcessor 做的更多。

关于java - 如何解析 Web servlet 中的 Spring @Value 注释?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22066691/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com