Không thể giải quyết trình giữ chỗ trong giá trị chuỗi


86

Tôi đang cố gắng sử dụng các thuộc tính từ một .propertiestệp, nhưng nó dường như không hoạt động.

Đây là mã của tôi:

@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;

[...]

}

Lớp này sử dụng @Valuecác chú thích để lấy các thuộc tính. Nó cũng được khai báo là một Dịch vụ mùa xuân và được liên kết với infraContext.xmltệp của tôi :

<?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>

Bằng cách sử dụng context:property-placeholder, tôi liên kết tệp này với tệp của mình context-core.properties:

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

Điều này có ý nghĩa, phải không?

Nhưng khi tôi cố gắng khởi chạy dự án của mình, Tomcat ném ngoại lệ này:

    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

Hay nói ngắn gọn là: java.lang.IllegalArgumentException: Could not resolve placeholder 'project.ftp.adresse' in string value "${project.ftp.adresse}"

BIÊN TẬP :

Đây là web.xml của tôi:

<?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 của tôi được nhập vào một tệp .xml khác có tên 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>

Tôi rõ ràng là thiếu một cái gì đó, nhưng tôi không thể tìm ra cái gì.

Vui lòng cho tôi biết nếu bạn cần thêm chi tiết, vì đây là câu hỏi đầu tiên của tôi ở đây, tôi sẽ cố gắng trả lời ngay khi có thể :).


1
Của bạn infraContext.xmlđang được tải ở đâu? Đánh giá từ stacktrace, nó không có trong cấu hình được tải bởi ContextLoaderListener. Vui lòng đăng web.xml của bạn.
M. Deinum

2
Vấn đề là bạn có nhiều trường hợp của một trường hợp PropertySourcesPlaceholderConfigurerđược xác định rõ ràng (tại sao?) Và một trường hợp do không gian tên. Người trong số bạn applicationContext.xmlkhông làm bất cứ điều gì cũng không thêm bất cứ điều gì. Loại bỏ nó.
M. Deinum

Câu trả lời:


73

Trong cấu hình của bạn, bạn có 2 PropertySourcesPlaceholderConfigurerphiên bản.

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"/>

Theo mặc định, a PlaceholderConfigurersẽ không nhanh, vì vậy nếu không thể giải quyết trình giữ chỗ, nó sẽ đưa ra một ngoại lệ. Thể hiện từ applicationContext.xmltệp không có thuộc tính và như vậy sẽ không thành công trên tất cả các phần giữ chỗ.

Giải pháp: Xóa một cái khỏi applicationContext.xml vì nó không thêm bất cứ thứ gì mà chỉ làm hỏng mọi thứ.


Tuyệt vời, cảm ơn bạn, vì vậy tôi hiểu rằng trong Spring chỉ có thể có một trường hợp của a PlaceholderConfigurer?
Mushtaq Jameel

11
Không, bạn có thể có nhiều nhưng theo mặc định, chúng không nhanh nếu không tìm thấy trình giữ chỗ. Bạn có thể tắt tính năng này bằng cách đặt ignore-unresolved-placeholdersthành true.
M. Deinum

3
làm thế nào tôi có thể xử lý nó trong khởi động mùa xuân với chú thích?
rezKesh

5

Tôi đã gặp vấn đề tương tự, đã giải quyết nó bằng cách thêm

<filtering>true</filtering> 

trong pom.xml:

trước (không hoạt động):

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

sau khi (nó hoạt động):

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

Sau đó, bạn chỉ cần chạy mvn clean install và deploy ứng dụng.


Cảm ơn, điều này đã giải quyết được vấn đề của tôi. Tuy nhiên, tôi rất tò mò, tại sao / làm thế nào mà plugin tài nguyên maven lại ảnh hưởng đến các trình giữ chỗ mùa xuân ... Tôi không bao giờ nghĩ rằng chúng có liên quan đến nhau!
Pim Hazebroek

3

Sự cố này xảy ra nếu ứng dụng không thể truy cập tệp some_file_name.properties. Đảm bảo rằng tệp thuộc tính được đặt trong thư mục tài nguyên vào mùa xuân.

Các bước chụp sự cố

