【问题标题】:How do I load nested key value pairs from a properties file into a Java object using Spring?如何使用 Spring 将属性文件中的嵌套键值对加载到 Java 对象中?
【发布时间】:2013-10-04 16:02:15
【问题描述】:

当我们知道需要哪些属性时,我了解如何使用 Spring 和 PropertyPlaceholderConfigurer 加载 .properties 文件,并使用 @Value 将这些值存储到变量或某个对象中。

但是,当键可以变化时,如何让 Spring 加载具有嵌套键值对的属性文件?

例如,假设我有以下 car.properties 文件:

Chevy=Corvette:String,1234567890:long,sportsCar:String
Honda=Odyssey:String,2345678910:long,minivan:String
Ford=F350:String,4567891011:long,truck:String

其中属性文件的每一行都有一个作为品牌的键,然后是三个嵌套的键值对,即一个用于模型,一个用于 VIN,一个用于车辆类型,即

<make>=<model>:<dataType>,<vin>:<dataType>,<vehicleType>:<dataType>

我正在使用这种结构,因为以后会添加未来的车辆,并且我不想更改我的底层 Java 代码。假设我想使用这些车辆属性来生成一些关于车辆的随机数据进行测试。

如何使用 Spring 将属性文件的每一行加载为要存储在 arraylist 中的车辆值集合?我想我会有一个二维数组列表,其中每辆车都是“所有车辆”数组列表中的一个数组列表。然后我会随机选择一个车辆数组列表来生成虚拟车辆数据。

无论如何,我认为我在正确的轨道上,但似乎无法弄清楚如何使用 Spring 加载我的嵌套键值对。有什么建议吗?

更新的 context.xml 对我有用:

顺便说一句,这是我正在使用的 context.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:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans     http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://www.springframework.org/schema/util     http://www.springframework.org/schema/util/spring-util-2.0.xsd">

    <!-- creates a java.util.Properties instance with values loaded from the supplied     location -->
<util:properties id="carProperties" location="classpath:/car.properties"/>

    <bean class="com.data.rcgen.generator.CarLoader">
        <property name="sourceProperties" ref="carProperties" />
    </bean>

</beans>

【问题讨论】:

    标签: java spring properties nested key-value


    【解决方案1】:

    spring 不可能为你做这件事。您将需要自己实现解析。但是,spring 可以为您提供一些方便的实用程序类:

    示例(可能包含拼写错误):

    <util:properties id="carProperties" location="classpath:car.properties"/>
    
    <bean class="my.package.CarLoader">
        <property name="sourceProperties" ref="carProperties" />
    </bean>
    

    public class Car {
        private String name;
        private String category;
        // ... Getters and setters
    }
    

    public class CarLoader {
    
        private Properties sourceProperties;
    
        public List<Car> getCars() {
            List<Car> cars = new ArrayList<Car>();
            for (Object key : sourceProperties.keySet()) {
                // Do the parsing - naive approach
                String[] values = sourceProperties.getProperty((String) key).split(",");
                // Create bean wrapper and set the parsed properties... will handle data convesions with 
                // default property editors or can use custom ConversionService via BeanWrapper#setConversionService
                BeanWrapper wrappedCar = PropertyAccessorFactory.forBeanPropertyAccess(new Car());
                wrappedCar.setPropertyValue("name", values[0].split(":")[0]); // Getting rid of the `:type`
                wrappedCar.setPropertyValue("category", values[2].split(":")[0]); // Getting rid of the `:type`
                // Phase 3 - prosper
                cars.add((Car) wrappedCar.getWrappedInstance());
            }
            return cars;
        }
    
        public void setSourceProperties(Properties properties) {
            this.sourceProperties = properties;
        }
    
    }
    

    更新基本示例如何从main 方法引导应用程序上下文:

    public class Main {
    
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("context.xml");
            CarLoader carLoader = context.getBean(CarLoader.class);
            for (Car car : carLoader.getCars()) {
                System.out.println("CAR - " + car.getName());
            }
        }
    
    }
    

    【讨论】:

    • 我查看了您提到的 util:properties 配置元素,它创建了一个 java.util.Properties 实例。然后如何在 Java 类中访问该实例以使用 BeanWrapperImpl?能举个简单的例子吗?
    • 如果您希望加载的结果在您的应用程序上下文中注册为 bean,您也可以让加载器实现 FactoryBean
    • 因此,使用您的示例,我现在尝试通过 MainApp.java 类中的 main 方法执行我的代码。我对如何访问数组列表的内容有点困惑。现在我只是想打印内容。但是当我尝试调用 CarLoader 类的 getCars() 方法时,我得到了 NullPointerException。顺便说一句,我确实将上面称为“值”的变量解析为“值”
    • 修正了错字。 NPE 你的意思是sourceProperties 没有设置?您是否访问了正确的 CarLoader 实例?只是想确保你没有尝试做new CarLoader().getCars()
    • 没关系,我查看了 Spring 文档,发现我的 context.xml 引用已过期。我更新了上面的 context.xml,现在我得到了信息。感谢您的所有帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多