Skip to content

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

Closed as not planned
@lizongbo

Description

@lizongbo

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

image

  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:
    image

  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:
    image

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 :

image
image

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions