Versions

Spring Boot Version 2.7.2

Overview

(I'm sorry ,The English translation comes from the search engine Bing.com ) I was migrating the previous Spring application to the current SpringBoot application, and I found that the encoding of application.properties was ISO_8859_1, so I customized the chaset to UTF-8, but because SpringBoot's class PropertiesPropertySourceLoader is not convenient to inherit, I can only use the ugly inheritance implementation to set (Copy OriginTrackedPropertiesLoader.java to my customized java file). It is therefore expected that class plus an extended feature that allows the specified encoding to be used makes it easy to customize the character set using a concise inheritance implementation.

config in Spring application:

java code :

@PropertySource(value = "classpath:application.properties", encoding = "UTF-8")

or xml code:

<context:property-placeholder location="classpath:application.properties" file-encoding="UTF-8"/>

My custom extension steps are as follows:

  1. go to https://start.spring.io/ , generate a gradle project with Java 8 and SpringBoot 2.7.2.

  2. add chinese value to application.properties,just like follow:

  testCnVal = 测试中文
  testCnValUcode = \u6D4B\u8BD5\u6C49\u5B57
  testArrayVal[] = a,b,c

SpringBoot PropertiesPropertySourceLoader class is not convenient to customize the character set UTF-8

  1. write test code to get value,just like follow:
@Service
public class PropTestBean {

    @Value("${testCnVal}")
    private String testCnVal;
    @Value("${testCnValUcode}")
    private String testCnValUcode;
    @Value("${testArrayVal[1]}")
    private String testArrayVal1;

    @EventListener
    void onRefreshEvent(ContextRefreshedEvent event) {
        System.out.println("testCnVal==" + testCnVal);
        System.out.println("testCnValUcode==" + testCnValUcode);
        System.out.println("testArrayVal1==" + testArrayVal1);
        Environment env = event.getApplicationContext().getEnvironment();
        System.out.println("find key|testArrayVal=" + env.containsProperty("testArrayVal"));
        System.out.println("find key|testArrayVal[]=" + env.containsProperty("testArrayVal[]"));
        System.out.println("find key|testArrayVal[1]=" + env.containsProperty("testArrayVal[1]"));
        System.out.println("testArrayVal==" + env.getProperty("testArrayVal[]"));
        System.out.println("testArrayVal2==" + env.getProperty("testArrayVal[2]"));
    }
}
  1. run the main class PropertiesdemoApplication,then see the value is not right: SpringBoot PropertiesPropertySourceLoader class is not convenient to customize the character set UTF-8

  2. copy PropertiesPropertySourceLoader's code and OriginTrackedPropertiesLoader's code to my customized class UglyUTF8PropertiesPropertySourceLoader:

  3. change StandardCharsets.ISO_8859_1 to StandardCharsets.UTF_8 in OriginTrackedPropertiesLoader.CharacterReader's construct method

            CharacterReader(Resource resource) throws IOException {
                reader = new LineNumberReader(new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8));
            }
  1. write config to src/main/resources/META-INF/spring.factories:
org.springframework.boot.env.PropertySourceLoader=com.lizongbo.propertiesdemo.UglyUTF8PropertiesPropertySourceLoader
  1. run the main class PropertiesdemoApplication again,see the value is right: SpringBoot PropertiesPropertySourceLoader class is not convenient to customize the character set UTF-8

Refactored sample code

So I expect to expose the parameters that can be extended to the settings, and the other logic reuses the current code. So I've given an example of the refactored code under com.lizongbo.propertiesdemo.boot.env, adding the following variables

public class PropertiesPropertySourceLoader implements PropertySourceLoader {
    // default charset
    protected Charset charset = StandardCharsets.ISO_8859_1;
    protected boolean expandLists = true;

    private static final String XML_FILE_EXTENSION = ".xml";

    public Charset getCharset() {
        return charset;
    }

    public boolean isExpandLists() {
        return expandLists;
    }

Then my customized extend class is very simple:

  public class UTF8PropertiesPropertySourceLoader extends PropertiesPropertySourceLoader {

    public Charset getCharset() {
        return StandardCharsets.UTF_8;
    }

    public boolean isExpandLists() {
        return true;
    }
}

### refactored code diff :

SpringBoot PropertiesPropertySourceLoader class is not convenient to customize the character set UTF-8 SpringBoot PropertiesPropertySourceLoader class is not convenient to customize the character set UTF-8

the demo project in the attach file:

propertiesdemo.zip

Steps to Reproduce

  1. import the demo project to ide.
  2. run the main class PropertiesdemoApplication.
  3. see console output info.
  4. see spring.factories
  5. review com.lizongbo.propertiesdemo.boot.env's code.

other issues:

29587

28663

7361

5361

Comment From: wilkinsona

https://github.com/spring-projects/spring-boot/issues/28663 is tracking making this easier.