Five ways to make it no longer a problem for you to read the contents of the properties file in java

1. Background

  Recently , in the process of project development, I encountered the need to define some custom variables in the properties file for the java program to dynamically read and modify the variables, and no longer need to modify the code. I took this opportunity to sort out and analyze the method of reading the properties file content through the java program in the project integrated and developed by Spring+SpringMVC+Mybatis, and share it with you first.

2. Introduction to the project environment

    Spring 4.2.6.RELEASE SpringMvc

    4.2.6.RELEASE

    Mybatis 3.2.8

    Maven 3.3.9

    Jdk 1.7

    Idea 15.04 content in



<context:property-placeholder location="classpath:jdbc.properties" ignore-unresolvable="true"/>

The above configuration is equivalent to the following configuration, which is a simplification of the following configuration
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
   <property name="ignoreUnresolvablePlaceholders" value="true" />
   <property name="locations">
      <list>
         <value>classpath:jdbc.properties</value>
      </list>
    </property>
</bean>
Note: In this way, if you are in spring-mvc If there is the following configuration in the .xml file, the following red part must not be missing. For its function and principle, see another blog: The function and principle analysis of the use-default-filters attribute of the context:component-scan tag
<!-- Configure component scanning, only Controller annotations are scanned in the springmvc container-->
<context:component-scan base-package="com.hafiz.www" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

 Method 2. Use annotation injection, mainly used in java code to use annotation to inject the corresponding value value in the properties file
<bean id="prop" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
   <!-- Here is the PropertiesFactoryBean class, which also has a locations property and also receives an array, the same as above -->
   <property name="locations">
       <array>
          <value>classpath:jdbc.properties</value>
       </array>
   </property>
</bean>

Method 3. Use the util:properties tag to expose the content in the properties file
<util:properties id="propertiesReader" location="classpath:jdbc.properties"/>
Note: To use the above line configuration, you need to configure it in spring-dao.xml The header of the file declares the following red section

<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"
       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.2.xsd
        http://www.springframework.org/schema/context
        http://www.springframework. org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/util
     http://www.springframework.org/schema/util/spring-util.xsd">Method
  4. Expose properties to custom sub when loading context through PropertyPlaceholderConfigurer Properties of the class for use in the program

<bean id="propertyConfigurer" class="com.hafiz.www.util.PropertyConfigurer">
   <property name="ignoreUnresolvablePlaceholders" value="true"/>
   <property name="ignoreResourceNotFound " value="true"/>
   <property name="locations">
       <list>
          <value>classpath:jdbc.properties</value>
       </list>
   </property>
</bean>
The declaration of the custom class PropertyConfigurer is as follows :

package com.hafiz.www.util;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;

import java.util.Properties;

/**
* Desc:properties配置文件读取类
* Created by hafiz.zhang on 2016/9/14.
*/
public class PropertyConfigurer extends PropertyPlaceholderConfigurer {

    private Properties props;       // 存取properties配置文件key-value结果

    @Override
    protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props)
                            throws BeansException {
        super.processProperties(beanFactoryToProcess, props);
        this.props = props;
    }

    public String getProperty(String key){
        return this.props.getProperty(key);
    }

    public String getProperty(String key, String defaultValue) {
        return this.props.getProperty(key, defaultValue);
    }

    public Object setProperty(String key, String value) {
        return this.props.setProperty(key, value);
    }
}
How to use: Use @Autowired annotation to inject in the class to be used.

  Method 5. Customize the tool class PropertyUtil, and read the properties file content in the static static code block of this class and save it in the static property for other programs to use

package com.hafiz.www.util;

import org.slf4j.Logger ;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.Properties;

/**
* Desc:properties file get tool class
* Created by hafiz.zhang on 2016/9/15.
*/
public class PropertyUtil {
    private static final Logger logger = LoggerFactory.getLogger(PropertyUtil.class );
    private static Properties props;
    static{
        loadProps();
    }

    synchronized static private void loadProps(){
        logger.info("Start loading properties file content....");
        props = new Properties();
        InputStream in = null;
        try {
       <!--The first one, get the properties file stream through the class loader-->
            in = PropertyUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
        <!--Second, get properties file stream through class-->
            //in = PropertyUtil.class.getResourceAsStream("/jdbc.properties");
            props.load(in);
        } catch (FileNotFoundException e) {
            logger.error("jdbc.properties file not found");
        } catch (IOException e) {
            logger.error("IOException occurred");
        } finally {
            try {
                if(null != in) {
                    in.close();
                }
            } catch (IOException e) {
                logger.error("jdbc.properties file stream closed exception");
            }
        }
        logger.info("Loading properties file content completed..... ......");
        logger.info("properties file content: " + props);
    }

    public static String getProperty(String key){
        if(null == props) {
            loadProps();
        }
        return props.getProperty(key);
    }

    public static String getProperty (String key, String defaultValue) {
        if(null == props) {
            loadProps();
        }
        return props.getProperty(key, defaultValue);
    }
}
Explanation: In this way, when the class is loaded, it will automatically Read the content of the configuration file at the specified location and save it to a static property, which is efficient and convenient, loaded once, and can be used multiple times.

Fourth, matters needing attention and suggestions

  The above five methods, the first three methods are relatively rigid, and if you want to use it in a bean annotated with @Controller, you need to declare it in the SpringMVC configuration file spring-mvc.xml. To use it in non-@Controller-annotated beans such as Service and @Respository, you need to declare it in spring.xml in the Spring configuration file. For the reason, please refer to another blog: A first look at the relationship between Spring and SpringMVC parent-child container

  I personally recommend the fourth and fifth configuration methods, the fifth is the best, it does not even need to inject tool class objects, directly call static The method is obtained, and it is only loaded once, and the efficiency is also high. Moreover, the first three methods are not very flexible, and the key value of @Value needs to be modified.

