ไม่สามารถแก้ไขตัวยึดตำแหน่งในค่าสตริง


88

ฉันพยายามใช้คุณสมบัติจาก.propertiesไฟล์ แต่ดูเหมือนจะไม่ได้ผล

นี่คือรหัสของฉัน:

@Service("ServiceFTP")
@Transactional
public class ServiceFTPImpl implements ServiceFTP {

@Value("${project.ftp.adresse}")
private String adresse;

@Value("${project.ftp.login}")
private String compte;

@Value("${project.ftp.password}")
private String motDePasse;

@Value("${project.ftp.root}")
private String ROOT;

[...]

}

คลาสนี้ใช้@Valueคำอธิบายประกอบเพื่อรับคุณสมบัติ นอกจากนี้ยังประกาศเป็น Spring Service และเชื่อมโยงกับinfraContext.xmlไฟล์ของฉัน:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">

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

[...]

</beans>

โดยใช้context:property-placeholderฉันลิงก์ไฟล์นี้กับไฟล์ของฉันcontext-core.properties:

project.ftp.adresse = localhost
project.ftp.login = anonymous
project.ftp.password =
project.ftp.root = /anonymous/

มันสมเหตุสมผลแล้วใช่มั้ย?

แต่เมื่อฉันพยายามเปิดตัวโครงการ Tomcat ก็โยนข้อยกเว้นนี้:

    ERROR [context.ContextLoader.initWebApplicationContext()] Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ServiceFTP': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.lang.String project.sins.service.impl.ServiceFTPImpl.adresse; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'project.ftp.adresse' in string value "${project.ftp.adresse}"
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:925)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:472)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:388)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:293)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4887)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5381)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:633)
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:657)
    at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1636)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
    at java.util.concurrent.FutureTask.run(FutureTask.java:166)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:722)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.lang.String project.sins.service.impl.ServiceFTPImpl.adresse; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'project.ftp.adresse' in string value "${project.ftp.adresse}"
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:513)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:92)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:284)
    ... 27 more
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'project.ftp.adresse' in string value "${project.ftp.adresse}"
    at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:173)
    at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:125)
    at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:151)
    at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:142)
    at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$2.resolveStringValue(PropertySourcesPlaceholderConfigurer.java:169)
    at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:748)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:740)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:730)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:485)
    ... 29 more

หรือเรียกสั้น ๆ ว่า java.lang.IllegalArgumentException: Could not resolve placeholder 'project.ftp.adresse' in string value "${project.ftp.adresse}"

แก้ไข:

นี่คือ web.xml ของฉัน:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         id="sins" version="2.5">

    <display-name>Project</display-name>

    <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>

    <context-param>
        <param-name>log4jExposeWebAppRoot</param-name>
        <param-value>false</param-value>
    </context-param>

    <filter>
        <filter-name>ExpiresFilter</filter-name>
        <filter-class>org.apache.catalina.filters.ExpiresFilter</filter-class>
        <init-param>
            <param-name>ExpiresByType text/html</param-name>
            <param-value>now plus 0 seconds</param-value>
        </init-param>
        <init-param>
            <param-name>ExpiresByType application/json</param-name>
            <param-value>now plus 0 seconds</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>ExpiresFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>

    <filter>
        <filter-name>EncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>EncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
        <filter-class>
            org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
        </filter-class>
    </filter>

    <filter-mapping>
        <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <listener>
        <listener-class>org.apache.struts2.tiles.StrutsTilesListener</listener-class>
    </listener>

    <context-param>
        <param-name>
            org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG
        </param-name>
        <param-value>
            /WEB-INF/tiles/user.xml
        </param-value>
    </context-param>

    <resource-ref>
        <res-ref-name>jdbc/si_nsg</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>

    <session-config>
        <session-timeout>60</session-timeout>
    </session-config>

</web-app>

