Jak odczytać wartości z pliku właściwości?


134

Używam wiosny. Muszę odczytać wartości z pliku właściwości. To jest wewnętrzny plik właściwości, a nie zewnętrzny plik właściwości. Plik właściwości może wyglądać jak poniżej.

some.properties ---file name. values are below.

abc = abc
def = dsd
ghi = weds
jil = sdd

Muszę odczytać te wartości z pliku właściwości, a nie w tradycyjny sposób. Jak to osiągnąć? Czy jest jakieś najnowsze podejście do wiosny 3.0?


7
To nie wygląda jak plik właściwości .
Raghuram

Jeśli jest to plik właściwości w sensie Java - tak. W przeciwnym razie jest to niestandardowy format pliku, który musi być traktowany inaczej (i nie możesz po prostu użyć linii jako wartości właściwości w Spring, jeśli nie mają klucza).
Hauke ​​Ingmar Schmidt

3
„Nie w tradycyjny sposób” - co masz na myśli?
Hauke ​​Ingmar Schmidt

mam na myśli używanie adnotacji .. nie przez konfigurację XML ...
user1016403

Odpowiedzi:


200

Skonfiguruj PropertyPlaceholder w swoim kontekście:

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

Następnie odwołujesz się do właściwości swoich ziaren:

@Component
class MyClass {
  @Value("${my.property.name}")
  private String[] myValues;
}

EDYCJA: zaktualizowano kod, aby parsował właściwość z wieloma wartościami oddzielonymi przecinkami:

my.property.name=aaa,bbb,ccc

Jeśli to nie zadziała, możesz zdefiniować ziarno z właściwościami, wstrzyknąć i przetworzyć go ręcznie:

<bean id="myProperties"
      class="org.springframework.beans.factory.config.PropertiesFactoryBean">
  <property name="locations">
    <list>
      <value>classpath*:my.properties</value>
    </list>
  </property>
</bean>

i fasola:

@Component
class MyClass {
  @Resource(name="myProperties")
  private Properties myProperties;

  @PostConstruct
  public void init() {
    // do whatever you need with properties
  }
}

Cześć mrembisz, Dzięki za twoją odpowiedź. Już skonfigurowałem propert-placeholder do odczytywania wartości z zewnętrznego pliku właściwości. ale mam jeden plik właściwości w folderze zasobów. muszę przeczytać i wstrzyknąć. muszę wstrzyknąć wszystkie wartości do listy. Dzięki!
user1016403

Edytowane zgodnie z sugestią @Ethan. Dzięki za aktualizację, nie mogę zaakceptować oryginalnej edycji, było już za późno.
mrembisz

2
W przypadku, gdy masz do czynienia z wartościami oddzielonymi przecinkami, być może rozważ, co jest tutaj proponowane, używając EL: stackoverflow.com/questions/12576156/ ...
arcseldon

2
Jak używamy aaa? Czy to @Value(${aaa}) private String aaa;wtedy możemy System.out.println(aaa)???????

2
@ user75782131 Dokładniej @Value("${aaa}"), zwróć uwagę na cytaty. I tak, możesz go wydrukować, ale nie w konstruktorze, ponieważ konstruktor jest wykonywany przed wstrzyknięciem wartości.
mrembisz

48

Jest wiele sposobów na osiągnięcie tego samego. Poniżej znajduje się kilka powszechnie używanych sposobów na wiosnę:

  1. Korzystanie z PropertyPlaceholderConfigurer

  2. Korzystanie z PropertySource

  3. Korzystanie z ResourceBundleMessageSource

  4. Korzystanie z PropertiesFactoryBean

    i wiele więcej........................

Zakładając, że ds.typejest to kluczowe w pliku nieruchomości.


Za pomocą PropertyPlaceholderConfigurer

Zarejestruj PropertyPlaceholderConfigurerfasolę-

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

lub

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="locations" value="classpath:path/filename.properties" ></property>
</bean>

lub

@Configuration
public class SampleConfig {
 @Bean
 public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
  return new PropertySourcesPlaceholderConfigurer();
  //set locations as well.
 }
}

Po rejestracji PropertySourcesPlaceholderConfigurermożesz uzyskać dostęp do wartości-

@Value("${ds.type}")private String attr; 

Za pomocą PropertySource

W najnowszej wersji wiosennej nie trzeba zarejestrować PropertyPlaceHolderConfigurersię @PropertySource, znalazłem dobrą odnośnik do zrozumienia wersji compatibility-

@PropertySource("classpath:path/filename.properties")
@Component
public class BeanTester {
    @Autowired Environment environment; 
    public void execute() {
        String attr = this.environment.getProperty("ds.type");
    }
}

Za pomocą ResourceBundleMessageSource

Zarejestruj Bean-

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
  <property name="basenames">
    <list>
      <value>classpath:path/filename.properties</value>
    </list>
  </property>
</bean>

Wartość dostępu

((ApplicationContext)context).getMessage("ds.type", null, null);

lub

@Component
public class BeanTester {
    @Autowired MessageSource messageSource; 
    public void execute() {
        String attr = this.messageSource.getMessage("ds.type", null, null);
    }
}

Za pomocą PropertiesFactoryBean

Zarejestruj Bean-

<bean id="properties"
      class="org.springframework.beans.factory.config.PropertiesFactoryBean">
  <property name="locations">
    <list>
      <value>classpath:path/filename.properties</value>
    </list>
  </property>
</bean>

Podłącz instancję Properties do swojej klasy

@Component
public class BeanTester {
    @Autowired Properties properties; 
    public void execute() {
        String attr = properties.getProperty("ds.type");
    }
}

Aby użyć PropertySourcesPlaceholderConfigurer, musisz zwykle ustawić lokalizację lub zasób, w przeciwnym razie nie możesz uzyskać dostępu do pliku właściwości. Możesz użyć np. ClassPathResource generalProperties = new ClassPathResource ("general.properties");
M46

43

W klasie konfiguracji

@Configuration
@PropertySource("classpath:/com/myco/app.properties")
public class AppConfig {
   @Autowired
   Environment env;

   @Bean
   public TestBean testBean() {
       TestBean testBean = new TestBean();
       testBean.setName(env.getProperty("testbean.name"));
       return testBean;
   }
}

Czy w tym przykładzie użyłbyś po prostu innego app.propertiesw testowaniu produkcyjnym? Innymi słowy, czy częścią procesu wdrażania byłoby zastąpienie app.propertieswartościami produkcyjnymi?
Kevin Meredith

1
@KevinMeredith tak, możesz, po prostu podziel konfigurację sprężyny za pomocą adnotacji w profilu stackoverflow.com/questions/12691812/ ...
mokshino

@KevinMeredith używamy folderu poza wdrożeniem wojny: jak c: \ apps \ nazwa_sysa \ conf \ app.properties. Proces wdrażania zostaje uproszczony i mniej podatny na błędy.
jpfreire

27

Oto dodatkowa odpowiedź, która również była dla mnie bardzo pomocna, aby zrozumieć, jak to działa: http://www.javacodegeeks.com/2013/07/spring-bean-and-propertyplaceholderconfigurer.html

wszystkie ziarna BeanFactoryPostProcessor muszą być zadeklarowane ze statycznym modyfikatorem

@Configuration
@PropertySource("classpath:root/test.props")
public class SampleConfig {
 @Value("${test.prop}")
 private String attr;
 @Bean
 public SampleService sampleService() {
  return new SampleService(attr);
 }

 @Bean
 public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
  return new PropertySourcesPlaceholderConfigurer();
 }
}

Nie ma potrzeby jawnego rejestrowania PropertySourcesPlaceholderConfigurerBeana na@PropertySource

@ dubey-theHarcourtians, której wersji Spring (rdzeniowej) używasz? jeśli używasz Spring Boot, nie potrzebujesz go wcale @PropertySource.
Michael Técourt

11

Jeśli chcesz ręcznie odczytać plik właściwości bez użycia @Value.

Dzięki za dobrze napisaną stronę przez Lokesh Gupta: Blog

wprowadź opis obrazu tutaj

package utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ResourceUtils;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.io.File;


