본문 바로가기
FullStack/21. Java

[UTIL] String 템플릿 + Map 결합하여 문자열 생성

by nakanara 2021. 9. 7.
반응형

개요

Stirng 템플릿 포맷과 Map의 데이터를 결합하여 하나의 문자열로 생성하는 기능

DataBase 유형에 따라 SQL 및 사용 문구가 달라지는 현상으로 인해, 필요한 내용을 Resource로 관리하여 유형에 관계없이 실행 가능한 문자열을 만드는 유틸

사용 예로 SQL 기능은 같은데 데이터 유형 및 일부가 달라지는 경우,
해당 프로젝트에는 ORM 등 관련 도구가 없는 경우 가볍게 사용하기 위한 목적

SQL을 예로 들었지만, 목적에 따라서 다른 용도로도 사용이 가능

String 템플릿 Resource

동일한 기능이지만 DB 타입에 따라 다르게 보여줘야하는 SQL

  • MARIADB

파일 경로: WEB-INF/classes/resource/mariadb/table.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
    <comment>MariaDB Resource</comment>

    <entry key="createTable">

    create table {{tablename}}
    (
      TAB_ID       VARCHAR(100) NOT NULL,
      TAB_REG_DTTM VARCHAR(14),
      TAB_TITLE    VARCHAR(500),
      TAB_CONTENT  MEDIUMTEXT
    )
    </entry>
</properties>    
  • ORACLE

파일 경로: WEB-INF/classes/resource/oracle/table.xml


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
    <comment>Oracle Resource</comment>

    <entry key="createTable">

    create table {{tablename}}
    (
      TAB_ID       VARCHAR2(100) NOT NULL,
      TAB_REG_DTTM VARCHAR2(14),
      TAB_TITLE    VARCHAR2(500),
      TAB_CONTENT  CLOB
    )
    </entry>
</properties>    

리소스를 읽어 properties로 저장, 사용할 때 resource와 data를 결합하는 기능


public class StringResource {

    static Logger logger = LoggerFactory.getLogger(StringResource.class);

    private static StringResource stringResource = null;
    private Properties properties = new Properties();

    private String path = "WEB-INF/classes/resource";
    private String dbType = "mariadb";
    static Pattern pattern = Pattern.compile("\\{\\{(\\w+|_)}}"); // {{key}}

    // todo singleton 생성 방식 변경 필요
    // https://www.journaldev.com/1377/java-singleton-design-pattern-best-practices-examples
    /**
     * StringResource 생성 
     **/
    public static synchronized StringResource getInstance(){
        if(stringResource == null) {
            stringResource = new StringResource();
        }

        return stringResource;
    }

    /**
     * 외부에서 호출 못하는 생성자 
     **/
    private StringResource(){        
      // todo dbType 외부 변수로 받아서 처리
        init(this.dbType);
    }


    private void init(String dbType){
        this.dbType = dbType;
        logger.debug("stringResource Init");

        load();
    }

    /**
     * Resource Load
     **/
    private void load(){

        // ctx.getRealPath("").replace('\\', '/');
        String webPath = "";  // WEB 절대 경로 필요
        String resPath = webPath + path + "/" + dbType;
        File file = new File(resPath);

        // XML 파일만을 필터링
        String resources[] = file.list(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                if(name.endsWith(".xml")) return true;
                return false;
            }
        });


        // 필터링된 파일 load
        for(String res : resources ) {

            try (FileInputStream inputStream = new FileInputStream(resPath+"/"+res)) {
                properties.loadFromXML(inputStream);  // xml 파일 로드

            } catch (IOException ioe) {
                logger.error("{}", ioe);
            }
        }

        logger.info("StringResrouce.inited.");
    }

    /**
     * 초기화
     **/
    public void reset(){
        logger.debug("stringResource ReLoad");

        properties.clear();

        load();
    }

    /**
     * 항목 조회
     **/
    public String get(String key) {
        return properties.getProperty(key);
    }

    public String get(String key, String defVal) {
        return properties.getProperty(key, defVal);
    }

    /**
     * 해당 Template를 전달한 값과 결합한다.
     * @param key
     * @param data 데이터
     * @return
     */
    public String getTemplateRender(String key, Map data) {
        String str = get(key);

        // 값이 없다면 공백
        if (StringUtil.invalid(str)) {
            return "";
        }

        long len = str.length();
        Matcher matcher  = pattern.matcher(str);  // 패턴
        StringBuffer buf = new StringBuffer();

        int s = 0;
        while(matcher.find()) {
            String token = matcher.group(1);
            buf.append(str.substring(s, matcher.start()));
            buf.append(data.get(token));

            s = matcher.end();
        }

        // 남은 문자가 존재하는 경우 나머지 붙이기
        if(s != len) {
            buf.append(str.substring(s));
        }

        return buf.toString();

    }
}

사용 예시


String id = "createTable";
Map<String, String> data = new HashMap();
data.put("tablename", "TB_SAMPLE");
String sql = StringResource.getInstance().getTemplateRender(id, data);

...

#string #template #render

반응형