Có một hàm thay thế chuỗi chung tương tự như sl4fj không?


83

Với sl4fj, nếu tôi muốn xây dựng một thông báo chuỗi thì có một cách tiếp cận hay là sử dụng các thay thế. Ví dụ, nó có thể là một cái gì đó như:

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

Nếu có nhiều hơn một số thay thế được yêu cầu thì nó giống như:

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

Câu hỏi của tôi là: Có cách chung nào để tôi tạo một chuỗi (và không chỉ một thông báo nhật ký slf4j) không? Cái gì đó như:

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

hoặc là

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

Nếu nó nằm trong thư viện Java chuẩn, thì "someMethod" đó sẽ là gì?


1
Cảm ơn những người có câu trả lời dưới đây. Ngoài ra, tôi phát hiện ra câu hỏi này đã được hỏi ở đây: stackoverflow.com/questions/3114021 . Xin lỗi vì đã đăng một bản trùng lặp nhiều hơn hoặc ít hơn.
kmccoy

Câu trả lời:


110

String.format

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

Hoặc là

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

Bạn cũng có thể sử dụng các vị trí số, chẳng hạn như để chuyển đổi các tham số xung quanh:

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

44

Bạn có thể sử dụng String.format hoặc MessageFormat.format

Ví dụ,

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

hoặc đơn giản

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

1
MessageFormat rất linh hoạt và mạnh mẽ, nhưng để thay thế đơn giản, String.format có thể sẽ đơn giản hơn và ít bị hạn chế hơn (ví dụ: MessageFormat yêu cầu các dấu ngoặc kép phải được nhân đôi).
Kat

1
Số nguyên mới (1) được thay thế bằng chỉ 1 ở trên thì cũng sẽ hoạt động.
TechnoCrat

25

Nếu bạn đang tìm kiếm một giải pháp mà bạn có thể thay thế một loạt các biến trong Chuỗi bằng các giá trị, bạn có thể sử dụng 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);

Nó tuân theo một mẫu được chấp nhận chung, trong đó người ta có thể chuyển một bản đồ với các biến đến các giá trị cùng với Chuỗi chưa được giải quyết và nó trả về một Chuỗi đã phân giải.


20

Tôi sẽ đề nghị sử dụng org.slf4j.helpers.MessageFormatter . Với sự trợ giúp của nó, người ta có thể tạo một phương thức utillity sử dụng cùng một kiểu định dạng như 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); 
}

Lưu ý : Nếu đối tượng cuối cùng trong mảng là Ngoại lệ, nó sẽ không được thay thế trong thông báo, giống như với trình ghi slf4j. Có thể truy cập Exception thông qua MessageFormatter.arrayFormat(msg, objs).getThrowable().


3
Mặc dù vậy, tôi cho rằng đây không phải là một câu trả lời có mục đích chung tốt, nhưng thực sự khá đúng với những gì được hỏi.
Michael Piefel

3
Tôi thấy đây chính xác là câu trả lời đúng. Điều này sẽ là tốt nhất về mặt hiệu suất.
Sasa

1
Câu trả lời hay nhất vì nó sử dụng cú pháp chính xác mà câu hỏi yêu cầu.
Christoph

Thành thật mà nói, IMHO đây là câu trả lời duy nhất thực sự khớp với câu hỏi ban đầu ... đánh bại tôi tại sao nó lại xếp ở vị trí thứ tư ngay bây giờ ...
raner

0

Tôi chọn bọc Log4j2 ParameterizedMessage mà ban đầu được viết cho Lilith bởi Joern Huxhorn:

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

Nó tập trung vào định dạng tin nhắn, không giống như SLF4J MessageFormatter chứa xử lý Throwable không cần thiết.

Xem Javadoc:

Xử lý các thông báo bao gồm một chuỗi định dạng có chứa '{}' để đại diện cho từng mã thông báo có thể thay thế và các tham số.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.