Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
lizongbo opened this issue Aug 13, 2022 · 1 comment
Labels
status: duplicate A duplicate of another issue

Comments

@lizongbo
Copy link

lizongbo commented Aug 13, 2022

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

@wilkinsona
Copy link
Member

#28663 is tracking making this easier.

@wilkinsona wilkinsona closed this as not planned Won't fix, can't repro, duplicate, stale Aug 15, 2022
@wilkinsona wilkinsona added status: duplicate A duplicate of another issue and removed status: waiting-for-triage An issue we've not yet triaged labels Aug 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: duplicate A duplicate of another issue
Projects
None yet
Development

No branches or pull requests

3 participants