public class Utils {

    private static final Logger LOGGER = LoggerFactory.getLogger(Utils.class.getName());

    public static Properties fetchProperties(){
        Properties properties = new Properties();
        try {
            File file = ResourceUtils.getFile("classpath:application.properties");
            InputStream in = new FileInputStream(file);
            properties.load(in);
        } catch (IOException e) {
            LOGGER.error(e.getMessage());
        }
        return properties;
    }
}

Dzięki, działa w moim przypadku. Muszę odczytać właściwości z funkcji statycznej.
Trieu Nguyen


5

Innym sposobem jest użycie ResourceBundle . Zasadniczo otrzymujesz pakiet, używając jego nazwy bez „.properties”

private static final ResourceBundle resource = ResourceBundle.getBundle("config");

I odzyskasz każdą wartość, używając tego:

private final String prop = resource.getString("propName");

0
 [project structure]: http://i.stack.imgur.com/RAGX3.jpg
-------------------------------
    package beans;

        import java.util.Properties;
        import java.util.Set;

        public class PropertiesBeans {

            private Properties properties;

            public void setProperties(Properties properties) {
                this.properties = properties;
            }

            public void getProperty(){
                Set keys = properties.keySet();
                for (Object key : keys) {
                    System.out.println(key+" : "+properties.getProperty(key.toString()));
                }
            }

        }
    ----------------------------

        package beans;

        import org.springframework.context.ApplicationContext;
        import org.springframework.context.support.ClassPathXmlApplicationContext;

        public class Test {

            public static void main(String[] args) {
                // TODO Auto-generated method stub
                ApplicationContext ap = new ClassPathXmlApplicationContext("resource/spring.xml");
                PropertiesBeans p = (PropertiesBeans)ap.getBean("p");
                p.getProperty();
            }

        }
    ----------------------------

 - driver.properties

    Driver = com.mysql.jdbc.Driver
    url = jdbc:mysql://localhost:3306/test
    username = root
    password = root
    ----------------------------



     <beans xmlns="http://www.springframework.org/schema/beans"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:util="http://www.springframework.org/schema/util"
               xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">

            <bean id="p" class="beans.PropertiesBeans">
                <property name="properties">
                    <util:properties location="classpath:resource/driver.properties"/>
                </property>
            </bean>

        </beans>

dodaj wyjaśnienie
HaveNoDisplayName

używając kontenera podstawowego nie możesz uzyskać dostępu do zewnętrznego pliku właściwości zasobów, więc musisz użyć kontenera j2ee, takiego jak ApplicationContext, i musisz użyć walidacji na poziomie fasoli, takiej jak xmlns, xmlns: util, xsi: schemaLocation, xmlns: xsi
Sangram Badi


0

Chciałem klasę użytkową, który nie jest zarządzany przez wiosnę, więc nie ma adnotacji wiosny podoba @Component, @Configurationitd. Ale chciałem klasę odczytu zapplication.properties

Udało mi się to sprawić, aby klasa była świadoma kontekstu sprężyny, stąd jest świadoma Environmenti dlatego environment.getProperty()działa zgodnie z oczekiwaniami.

Mówiąc wprost, mam:

application.properties

mypath=somestring

Utils.java

import org.springframework.core.env.Environment;

// No spring annotations here
public class Utils {
    public String execute(String cmd) {
        // Making the class Spring context aware
        ApplicationContextProvider appContext = new ApplicationContextProvider();
        Environment env = appContext.getApplicationContext().getEnvironment();

        // env.getProperty() works!!!
        System.out.println(env.getProperty("mypath")) 
    }
}

ApplicationContextProvider.java (zobacz Spring, aby pobrać aktualny ApplicationContext )

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class ApplicationContextProvider implements ApplicationContextAware {
    private static ApplicationContext CONTEXT;

    public ApplicationContext getApplicationContext() {
        return CONTEXT;
    }

    public void setApplicationContext(ApplicationContext context) throws BeansException {
        CONTEXT = context;
    }

    public static Object getBean(String beanName) {
        return CONTEXT.getBean(beanName);
    }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.