InfraContext.xml ของฉันถูกอิมพอร์ตในไฟล์. xml อื่นชื่อ applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd">

    <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
        <property name="environment">
            <bean class="org.springframework.web.context.support.StandardServletEnvironment"/>
        </property>
    </bean>

    <import resource="classpath:securityContext.xml"/>

    [...]
    <import resource="classpath:project/sins/persistenceContext.xml"/>

    <import resource="classpath:project/sins/infraContext.xml"/>

</beans>

เห็นได้ชัดว่าฉันขาดอะไรไป แต่ฉันคิดไม่ออกว่าอะไร

โปรดแจ้งให้เราทราบหากคุณต้องการรายละเอียดเพิ่มเติมเนื่องจากเป็นคำถามแรกของฉันที่นี่ฉันจะพยายามตอบโดยเร็วที่สุด :)


1
คุณinfraContext.xmlกำลังโหลดอยู่ที่ไหน? การตัดสินจาก stacktrace จะไม่รวมอยู่ในการกำหนดค่าที่โหลดโดยContextLoaderListener. กรุณาโพสต์ web.xml ของคุณ
M. Deinum

2
ปัญหาคือคุณมีหลายอินสแตนซ์ของอินสแตนซ์ที่PropertySourcesPlaceholderConfigurerกำหนดไว้อย่างชัดเจน (ทำไม?) และอีกอันเกิดจากเนมสเปซ สิ่งที่อยู่ในตัวคุณapplicationContext.xmlไม่ได้ทำอะไรหรือเพิ่มอะไรเลย ย้ายมัน.
M. Deinum

คำตอบ:


74

ในการกำหนดค่าของคุณคุณมี 2 PropertySourcesPlaceholderConfigurerอินสแตนซ์

applicationContext.xml

<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
    <property name="environment">
        <bean class="org.springframework.web.context.support.StandardServletEnvironment"/>
    </property>
</bean>

InfraContext.xml

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

โดยค่าเริ่มต้น a PlaceholderConfigurerจะล้มเหลวอย่างรวดเร็วดังนั้นหากไม่สามารถแก้ไขตัวยึดตำแหน่งได้จะทำให้เกิดข้อยกเว้น อินสแตนซ์จากapplicationContext.xmlไฟล์ไม่มีคุณสมบัติและด้วยเหตุนี้จะล้มเหลวในตัวยึดตำแหน่งทั้งหมด

วิธีแก้ปัญหา: ลบอันหนึ่งออกจากapplicationContext.xmlเนื่องจากไม่ได้เพิ่มอะไรเลย แต่จะทำลายสิ่งต่างๆ


ยอดเยี่ยมขอบคุณดังนั้นฉันจึงเข้าใจว่าในฤดูใบไม้ผลิจะมี a PlaceholderConfigurer?
Mushtaq Jameel

11
ไม่มีคุณสามารถมีหลายตัวได้อย่างไรก็ตามโดยค่าเริ่มต้นจะล้มเหลวอย่างรวดเร็วหากไม่พบตัวยึดตำแหน่ง คุณสามารถปิดการใช้งานโดยการตั้งค่าไปignore-unresolved-placeholders true
M. Deinum

3
ฉันจะจัดการกับสปริงบูตพร้อมคำอธิบายประกอบได้อย่างไร
rezKesh

5

ฉันมีปัญหาเดียวกันแก้ไขได้โดยการเพิ่ม

<filtering>true</filtering> 

ใน pom.xml:

ก่อนหน้านี้ (ไม่ทำงาน):

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>               
        </resource>
    </resources>
</build>

หลังจาก (มันใช้งานได้):

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>

หลังจากนั้นคุณก็เรียกใช้mvn clean installและปรับใช้แอปพลิเคชัน


ขอบคุณสิ่งนี้ช่วยแก้ปัญหาของฉันได้ ฉันสงสัยว่าทำไมปลั๊กอินทรัพยากร maven ถึงมีผลต่อตัวยึดสปริง ... ฉันไม่เคยเดาเลยว่ามันเกี่ยวข้องกัน!
Pim Hazebroek

3

