• spring 使用外部属性文件


    一、PropertyPlaceholderConfigurer

    spring提供的PropertyPlaceholderConfigurer实现类能够使Bean在配置时引用外部属性文件。
    PropertyPlaceholderConfigurer实现了BeanFactoryPostProcessorBean接口,因而也是一个Bean工厂后处理器。


    二、PropertyPlaceholderConfigurer的使用

    1、xml配置及注解方式:

          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.16.RELEASE</version>
          </dependency>
          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.16.RELEASE</version>
          </dependency>
          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>4.3.16.RELEASE</version>
          </dependency>
    pom.xml
    name=zhangsan
    age=23
    my.properties
    package test;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Driver {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("my.xml");
            User user = context.getBean("user", User.class);
            System.out.println(user.getName());
            System.out.println(user.getAge());
        }
    }
    class User {
        @Value("${name}")
        private String name;
        private int age;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
    }
    java 类
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:p="http://www.springframework.org/schema/p"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="
          http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans.xsd
          http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context.xsd">
        <!-- spring 引入属性文件 -->
        <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
            p:location="classpath:my.properties"
            p:fileEncoding="utf-8"/>
        <!-- 开启包扫描,因为User类使用到了@Value注解;包扫描不支持裸体类上的注解 -->
        <context:component-scan base-package="test"/>
        <!-- 使用外部属性文件值赋值 -->
        <bean id="user" class="test.User" p:age="${age}"/>
    </beans>
    spring my.xml

    PropertyPlaceholderConfigurer的其他属性:
    locations:可以引入多个属性文件
    fileEncoding:属性文件的编码格式
    order:指定多个属性的优先级
    placeholderPrefix:默认值为“${”,可以修改
    placeholderSuffix:默认为“}”

    除了使用<bean>声明PropertyPlaceholderConfigurer引入属性文件这种方式外,还可以使用另一种简洁的方式;但如果希望自定义一些额外的高级功能,如属性加密、使用数据库表来保存配置信息时,就必须使用<bean>声明PropertyPlaceholderConfigurer的方式

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:p="http://www.springframework.org/schema/p"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="
          http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans.xsd
          http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context.xsd">
        <!-- spring 引入属性文件 -->
        <context:property-placeholder location="my.properties"/>
        <!-- 开启包扫描,因为User类使用到了@Value注解;包扫描不支持裸体类上的注解 -->
        <context:component-scan base-package="test"/>
        <!-- 使用外部属性文件值赋值 -->
        <bean id="user" class="test.User" p:age="${age}"/>
    </beans>
    spring my.xml

    2、Java配置及注解方式:

          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.16.RELEASE</version>
          </dependency>
          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.16.RELEASE</version>
          </dependency>
          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>4.3.16.RELEASE</version>
          </dependency>
    pom.xml
    name=zhangsan
    age=23
    my.properties
    package test;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    public class Driver {
        public static void main(String[] args) {
            ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
            User user = context.getBean("user", User.class);
            System.out.println(user.getName());
            System.out.println(user.getAge());
        }
    }
    class User {
        @Value("${name}")
        private String name;
        @Value("${age}")
        private int age;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
    }
    java类
    package test;
    
    import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.io.ClassPathResource;
    
    @Configuration
    @ComponentScan
    public class MyConfig {
        @Bean
        public User user() {
            return new User();
        }
        @Bean
        public PropertyPlaceholderConfigurer PropertyPlaceholderConfigurer() {
            PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();
            configurer.setLocation(new ClassPathResource("my.properties"));
            return configurer;
        }
    
    }
    java 配置类

    三、自定义PropertyPlaceholderConfigurer——支持加密

    加密

    如果属性信息是数据库用户名、密码等敏感信息,应该使用密文方式。虽说Web应用的客户端用户看不到服务器端的属性文件,但内部人员却可以轻易查看属性文件的内容,这样容易造成数据库访问权限的泄露。

    实现

    PropertyPlaceholderConfigurer类继承了PlaceholderConfigurerSupport,PlaceholderConfigurerSupport有几个protected的空实现的属性转换方法,专门用于在使用属性之前对属性值进行转换;
    所以我们需要自定义PlaceholderConfigurerSupport的实现类并覆盖相应的属性转换方法来代替spring提供的PropertyPlaceholderConfigurer

    信息的加密可分为对称和非对称两种方式,前者加密后可以解密还原,而后者不可以还原;MD5是非对称加密,DES是对称加密,这里使用DES方式。DES加密解密的关键是加密密钥。

    demo

          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.16.RELEASE</version>
          </dependency>
          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.16.RELEASE</version>
          </dependency>
          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>4.3.16.RELEASE</version>
          </dependency>
          <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
          </dependency>
    pom.xml
    name=agyo9QHJ78MfJAfVsP+M2w==
    age=ArphqsQ7cdE=
    my.properties
    package test;
    
    import java.security.Key;
    import java.security.SecureRandom;
    
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    
    import sun.misc.BASE64Decoder;
    import sun.misc.BASE64Encoder;
    
    public class DESUtils {
        // 指定DES加密解密所用的密钥
        private static Key key;
        private static String KEY_STR = "myKey";
        static {
            try {
                KeyGenerator generator = KeyGenerator.getInstance("DES");
                generator.init(new SecureRandom(KEY_STR.getBytes()));
                key = generator.generateKey();
                generator = null;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        /**
         * 对字符串进行DES加密,返回Base64编码的加密字符串
         */
        public static String getEncryptString(String str) {
            BASE64Encoder base64en = new BASE64Encoder();
            try {
                byte[] strBytes = str.getBytes("UTF8");
                Cipher cipher = Cipher.getInstance("DES");
                cipher.init(Cipher.ENCRYPT_MODE, key);
                byte[] encryptStrBytes = cipher.doFinal(strBytes);
                return base64en.encode(encryptStrBytes);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        /**
         * 对Base64编码的加密字符串进行DES解密,返回解密后的字符串
         */
        public static String getDecryptString(String str) {
            BASE64Decoder base64De = new BASE64Decoder();
            try {
                byte[] strBytes = base64De.decodeBuffer(str);
                Cipher cipher = Cipher.getInstance("DES");
                cipher.init(Cipher.DECRYPT_MODE, key);
                byte[] decryptStrBytes = cipher.doFinal(strBytes);
                return new String(decryptStrBytes, "UTF8");
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
    
        }
    
        /**
         * 对入参的字符串加密,并打印密文
         */
        public static void main(String[] args) throws Exception {
            args = new String[]{"zhangsan", "23"};
            if (args == null || args.length < 1) {
                System.out.println("请输入要加密的字符,用空格分隔.");
            } else {
                for (String arg : args) {
                    System.out.println(arg + ":" + getEncryptString(arg));
                }
            }
            
            //System.out.println(getDecryptString("WnplV/ietfQ="));
            //System.out.println(getDecryptString("gJQ9O+q34qk="));
        }
    }
    DESUtils.java
    package test;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    public class Driver {
        public static void main(String[] args) {
            ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
            User user = context.getBean("user", User.class);
            System.out.println(user.getName());
            System.out.println(user.getAge());
        }
    }
    class User {
        @Value("${name}")
        private String name;
        @Value("${age}")
        private int age;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
    }
    Driver.java 
    package test;
    
    import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
    
    public class MyPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
        // 需要解密的属性
        private String[] encryptPropNames ={"name","age"};
    
        // 解密
        @Override
        protected String convertProperty(String propertyName, String propertyValue) {        
            if(isEncryptProp(propertyName)){
                String decryptValue = DESUtils.getDecryptString(propertyValue);
                System.out.println(decryptValue);
                return decryptValue;
            }else{
                return propertyValue;
            }
        }
        
        /**
         * 判断是否是加密的属性
         */
        private boolean isEncryptProp(String propertyName){
            for(String encryptPropName:encryptPropNames){
                if(encryptPropName.equals(propertyName)){
                    return true;
                }
            }
            return false;
        }
    }
    自定义属性文件加载器
    package test;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.io.ClassPathResource;
    
    @Configuration
    @ComponentScan // 因为用到了@Value注解,所以需要开启扫描
    public class MyConfig {
        @Bean
        public User user() {
            return new User();
        }
    //    @Bean
    ////    public PropertyPlaceholderConfigurer PropertyPlaceholderConfigurer() {
    ////        PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();
    ////        configurer.setLocation(new ClassPathResource("my.properties"));
    ////        return configurer;
    ////    }
        @Bean
        public MyPropertyPlaceholderConfigurer encryptPropertyPlaceholderConfigurer() {
            MyPropertyPlaceholderConfigurer configurer = new MyPropertyPlaceholderConfigurer();
            configurer.setLocation(new ClassPathResource("my.properties"));
            return configurer;
        }
    }
    java配置类

    四、属性文件引用属性文件的属性值

    Spring允许在xml、java类中使用${xxx}、@Value("${xxx}")引用属性值,也允许在属性文件中使用${xxx}引用其它属性文件的属性值
    
    name=lisi
    age=${age}
    my.properties
    age=18
    my2.properties
    package test;
    
    import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.io.ClassPathResource;
    
    @Configuration
    public class MyConfig {
        @Bean
        public User user() {
            return new User();
        }
        @Bean
        public PropertyPlaceholderConfigurer PropertyPlaceholderConfigurer() {
            PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();
            configurer.setLocations(new ClassPathResource[] {new ClassPathResource("my.properties"),
                                    new ClassPathResource("my2.properties")});
            return configurer;
        }
    }
    MyConfig.java

      

  • 相关阅读:
    Windows 驱动加载程序代码
    coding push 上传文件
    MinGW 可以编译驱动的
    通过使用 NTLite 工具实现精简Windows系统
    一些常用的注入技巧
    Python 图片转字符图
    MySQL数据库及注入方法
    路由器被蹭网后,我有被黑的风险吗?
    markdown 实现代码折叠效果
    Windows 签名伪造工具的使用,Python,签名
  • 原文地址:https://www.cnblogs.com/Mike_Chang/p/10276303.html
Copyright © 2020-2023  润新知