[java] 속도 템플릿과 유사한 자바의 문자열 대체

String텍스트로 객체를 전달할 수있는 Java에 대체 메커니즘 이 있습니까? 문자열이 발생하면이를 대체합니다.
예를 들어 텍스트는 다음과 같습니다.

Hello ${user.name},
    Welcome to ${site.name}. 

내가 가진 개체는 "user""site"입니다. 내부 ${}에 주어진 문자열을 객체의 동등한 값 으로 바꾸고 싶습니다 . 이것은 속도 템플릿에서 객체를 교체하는 것과 같습니다.



답변

StringSubstitutorApache Commons Text에서 사용합니다 .

https://commons.apache.org/proper/commons-text/

그것은 당신을 위해 할 것입니다 (그리고 오픈 소스 …)

 Map<String, String> valuesMap = new HashMap<String, String>();
 valuesMap.put("animal", "quick brown fox");
 valuesMap.put("target", "lazy dog");
 String templateString = "The ${animal} jumped over the ${target}.";
 StringSubstitutor sub = new StringSubstitutor(valuesMap);
 String resolvedString = sub.replace(templateString);


답변

java.text.MessageFormat클래스를 살펴보면 MessageFormat은 개체 집합을 가져 와서 형식을 지정한 다음 형식이 지정된 문자열을 적절한 위치의 패턴에 삽입합니다.

Object[] params = new Object[]{"hello", "!"};
String msg = MessageFormat.format("{0} world {1}", params);


답변

내가 선호하는 방법은 String.format() oneliner이고 타사 라이브러리가 필요하지 않기 때문입니다.

String message = String.format("Hello! My name is %s, I'm %s.", name, age); 

예를 들어 다음과 같은 예외 메시지에서 정기적으로 사용합니다.

throw new Exception(String.format("Unable to login with email: %s", email));

힌트 : Varargs를format() 사용 하기 때문에 원하는만큼 변수를 입력 할 수 있습니다.


답변

나는 이것의 작은 테스트 구현을 함께 던졌다. 기본 아이디어는format 형식 문자열, 객체 맵 및 로컬에있는 이름 하고 전달하는 것입니다.

다음의 출력은 다음과 같습니다.

내 개 이름은 fido이고 Jane Doe는 그를 소유합니다.

public class StringFormatter {

    private static final String fieldStart = "\\$\\{";
    private static final String fieldEnd = "\\}";

    private static final String regex = fieldStart + "([^}]+)" + fieldEnd;
    private static final Pattern pattern = Pattern.compile(regex);

    public static String format(String format, Map<String, Object> objects) {
        Matcher m = pattern.matcher(format);
        String result = format;
        while (m.find()) {
            String[] found = m.group(1).split("\\.");
            Object o = objects.get(found[0]);
            Field f = o.getClass().getField(found[1]);
            String newVal = f.get(o).toString();
            result = result.replaceFirst(regex, newVal);
        }
        return result;
    }

    static class Dog {
        public String name;
        public String owner;
        public String gender;
    }

    public static void main(String[] args) {
        Dog d = new Dog();
        d.name = "fido";
        d.owner = "Jane Doe";
        d.gender = "him";
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("d", d);
        System.out.println(
           StringFormatter.format(
                "My dog is named ${d.name}, and ${d.owner} owns ${d.gender}.",
                map));
    }
}

참고 : 처리되지 않은 예외로 인해 컴파일되지 않습니다. 그러나 코드를 훨씬 쉽게 읽을 수 있습니다.

또한 코드에서 직접 맵을 구성해야한다는 점이 마음에 들지 않지만 프로그래밍 방식으로 지역 변수의 이름을 얻는 방법을 모릅니다. 이를 수행하는 가장 좋은 방법은 객체를 생성하자마자지도에 객체를 배치하는 것입니다.

다음 예제는 예제에서 원하는 결과를 생성합니다.

public static void main(String[] args) {
    Map<String, Object> map = new HashMap<String, Object>();
    Site site = new Site();
    map.put("site", site);
    site.name = "StackOverflow.com";
    User user = new User();
    map.put("user", user);
    user.name = "jjnguy";
    System.out.println(
         format("Hello ${user.name},\n\tWelcome to ${site.name}. ", map));
}

나는 또한 Velocity가 무엇인지 모른다는 것을 언급해야 하므로이 답변이 관련이 있기를 바랍니다.


답변

이 작업을 수행하는 방법에 대한 개요가 있습니다. 실제 코드로 구현하는 것은 비교적 간단해야합니다.

  1. 템플릿에서 참조 할 모든 개체의 맵을 만듭니다.
  2. 정규식을 사용하여 템플릿에서 변수 참조를 찾고 해당 값으로 바꿉니다 (3 단계 참조). Matcher를 찾기 및 바꾸기 위해 클래스는 유용합니다.
  3. 점에서 변수 이름을 분할합니다. user.name될 것입니다 username. 조회 user객체를 얻고 사용하도록지도에서 반사 의 값을 얻을 name목적에서입니다. 객체에 표준 getter가 있다고 가정하면 메서드를 getName찾아 호출합니다.


답변

이 작업을 수행하는 몇 가지 Expression Language 구현이 있습니다. 자체 구현을 사용하거나 요구 사항이 증가하면 JUELMVEL을 참조하십시오.

적어도 하나의 프로젝트에서 MVEL을 좋아하고 성공적으로 사용했습니다.

또한 비 JSP (독립 실행 형) 컨텍스트 에서 Stackflow 게시물 JSTL / JSP EL (Expression Language)을 참조하십시오.


답변

속도는 그 문제를 정확히 해결하기 위해 작성 되었기 때문에 속도에 필적하는 즉시 사용할 수있는 것은 없습니다. 시도 할 수있는 가장 가까운 방법은 Formatter를 살펴 보는 것입니다.

http://cupi2.uniandes.edu.co/site/images/recursos/javadoc/j2se/1.5.0/docs/api/java/util/Formatter.html

그러나 내가 아는 한 포맷터는 Java에서 포맷 옵션과 같은 C를 제공하기 위해 만들어 졌으므로 가려움증을 정확히 긁지 않을 수 있지만 시도해 볼 수 있습니다 :).