开发者

Is there a general string substitution function similar to sl4fj?

With sl4fj if I want to construct a string message there is a nice approach which makes use of substitutions. For instance, it might be something like:

logger.info("Action {} occured on object {}.", objectA.getAction(), objectB);

If there are more than a few substitutions required then it is something like:

logger.info("Action {} occured on object {} with outcome {}.", 
    new Object[]{objectA.getAction(), objectB, outcome});

My question is: Is there a generic way for me to create a string (and not just a slf4j log message)? Something like:

String str = someMethod("Action {} occured on object {}.", objectA.getAction(), objectB);

or

String str = someMethod("Action {} occured开发者_运维知识库 on object {} with outcome {}.", 
    new Object[]{objectA.getAction(), objectB, outcome});

If it is in the standard Java library, what would that "someMethod" be?


String.format

String str = String.format("Action %s occured on object %s.",
   objectA.getAction(), objectB);

Or

String str = String.format("Action %s occured on object %s with outcome %s.",
   new Object[]{objectA.getAction(), objectB, outcome});

You can also use numeric positions, for example to switch the parameters around:

String str = String.format("Action %2$s occured on object %1$s.",
   objectA.getAction(), objectB);


You can use String.format or MessageFormat.format

E.g.,

MessageFormat.format("A sample value {1} with a sample string {0}", 
    new Object[] {"first", 1});

or simply

MessageFormat.format("A sample value {1} with a sample string {0}", "first", 1);


If you are looking for a solution where you can replace a bunch of variables in a String with values, you can use 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);

It follows a generally accepted pattern where one can pass a map with variables to values along with the unresolved String and it returns a resolved String.


I would suggest to use org.slf4j.helpers.MessageFormatter. With the help of it one can create a utillity method that uses the exact same formatting style as 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); 
}

Note: If the last object in the array is an Exception it will not be substituted in the message, just like with an slf4j logger. The Exception would be accessible via MessageFormatter.arrayFormat(msg, objs).getThrowable().


I choose wrap the Log4j2 ParameterizedMessage which was originally written for Lilith by Joern Huxhorn:

public static String format(final String messagePattern, Object... arguments) {
    return ParameterizedMessage.format(messagePattern, arguments);
}

It is focus on message format, unlike SLF4J MessageFormatter which contains unnecessary processing of Throwable.

See the Javadoc:

Handles messages that consist of a format string containing '{}' to represent each replaceable token, and the parameters.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