2013-07-01 19 views
11

Tôi đang sử dụng Spring 3.2 trong một ứng dụng web và tôi muốn có tệp .properties trong đường dẫn lớp có chứa các giá trị mặc định. Người dùng sẽ có thể sử dụng JNDI để xác định vị trí nơi khác .properties được lưu trữ để ghi đè các giá trị mặc định.Vị trí @PropertySource tùy chọn

Tác phẩm sau đây miễn là người dùng đã đặt configLocation làm thuộc tính JNDI.

@Configuration 
@PropertySource({ "classpath:default.properties", "file:${java:comp/env/configLocation}/override.properties" }) 
public class AppConfig 
{ 
} 

Tuy nhiên, phần ghi đè bên ngoài phải là tùy chọn và do đó thuộc tính JNDI.

Hiện nay tôi nhận được một ngoại lệ (java.io.FileNotFoundException: comp\env\configLocation\app.properties (The system cannot find the path specified) khi tài sản JNDI là mất tích.

Làm thế nào tôi có thể xác định tùy chọn .properties mà chỉ được sử dụng khi tài sản JNDI (configLocation) được thiết lập? Đây có phải là thậm chí có thể với @PropertySource hoặc là có một giải pháp

Trả lời

3

Hãy thử những điều sau đây Tạo một ApplicationContextInitializer

trong một bối cảnh Web:?. ApplicationContextInitializer<ConfigurableWebApplicationContext> và đăng ký nó trong web.xml qua:

<context-param> 
    <param-name>contextInitializerClasses</param-name> 
    <param-value>...ContextInitializer</param-value> 
</context-param> 

Trong ContextInitializer, bạn có thể thêm tệp thuộc tính của bạn thông qua classpath và hệ thống tệp (chưa thử JNDI).

public void initialize(ConfigurableWebApplicationContext applicationContext) { 
    String activeProfileName = null; 
    String location = null; 

    try { 
     ConfigurableEnvironment environment = applicationContext.getEnvironment(); 
     String appconfigDir = environment.getProperty(APPCONFIG); 
     if (appconfigDir == null) { 
     logger.error("missing property: " + APPCONFIG); 
     appconfigDir = "/tmp"; 
     } 
     String[] activeProfiles = environment.getActiveProfiles(); 

     for (int i = 0; i < activeProfiles.length; i++) { 
     activeProfileName = activeProfiles[i]; 
     MutablePropertySources propertySources = environment.getPropertySources(); 
     location = "file://" + appconfigDir + activeProfileName + ".properties"; 
     addPropertySource(applicationContext, activeProfileName, 
       location, propertySources); 
     location = "classpath:/" + activeProfileName + ".properties"; 
     addPropertySource(applicationContext, activeProfileName, 
          location, propertySources); 
     } 
     logger.debug("environment: '{}'", environment.getProperty("env")); 

    } catch (IOException e) { 
     logger.info("could not find properties file for active Spring profile '{}' (tried '{}')", activeProfileName, location); 
     e.printStackTrace(); 
    } 
    } 

    private void addPropertySource(ConfigurableWebApplicationContext applicationContext, String activeProfileName, 
           String location, MutablePropertySources propertySources) throws IOException { 
    Resource resource = applicationContext.getResource(location); 
    if (resource.exists()) { 
     ResourcePropertySource propertySource = new ResourcePropertySource(location); 
     propertySources.addLast(propertySource); 
    } else { 
     logger.info("could not find properties file for active Spring profile '{}' (tried '{}')", activeProfileName, location); 
    } 
    } 

Đoạn mã trên cố gắng để tìm một tập tin bất động sản cho mỗi cấu hình hoạt động (xem: How to set active spring 3.1 environment profile via a properites file and not via an env variable or system property)

+0

Cảm ơn. Tôi cũng đã giải quyết nó bằng cách sử dụng 'ApplicationContextInitializer'. Có vẻ như đó là cách khả thi duy nhất để làm điều đó. –

33

Tính đến mùa xuân 4, vấn đề SPR-8371 đã được giải quyết. Do đó, chú thích @PropertySource có thuộc tính mới được gọi là ignoreResourceNotFound đã được thêm chính xác cho mục đích này. Ngoài ra, đó cũng là @PropertySources chú thích mới cho phép triển khai như:

@PropertySources({ 
    @PropertySource("classpath:default.properties"), 
    @PropertySource(value = "file:/path_to_file/optional_override.properties", ignoreResourceNotFound = true) 
}) 
+3

Lưu ý theo JavaDoc '@ PropertySources', trong Java 8, bạn có thể trực tiếp áp dụng nhiều chú thích' @ PropertySource' cho một lớp không có trình bao bọc. –

+2

@ billc.cn Khá đúng. Tôi đã viết một [bài đăng blog] (http://www.jayway.com/2014/02/16/spring-propertysource/) khoảng một năm trước về '@ PropertySource', trong đó tôi cũng đã đề cập đến [chú thích lặp lại của Java 8] (http://openjdk.java.net/jeps/120). – matsev

5

Nếu bạn chưa phải vào mùa xuân 4 (xem giải pháp matsev của), đây là một giải pháp tiết hơn, nhưng tương đương:

@Configuration 
@PropertySource("classpath:default.properties") 
public class AppConfig { 

    @Autowired 
    public void addOptionalProperties(StandardEnvironment environment) { 
     try { 
      String localPropertiesPath = environment.resolvePlaceholders("file:${java:comp/env/configLocation}/override.properties"); 
      ResourcePropertySource localPropertySource = new ResourcePropertySource(localPropertiesPath); 
      environment.getPropertySources().addLast(localPropertySource); 
     } catch (IOException ignored) {} 
    } 

}