当前位置: 首页 > 知识库问答 >
问题:

如何在web servlet中解析Spring@Value注释?

麻鸿熙
2023-03-14

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

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

战争文件包含:

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应用程序.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属性总是空的(可能是默认值)。

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

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

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

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

我也看到了这一点:Spring 3.0.5没有从属性中评估@Value注释,这看起来像是同样的问题,但那里的解决方案似乎是移动”

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

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

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

谢谢

更新-已解决

原来解决这个问题的关键是M Deina的评论,“你也有一个重复的元素……”。我在同一个上下文中有两个单独的属性PlaceholderConfigrer,所以第二个被忽略了,它的属性从未使用过。上下文本身(这是一个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在web中的init参数。xml还可以很好地解释不同上下文是如何处理的!

干杯,

共有3个答案

侯兴为
2023-03-14

对此有一个解决方法。

您可以在 Java 类中创建静态字段来存储值。

public class SystemPropertyHelper {
    public static String propertyValue;
}

并创建一个用@Service或@Component注释的java类,您可以在其中注入属性,并将此值传递给静态字段。

@Component
public class SpringBeanClass {

    @Value("${propertyName}")
    private String propertyValue;

    @PostConstruct
    public void init() {
        SystemPropertyHelper.propertyValue = propertyValue;
    }
}

这样,您可以始终通过静态字段访问属性值SystemPropertyHelper.propertyValue

章绪
2023-03-14

对于@Autowired注释,您只需要有一个包含这些注释的类:

@Configuration
@PropertySource("classpath:myFile.properties")
@ComponentScan("com.company.package")

Spring使用@Configuration来告诉它是一个用于配置的类(它替换了您提到的xml文件,xml conf文件是Spring 2,注解是Spring 3和4的新内容)

@ ComponentScan可以管理IOC (@Autowire)

@PropertySource加载属性文件

然后在启动时使用prop文件初始化类:

 @Component("myFileProperties")
 public class MyFileProperties{

 @Value("${app.name}")
 private String appName;

 public String getAppName() {
   return appName;
 }

 public void setAppName(String appName) {
   this.appName= appName;
 }
}

如果您希望它能够激励您,请看这里(我开发的web上下文中的conf文件):https://github.com/ebrigand/RSSLiker/blob/master/src/main/java/com/mrm/rss/init/WebAppConfig.java

申炳
2023-03-14

您的servlet不是spring管理的bean,而是由Servlet容器管理的。这就是为什么< code>@Autowired不能工作的原因。Spring只会处理它知道的豆子。

ContextLoaderListener和servlet(基本上是任何扩展FrameworkServletContextLoaderListener中的一个被servlet中构造的上下文用作父级。因此,您的servlet中确实有一个ApplicationContext

现在要正确解析这个@Value,您需要有一个Property tyPlaceHolderConfigrer来解析占位符。由于Property tyPlaceHolderConfigrer是一个BeanFactoryPostProcorer,它只对同一上下文中的bean进行操作,因此由ContextLoaderListener加载/配置的那个不会对与servlet中的上下文相关的bean执行任何操作。(因此您需要添加

一般来说,你也有一个重复的元素,你想避免这种情况,因为它会同时导致问题,要么一个覆盖另一个,要么你会得到占位符不能被属性PlaceHolderConfigrer中的任何一个解析的异常

您的init代码也过于复杂,您不需要< code > AutowiredAnnotationBeanPostProcessor 只需使用可用的方法。

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

这也比只有AutowiredAnnotationBeanPostProcessor做的更多。

 类似资料:
  • 主要内容:@WebServlet 注解的属性,@WebServlet 注解的使用,@WebServlet 注解 和 web.xml 的优缺点在 Servlet 中,web.xml 扮演的角色十分的重要,它可以将所有的 Servlet 的配置集中进行管理,但是若项目中 Servelt 数量较多时,web.xml 的配置会变得十分的冗长。这种情况下,注解(Annotation)就是一种更好的选择。 与 XML 不同,注解不需要依赖于配置文件,它可以直接在类中使用,其配置只对当前类有效,这样就避免了集

  • 本文向大家介绍Spring @value和@PropertySource注解使用方法解析,包括了Spring @value和@PropertySource注解使用方法解析的使用技巧和注意事项,需要的朋友参考一下 这篇文章主要介绍了Spring @value和@PropertySource注解使用方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考

  • 问题内容: 使用诸如 可以分配具有某些属性的某些字段。 是否有更短,更简洁的形式来执行此操作? 问题答案:

  • 问题内容: 如何在Spring中使用@Value批注将值从属性文件注入Map中? 我的Spring Java类是我尝试使用$,但收到以下错误消息 无法自动装配字段:私有 嵌套异常是:无法解析字符串值中的占位符 我在.properties文件中具有以下属性 问题答案: 我相信Spring Boot支持使用注释开箱即用地加载属性映射。 根据该文档,你可以加载属性: 像这样变成豆子: 我之前使用过@Co

  • 我正在运行IntelliJ IDEA 2017.3.4(终极版)。我有一个Spring Boot项目,定义了Spring属性,它将自动连接到类中的注释字段中。属性在Application.properties中定义。 如果“My.Property.Value”解析为“TheValue”,将显示如下: 我宁愿它不这样做。是否有禁用此功能的首选项?我没有运气找到答案,搜索的想法,偏好或网上。