จะอ่านค่าจากไฟล์คุณสมบัติได้อย่างไร?


134

ฉันใช้สปริง ฉันต้องการอ่านค่าจากไฟล์คุณสมบัติ นี่คือไฟล์คุณสมบัติภายในไม่ใช่ไฟล์คุณสมบัติภายนอก ไฟล์ Properties ได้ตามด้านล่าง

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

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

ฉันต้องการอ่านค่าเหล่านั้นจากไฟล์คุณสมบัติไม่ใช่แบบดั้งเดิม จะบรรลุได้อย่างไร? มีแนวทางล่าสุดเกี่ยวกับสปริง 3.0 หรือไม่?


7
สิ่งนี้ดูเหมือนไฟล์คุณสมบัติ
Raghuram

หากเป็นไฟล์คุณสมบัติในความหมาย Java - ใช่ มิฉะนั้นจะเป็นรูปแบบไฟล์ที่กำหนดเองซึ่งจำเป็นต้องได้รับการปฏิบัติที่แตกต่างกัน (และคุณไม่สามารถใช้บรรทัดเป็นค่าคุณสมบัติใน Spring ได้หากไม่มีคีย์)
Hauke ​​Ingmar Schmidt

3
"ไม่ใช่ในแบบดั้งเดิม" - คุณหมายถึงอะไร?
Hauke ​​Ingmar Schmidt

ฉันหมายถึงการใช้คำอธิบายประกอบ .. ไม่ใช่โดยการกำหนดค่า xml ...
user1016403

คำตอบ:


200

กำหนดค่า PropertyPlaceholder ในบริบทของคุณ:

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

จากนั้นคุณอ้างถึงคุณสมบัติในถั่วของคุณ:

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

แก้ไข: อัปเดตรหัสเพื่อแยกวิเคราะห์คุณสมบัติด้วยค่าที่คั่นด้วยเครื่องหมายจุลภาคหลายค่า:

my.property.name=aaa,bbb,ccc

หากไม่ได้ผลคุณสามารถกำหนด bean ที่มีคุณสมบัติฉีดและประมวลผลด้วยตนเอง:

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

และถั่ว:

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

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

สวัสดี mrembisz ขอบคุณสำหรับการตอบกลับของคุณ ฉันได้กำหนดค่าตัวยึดตำแหน่งที่เหมาะสมเพื่ออ่านค่าจากไฟล์คุณสมบัติภายนอกแล้ว แต่ฉันมีไฟล์คุณสมบัติหนึ่งไฟล์ในโฟลเดอร์ทรัพยากร ฉันต้องอ่านและฉีด ฉันต้องฉีดค่าทั้งหมดลงในรายการ ขอบคุณ!
user1016403

แก้ไขตามที่ @Ethan แนะนำ ขอบคุณสำหรับการอัปเดตไม่สามารถยอมรับการแก้ไขต้นฉบับมันสายเกินไปแล้ว
mrembisz

2
สำหรับกรณีที่คุณกำลังจัดการกับค่าที่คั่นด้วยเครื่องหมายจุลภาคอาจพิจารณาสิ่งที่กำลังเสนอที่นี่โดยใช้ EL: stackoverflow.com/questions/12576156/…
arcseldon

2
เราจะใช้aaaอย่างไร? @Value(${aaa}) private String aaa;แล้วเราจะทำได้ไหมSystem.out.println(aaa)???????

2
@ user75782131 แม่นยำมากขึ้น@Value("${aaa}")คำนึงถึงคำพูด และใช่คุณสามารถพิมพ์ได้ยกเว้นไม่ได้อยู่ในตัวสร้างเนื่องจากตัวสร้างถูกดำเนินการก่อนที่จะมีการแทรกค่า
mrembisz

48

มีหลายวิธีที่จะบรรลุเช่นเดียวกัน ด้านล่างนี้เป็นวิธีที่ใช้กันทั่วไปในฤดูใบไม้ผลิ -

  1. การใช้ PropertyPlaceholderConfigurer

  2. ใช้ PropertySource

  3. การใช้ ResourceBundleMessageSource

  4. การใช้ PropertiesFactoryBean

    และอื่น ๆ อีกมากมาย........................

สมมติว่าds.typeเป็นกุญแจสำคัญในไฟล์คุณสมบัติของคุณ


การใช้ PropertyPlaceholderConfigurer

ลงทะเบียนPropertyPlaceholderConfigurerbean-

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

หรือ

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

หรือ

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

หลังจากลงทะเบียนPropertySourcesPlaceholderConfigurerคุณสามารถเข้าถึงมูลค่า -

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

การใช้ PropertySource

ในเวอร์ชั่นฤดูใบไม้ผลิล่าสุดที่คุณไม่จำเป็นต้องลงทะเบียนPropertyPlaceHolderConfigurerกับ@PropertySourceผมพบว่าดีลิงค์ที่จะเข้าใจรุ่น compatibility-

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

การใช้ ResourceBundleMessageSource

ลงทะเบียน Bean-

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

เข้าถึงมูลค่า -

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

หรือ

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

การใช้ PropertiesFactoryBean

ลงทะเบียน Bean-

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