Five, test to verify whether it is available

  1. First we create PropertiesService

package com.hafiz.www.service;

/**
* Desc:java program to obtain the service of properties file content
* Created by hafiz.zhang on 2016/9/16.
*/
public interface PropertiesService {

    /**
     * The first implementation method gets the value of the specified key in the properties file
     *
     * @return
     */
    String getProperyByFirstWay();

    /**
     * The second implementation method gets the value of the specified key in the properties file
     *
     * @return
     */
    String getProperyBySecondWay();

    /**
     * The third implementation method gets the value of the specified key in the properties file
     *
     * @return
     * /
    String getProperyByThirdWay();

    /**
     * The fourth implementation method gets the value of the specified key in the properties file
     *
     * @param key
     *
     * @return
     */
    String getProperyByFourthWay(String key);

    /**
     * The fourth implementation method Get the value of the specified key in the properties file
     *
     * @param key
     *
     * @param defaultValue
     *
     * @return
     */
    String getProperyByFourthWay(String key, String defaultValue);

    /**
     * The fifth implementation method gets the value of the specified key in the properties file
     *
     * @param key
     *
     * @return
     */
    String getProperyByFifthWay(String key) ;

    /**
     * The fifth implementation method gets the value of the specified key in the properties file
     *
     * @param key
     *
     * @param defaultValue
     *
     * @return
     */
    String getProperyByFifthWay(String key, String defaultValue);
}
  2. Create an implementation class PropertiesServiceImpl

package com.hafiz.www.service.impl;

import com.hafiz.www.service.PropertiesService;
import com.hafiz.www.util.PropertyConfigurer;
import com.hafiz.www.util.PropertyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
* Desc:java程序获取properties文件内容的service的实现类
* Created by hafiz.zhang on 2016/9/16.
*/
@Service
public class PropertiesServiceImpl implements PropertiesService {

    @Value("${test}")
    private String testDataByFirst;

    @Value("#{prop.test}")
    private String testDataBySecond;

    @Value("#{propertiesReader[test]}")
    private String testDataByThird;

    @Autowired
    private PropertyConfigurer pc;

    @Override
    public String getProperyByFirstWay() {
        return testDataByFirst;
    }

    @Override
    public String getProperyBySecondWay() {
        return testDataBySecond;
    }

    @Override
    public String getProperyByThirdWay() {
        return testDataByThird;
    }

    @Override
    public String getProperyByFourthWay(String key) {
        return pc.getProperty(key);
    }

    @Override
    public String getProperyByFourthWay(String key, String defaultValue) {
        return pc.getProperty(key, defaultValue);
    }

    @Override
    public String getProperyByFifthWay(String key) {
        return PropertyUtil.getPropery(key);
    }

    @Override
    public String getProperyByFifthWay(String key, String defaultValue) {
        return PropertyUtil.getProperty(key, defaultValue);
    }
}
  3.控制器类PropertyController

package com.hafiz.www.controller;

import com.hafiz.www.service.PropertiesService;
import com.hafiz.www.util.PropertyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

/**
* Desc:properties测试控制器
* Created by hafiz.zhang on 2016/9/16.
*/
@Controller
@RequestMapping("/prop")
public class PropertyController {
    @Autowired
    private PropertiesService ps;

    @RequestMapping(value = "/way/first", method = RequestMethod.GET)
    @ResponseBody
    public String getPropertyByFirstWay(){
        return ps.getProperyByFirstWay();
    }

    @RequestMapping(value = "/way/second", method = RequestMethod.GET)
    @ResponseBody
    public String getPropertyBySecondWay(){
        return ps.getProperyBySecondWay();
    }

    @RequestMapping(value = "/way/third", method = RequestMethod.GET)
    @ResponseBody
    public String getPropertyByThirdWay(){
        return ps.getProperyByThirdWay();
    }

    @RequestMapping(value = "/way/fourth/{key}", method = RequestMethod.GET)
    @ResponseBody
    public String getPropertyByFourthWay(@PathVariable("key") String key){
        return ps.getProperyByFourthWay(key, "defaultValue");
    }

    @RequestMapping(value = "/way/fifth/{key}", method = RequestMethod.GET)
    @ResponseBody
    public String getPropertyByFifthWay(@PathVariable("key") String key){
        return PropertyUtil.getProperty(key, "defaultValue");
    }
}
  4.jdbc.properties文件

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://192.168.1.196:3306/dev?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=123456
jdbc.maxActive=200
jdbc.minIdle=5
jdbc.initialSize=1
jdbc.maxWait=60000
jdbc.timeBetweenEvictionRunsMillis=60000
jdbc.minEvictableIdleTimeMillis=300000
jdbc.validationQuery=select 1 from t_user
jdbc.testWhileIdle=true
jdbc.testOnReturn=false
jdbc.poolPreparedStatements=true jdbc.maxPoolPreparedStatementPerConnectionSize
=20
jdbc.
data
test=com.hafiz.www

6. Summary

  Through this combing and test, we understand the parent-child container relationship between Spring and SpringMVC and the use-default-filters attribute that is most easily ignored when the context:component-scan tag package is scanned. function and principle. Can better locate and quickly solve the problems encountered again. All in all, great~~

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326438190&siteId=291194637