ปัญหานี้เกิดขึ้นหากแอปพลิเคชันไม่สามารถเข้าถึงไฟล์ some_file_name.properties ตรวจสอบให้แน่ใจว่าไฟล์คุณสมบัติถูกวางไว้ในโฟลเดอร์ทรัพยากรในฤดูใบไม้ผลิ

มีปัญหาในการถ่ายทำขั้นตอน

1: เพิ่มไฟล์คุณสมบัติภายใต้โฟลเดอร์ทรัพยากร

2: หากคุณไม่มีโฟลเดอร์ทรัพยากร สร้างโดยการไปยังส่วนต่างๆใหม่โดยคลิกขวาที่โปรเจ็กต์ใหม่> โฟลเดอร์ซอร์สตั้งชื่อเป็นทรัพยากรและวางไฟล์คุณสมบัติของคุณไว้ข้างใต้

สำหรับการใช้งานตามคำอธิบายประกอบ

เพิ่ม@PropertySource(ignoreResourceNotFound = true, value = "classpath:some_file_name.properties")// เพิ่มก่อนใช้ที่ยึด

ตัวอย่าง:

Assignment1Controller Java

@PropertySource(ignoreResourceNotFound = true, value = "classpath:assignment1.properties")
@RestController  
public class Assignment1Controller {

//  @Autowired
//  Assignment1Services assignment1Services;
    @Value("${app.title}")
    private String appTitle;
     @RequestMapping(value = "/hello")  
        public String getValues() {

          return appTitle;

        }  

}

การมอบหมาย 1. คุณสมบัติ

app.title=Learning Spring

1
สิ่งนี้ใช้กับ Spring4 และใหม่กว่าหรือไม่
Malkocoglu

ใช่ @Malkocoglu
Gani

3

ในกรณีของฉันฉันประมาทในขณะที่รวมไฟล์ application.yml และฉันไม่จำเป็นต้องเยื้องคุณสมบัติของฉันไปทางขวา

ฉันเยื้องมันดังนี้:

spring:
    application:
       name: applicationName
............................
    myProperties:
       property1: property1value

ในขณะที่รหัสคาดว่าจะเป็นเช่นนี้:

spring:
    application:
        name: applicationName
.............................
myProperties:
    property1: property1value

3

คุณยังสามารถลองใช้ค่าเริ่มต้น ฤดูใบไม้ผลิค่าคำอธิบายประกอบ

สามารถระบุค่าดีฟอลต์สำหรับคุณสมบัติที่อาจไม่ได้กำหนดไว้ ในตัวอย่างนี้ค่า“ ค่าเริ่มต้นบางส่วน” จะถูกฉีดเข้าไป:

@Value("${unknown.param:some default}")
private String someDefault;

หากคุณสมบัติเดียวกันถูกกำหนดให้เป็นคุณสมบัติของระบบและในไฟล์คุณสมบัติคุณสมบัติของระบบจะถูกนำไปใช้


โอเค ... สิ่งนี้ช่วยฉันได้ อันที่จริงแอปของฉันมีไฟล์ .yml ของแอปพลิเคชันจำนวนมากและฉันได้รับข้อผิดพลาดเนื่องจากคุณสมบัติใหม่ที่กำหนดไว้ในการกำหนดค่าหลัก ไฟล์เท่านั้น ฉันคาดหวังว่าจะกำหนดค่าเพียงครั้งเดียวในการกำหนดค่าหลักและในกรณีที่แทนที่ค่าในการกำหนดค่าเฉพาะโปรไฟล์ ดูเหมือนจะไม่ได้ผลเช่นนั้นและต้องระบุค่าเริ่มต้นเสมอ ตอนนี้ฉันเข้าใจแล้วว่าทำไมการกำหนดค่า java ของฉันจึงล้มเหลวเมื่อฉันไม่ได้เริ่มต้นคุณสมบัติด้วยค่าเริ่มต้น! พฤติกรรมนี้สามารถเปลี่ยนแปลงได้หรือไม่? ขอบคุณ :-)
funder7