Wire Properties อินสแตนซ์ในคลาสของคุณ -

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

ในการใช้ PropertySourcesPlaceholderConfigurer โดยปกติคุณต้องตั้งค่าตำแหน่งหรือทรัพยากรมิฉะนั้นคุณจะไม่สามารถเข้าถึงไฟล์คุณสมบัติได้ คุณสามารถใช้เช่น ClassPathResource generalProperties = new ClassPathResource ("general.properties");
M46

43

ในคลาสการกำหนดค่า

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

ในตัวอย่างนี้คุณจะใช้การทดสอบที่แตกต่างกันapp.propertiesในการผลิต v. กล่าวอีกนัยหนึ่งส่วนหนึ่งของกระบวนการปรับใช้ของคุณจะถูกแทนที่app.propertiesด้วยค่าการผลิตหรือไม่?
Kevin Meredith

1
@KevinMeredith ใช่คุณทำได้เพียงแค่แยกการกำหนดค่าสปริงของคุณตามคำอธิบายประกอบโปรไฟล์stackoverflow.com/questions/12691812/…
mokshino

@KevinMered เราใช้โฟลเดอร์นอก deploy war: เช่น c: \ apps \ sys_name \ conf \ app.properties กระบวนการทำให้ใช้งานได้ง่ายขึ้นและเกิดข้อผิดพลาดน้อยลง
jpfreire

27

นี่คือคำตอบเพิ่มเติมที่ช่วยให้ฉันเข้าใจว่ามันทำงานอย่างไร: http://www.javacodegeeks.com/2013/07/spring-bean-and-propertyplaceholderconfigurer.html

ถั่ว BeanFactoryPostProcessor ใด ๆ ต้องถูกประกาศด้วยตัวปรับแต่งแบบคงที่

@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();
 }
}

ไม่จำเป็นต้องลงทะเบียนPropertySourcesPlaceholderConfigurerBean อย่างชัดเจนด้วย@PropertySource

@ dubey-theHarcourtians คุณใช้ Spring (core) เวอร์ชั่นไหน หากคุณใช้ Spring Boot คุณไม่จำเป็นต้องใช้@PropertySourceเลยด้วยซ้ำ
Michael Técourt

11

หากคุณต้องการอ่านไฟล์คุณสมบัติด้วยตนเองโดยไม่ใช้ @Value

ขอบคุณสำหรับเพจที่เขียนดีโดย Lokesh Gupta: Blog

ป้อนคำอธิบายภาพที่นี่

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

ขอบคุณมันใช้ได้กับกรณีของฉัน ฉันต้องการอ่านคุณสมบัติจากฟังก์ชันคงที่
Trieu Nguyen

6

คุณต้องใส่ PropertyPlaceholderConfigurer bean ในบริบทแอปพลิเคชันของคุณและตั้งค่าคุณสมบัติตำแหน่ง

ดูรายละเอียดที่นี่: http://www.zparacha.com/how-to-read-properties-file-in-spring/

คุณอาจต้องแก้ไขไฟล์คุณสมบัติของคุณเล็กน้อยเพื่อให้สิ่งนี้ทำงานได้

หวังว่าจะช่วยได้


5

อีกวิธีหนึ่งคือการใช้ResourceBundle โดยทั่วไปคุณจะได้รับบันเดิลโดยใช้ชื่อโดยไม่มี ".properties"

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

และคุณกู้คืนค่าใด ๆ โดยใช้สิ่งนี้:

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>

เพิ่มคำอธิบาย
HaveNoDisplayName

การใช้คอนเทนเนอร์หลักคุณไม่สามารถเข้าถึงไฟล์คุณสมบัติทรัพยากรภายนอกได้ดังนั้นคุณต้องใช้คอนเทนเนอร์ j2ee เช่น ApplicationContext และคุณต้องใช้การตรวจสอบระดับถั่วเช่น xmlns, xmlns: util, xsi: schemaLocation, xmlns: xsi
Sangram Badi

0

ฉันขอแนะนำให้อ่านลิงก์นี้https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.htmlจากเอกสาร SpringBoot เกี่ยวกับการฉีดการกำหนดค่าภายนอก พวกเขาไม่ได้พูดถึงการดึงข้อมูลจากไฟล์คุณสมบัติเท่านั้น แต่ยังรวมถึง YAML และแม้แต่ไฟล์ JSON ด้วย ฉันพบว่ามันมีประโยชน์ ฉันหวังว่าคุณจะทำเช่นกัน


0

ผมอยากชั้นยูทิลิตี้ที่ไม่ได้รับการจัดการโดยฤดูใบไม้ผลิจึงไม่มีคำอธิบายประกอบในฤดูใบไม้ผลิชอบ@Component, @Configurationฯลฯ แต่ผมอยากเรียนเพื่ออ่านจากapplication.properties

ฉันจัดการให้มันใช้งานได้โดยให้ชั้นเรียนตระหนักถึง Spring Context ดังนั้นจึงรับรู้Environmentและด้วยเหตุนี้จึงได้environment.getProperty()ผลตามที่คาดไว้

เพื่อให้ชัดเจนฉันมี:

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 (ดูSpring รับ 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);
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.