1: Thêm tệp thuộc tính trong thư mục tài nguyên.

2: Nếu bạn không có thư mục tài nguyên. Tạo một tài nguyên bằng cách điều hướng mới bằng cách Nhấp chuột phải vào dự án mới> Thư mục Nguồn, đặt tên nó là tài nguyên và đặt tệp thuộc tính của bạn dưới nó.

Để triển khai dựa trên chú thích

Thêm @PropertySource(ignoreResourceNotFound = true, value = "classpath:some_file_name.properties")// Thêm nó trước khi sử dụng trình giữ chỗ

Thí dụ:

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;

        }  

}

task1.properties

app.title=Learning Spring

1
Điều này có áp dụng cho Spring4 trở lên không?
Malkocoglu

Có @Malkocoglu
Gani

3

Trong trường hợp của tôi, tôi đã bất cẩn khi hợp nhất tệp application.yml và tôi đã thụt lề không cần thiết các thuộc tính của mình sang bên phải.

Tôi đã thụt vào nó như thế này:

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

Trong khi mã dự kiến ​​nó sẽ như thế này:

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

3

Bạn cũng có thể thử các giá trị mặc định. spring-value-annotation

Giá trị mặc định có thể được cung cấp cho các thuộc tính có thể không được xác định. Trong ví dụ này, giá trị "một số mặc định" sẽ được đưa vào:

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

Nếu cùng một thuộc tính được định nghĩa là thuộc tính hệ thống và trong tệp thuộc tính, thì thuộc tính hệ thống sẽ được áp dụng.


Được rồi ... điều này đã giúp tôi. Trên thực tế, ứng dụng của tôi có nhiều tệp application- <profile> .yml và tôi đã gặp lỗi do thuộc tính mới được xác định trong cấu hình chính. chỉ tập tin. Thành thật mà nói, tôi đã mong đợi xác định giá trị chỉ một lần trong cấu hình chính và trong trường hợp ghi đè giá trị trong cấu hình cụ thể. Có vẻ như nó không hoạt động như vậy và một giá trị mặc định phải luôn được cung cấp. Bây giờ tôi hiểu tại sao cấu hình java của tôi không thành công, khi tôi không khởi tạo thuộc tính với giá trị mặc định! Có thể thay đổi hành vi này không? Cảm ơn :-)
funder7

2

Tôi gặp lỗi tương tự trong dịch vụ Vi mô của mình, bất cứ khi nào bạn khai báo chú thích @Value trong chương trình tức là @Value ("$ {project.api.key}")

đảm bảo rằng tệp application.properties của bạn có cùng giá trị không được để trống project.api.key = thêm một số giá trị

MostIMP : nếu không nó sẽ xuất hiện lỗi "Lỗi khi tạo bean với tên 'ServiceFTP': Chèn phụ thuộc tự động mong muốn"


0

Với Spring Boot:

Trong pom.xml

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

Ví dụ trong lớp 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;
    }
    [ ... ]

Trong các tệp thuộc tính:

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

Trong các đối số VM của Application.java

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

Đừng quên chạy lệnh mvn sau khi sửa đổi các thuộc tính!

mvn clean package -Dmaven.test.skip=true

Trong tệp nhật ký cho -Dspring.profiles.active = rec:

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

Trong tệp nhật ký cho -Dspring.profiles.active = prod:

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

Trong tệp nhật ký cho -Dspring.profiles.active = local:

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

Rất tiếc, tôi quên tạo application-local.properties.


0

Tôi đã gặp lỗi tương tự trong dự án microservice của mình. Bản thân thuộc tính bị thiếu trong tệp yml của tôi. Vì vậy, tôi đã thêm tên và giá trị thuộc tính để giải quyết vấn đề của mình


0

Lỗi này xuất hiện do dự án mùa xuân không đọc thuộc tính tệp ( bootstrap.yml hoặc application.yml ). Để giải quyết vấn đề này, bạn phải thêm phụ thuộc vào pom.xml của mình

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


-3

Giải pháp của tôi là thêm một khoảng trắng giữa $ và {.

Ví dụ:

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

trở thành

@Value("$ {project.ftp.adresse}")
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.