W sl4fj, jeśli chcę skonstruować wiadomość tekstową, jest fajne podejście, które wykorzystuje podstawienia. Na przykład może to być coś takiego:
logger.info("Action {} occured on object {}.", objectA.getAction(), objectB);
Jeśli wymaganych jest więcej niż kilka podstawień, to wygląda to tak:
logger.info("Action {} occured on object {} with outcome {}.",
new Object[]{objectA.getAction(), objectB, outcome});
Moje pytanie brzmi: czy istnieje ogólny sposób na utworzenie ciągu znaków (a nie tylko komunikat dziennika slf4j)? Coś jak:
String str = someMethod("Action {} occured on object {}.", objectA.getAction(), objectB);
lub
String str = someMethod("Action {} occured on object {} with outcome {}.",
new Object[]{objectA.getAction(), objectB, outcome});
Jeśli znajduje się w standardowej bibliotece Java, czym byłaby ta „someMethod”?
Odpowiedzi:
String.format
String str = String.format("Action %s occured on object %s.", objectA.getAction(), objectB);
Lub
String str = String.format("Action %s occured on object %s with outcome %s.", new Object[]{objectA.getAction(), objectB, outcome});
Możesz także użyć pozycji numerycznych, na przykład do przełączania parametrów między:
String str = String.format("Action %2$s occured on object %1$s.", objectA.getAction(), objectB);
źródło
Możesz użyć String.format lub MessageFormat.format
Na przykład,
MessageFormat.format("A sample value {1} with a sample string {0}", new Object[] {"first", 1});
lub po prostu
MessageFormat.format("A sample value {1} with a sample string {0}", "first", 1);
źródło
Jeśli szukasz rozwiązania, w którym możesz zastąpić kilka zmiennych w łańcuchu wartościami, możesz użyć StrSubstitutor .
Map<String, String> valuesMap = new HashMap<>(); valuesMap.put("animal", "quick brown fox"); valuesMap.put("target", "lazy dog"); String templateString = "The ${animal} jumped over the ${target}."; StrSubstitutor sub = new StrSubstitutor(valuesMap); String resolvedString = sub.replace(templateString);
Jest zgodny z ogólnie przyjętym wzorcem, w którym można przekazać mapę ze zmiennymi do wartości wraz z nierozpoznanym ciągiem i zwraca rozwiązany ciąg.
źródło
Sugerowałbym użycie org.slf4j.helpers.MessageFormatter . Z jego pomocą można stworzyć metodę użyteczności, która używa dokładnie tego samego stylu formatowania, co slf4j:
// utillity method to format like slf4j public static String format(String msg, Object... objs) { return MessageFormatter.arrayFormat(msg, objs).getMessage(); } // example usage public static void main(String[] args) { String msg = format("This msg is {} like slf{}j would do. {}", "formatted", 4, new Exception("Not substituted into the message")); // prints "This msg is formatted like slf4j would do. {}" System.out.println(msg); }
Uwaga : Jeśli ostatni obiekt w tablicy jest wyjątkiem, nie zostanie on zastąpiony w komunikacie, tak jak w przypadku rejestratora slf4j. Wyjątek byłby dostępny za pośrednictwem
MessageFormatter.arrayFormat(msg, objs).getThrowable()
.źródło
Wybieram zawinięcie Log4j2 ParameterizedMessage, który został pierwotnie napisany dla Lilith przez Joern Huxhorn:
public static String format(final String messagePattern, Object... arguments) { return ParameterizedMessage.format(messagePattern, arguments); }
Koncentruje się na formacie wiadomości, w przeciwieństwie do SLF4J MessageFormatter, który zawiera niepotrzebne przetwarzanie Throwable.
Zobacz Javadoc:
źródło