3

ฉันพบข้อผิดพลาดเดียวกันในบริการไมโครทุกครั้งที่คุณประกาศคำอธิบายประกอบ @Value ในโปรแกรมเช่น@Value ("$ {project.api.key}")

ตรวจสอบให้แน่ใจว่าไฟล์ application.properties ของคุณที่มีค่าเดียวกันไม่ควรเป็นproject.api.key = เพิ่มค่าบางค่า

MostIMP : ไม่เช่นนั้นจะเกิดข้อผิดพลาด "ข้อผิดพลาดในการสร้าง bean ด้วยชื่อ 'ServiceFTP': การแทรกการอ้างอิงอัตโนมัติ"


0

ด้วย Spring Boot:

ใน pom.xml

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <addResources>true</addResources>
            </configuration>
        </plugin>
    </plugins>
</build>

ตัวอย่างในคลาส Java

@Configuration
@Slf4j
public class MyAppConfig {
    @Value("${foo}")
    private String foo;
    @Value("${bar}")
    private String bar;
    @Bean("foo")
    public String foo() {
        log.info("foo={}", foo);
        return foo;
    }
    @Bean("bar")
    public String bar() {
        log.info("bar={}", bar);
        return bar;
    }
    [ ... ]

ในไฟล์คุณสมบัติ:

src / main / resources / application.properties

foo=all-env-foo

src / main / resources / application-rec.properties

bar=rec-bar

src / main / resources / application-prod.properties

bar=prod-bar

ในอาร์กิวเมนต์ VM ของ Application.java

-Dspring.profiles.active=[rec|prod]

อย่าลืมเรียกใช้คำสั่ง mvn หลังจากแก้ไขคุณสมบัติ!

mvn clean package -Dmaven.test.skip=true

ในล็อกไฟล์สำหรับ -Dspring.profiles.active = rec:

The following profiles are active: rec
foo=all-env-foo
bar=rec-bar

ในล็อกไฟล์สำหรับ -Dspring.profiles.active = prod:

The following profiles are active: prod
foo=all-env-foo
bar=prod-bar

ในล็อกไฟล์สำหรับ -Dspring.profiles.active = local:

Could not resolve placeholder 'bar' in value "${bar}"

Oups ฉันลืมสร้าง application-local.properties


0

ฉันได้รับข้อผิดพลาดเดียวกันในโครงการไมโครเซอร์วิสของฉันคุณสมบัตินั้นพลาดในไฟล์ yml ของฉันดังนั้นฉันจึงเพิ่มชื่อคุณสมบัติและค่าที่ช่วยแก้ปัญหาของฉัน


0

ข้อผิดพลาดนี้ปรากฏขึ้นเนื่องจาก spring project ไม่อ่านคุณสมบัติของไฟล์ ( bootstrap.ymlหรือapplication.yml ) ในการแก้ไขปัญหานี้คุณต้องเพิ่มการอ้างอิงในpom.xmlของคุณ

   <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-context</artifactId>
    </dependency>

0

ฉันพบปัญหานี้บ่อยครั้งเกี่ยวกับคุณสมบัติที่กำหนดเองบางอย่างที่ไม่พบโดยใช้IntelliJ IDEAซึ่งเป็นไปได้ว่าหลังจากเปลี่ยนสาขาแล้ว

สิ่งที่ช่วยในกรณีของฉันคือ

ไฟล์ -> ไม่ถูกต้องแคช / รีสตาร์ท

ฉันมีข้อสันนิษฐานว่าน่าจะเป็นปัญหาการแคช Gradle มากกว่าปัญหา IDE แต่ ./ gradle cleanไม่ได้ช่วย



-3

วิธีแก้ปัญหาของฉันคือเพิ่มช่องว่างระหว่าง $ และ {.

ตัวอย่างเช่น:

@Value("${project.ftp.adresse}")

กลายเป็น

@Value("$ {project.ftp.adresse}")
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.