SLF4J - Hướng dẫn nhanh

SLF4J là viết tắt của Ssự thúc giục Lkhai thác Facade cho Java. Nó cung cấp một bản tóm tắt đơn giản của tất cả các khung ghi nhật ký trong Java. Do đó, nó cho phép người dùng làm việc với bất kỳ khung ghi nhật ký nào như Log4j, Logback vàJUL(java.util.logging) sử dụng phụ thuộc duy nhất. Bạn có thể chuyển sang khung ghi nhật ký được yêu cầu tại thời gian chạy / thời gian triển khai.

Ceki Gülcü đã tạo ra SLF4J như một giải pháp thay thế cho khung ghi nhật ký chung của Jakarta.

Ưu điểm của SLF4J

Sau đây là những ưu điểm của SLF4J -

  • Sử dụng khung SLF4J, bạn có thể chuyển sang khung ghi nhật ký mong muốn tại thời điểm triển khai.

  • Slf4J cung cấp các ràng buộc với tất cả các khung ghi nhật ký phổ biến như log4j, JUL, Ghi nhật ký đơn giản và NOP. Do đó, bạn có thể chuyển sang bất kỳ khung phổ biến nào tại thời điểm triển khai.

  • SLF4J cung cấp hỗ trợ cho các thông báo ghi nhật ký được tham số hóa bất kể ràng buộc mà bạn sử dụng.

  • Vì SLF4J tách ứng dụng và khuôn khổ ghi nhật ký, bạn có thể dễ dàng viết các ứng dụng độc lập với khuôn khổ ghi nhật ký. Bạn không cần bận tâm về khung ghi nhật ký được sử dụng để viết ứng dụng.

  • SLF4J cung cấp một công cụ Java đơn giản được gọi là bộ di chuyển. Sử dụng công cụ này, bạn có thể di chuyển các dự án hiện có, sử dụng khung ghi nhật ký hoạt động như Jakarta Commons Logging (JCL) hoặc, log4j hoặc Java.util.logging (JUL) sang SLF4J.

Đăng nhập trong lập trình, đề cập đến việc ghi lại các hoạt động / sự kiện. Thông thường, các nhà phát triển ứng dụng nên quan tâm đến việc ghi nhật ký.

Để làm cho công việc ghi nhật ký dễ dàng hơn, Java cung cấp nhiều khung công tác khác nhau - log4J, java.util.logging (JUL), nhật ký nhỏ, logback, v.v.

Tổng quan về khung ghi nhật ký

Khung ghi nhật ký thường chứa ba yếu tố:

Tiều phu

Chụp thư cùng với siêu dữ liệu.

Định dạng

Định dạng các thông báo được ghi lại bởi trình ghi.

Người xử lý

Người xử lý hoặc người gửi cuối cùng gửi thư bằng cách in trên bảng điều khiển hoặc, bằng cách lưu trữ trong cơ sở dữ liệu hoặc bằng cách gửi qua email.

Một số khung công tác kết hợp các phần tử trình ghi nhật ký và phần tử appender để tăng tốc hoạt động.

Đối tượng Logger

Để ghi nhật ký một tin nhắn, ứng dụng sẽ gửi một đối tượng ghi nhật ký (đôi khi cùng với các ngoại lệ nếu có) với tên và mức độ bảo mật.

Mức độ nghiêm trọng

Các tin nhắn được ghi sẽ ở nhiều cấp độ khác nhau. Bảng sau liệt kê các cấp độ ghi nhật ký chung.

Sr.No Mức độ nghiêm trọng & Mô tả
1

Fatal

Sự cố nghiêm trọng khiến ứng dụng chấm dứt.

2

ERROR

Lỗi thời gian chạy.

3

WARNING

Trong hầu hết các trường hợp, lỗi là do việc sử dụng các API không dùng nữa.

4

INFO

Các sự kiện xảy ra trong thời gian chạy.

5

DEBUG

Thông tin về luồng của hệ thống.

6

TRACE

Thông tin chi tiết hơn về luồng của hệ thống.

Log4j là gì?

log4j là một công cụ đáng tin cậy, nhanh chóng và linh hoạt logging framework (APIs) written in Java, được phân phối theo Giấy phép Phần mềm Apache.

log4j có thể cấu hình cao thông qua các tệp cấu hình bên ngoài trong thời gian chạy. Nó xem quá trình ghi nhật ký theo mức độ ưu tiên và cung cấp các cơ chế để hướng thông tin ghi nhật ký đến nhiều điểm đến khác nhau, chẳng hạn như cơ sở dữ liệu, tệp, bảng điều khiển, UNIX Syslog, v.v. (để biết thêm chi tiết về log4j, hãy tham khảo Hướng dẫn của chúng tôi ).

So sánh SLF4J và Log4j

Không giống như log4j, SLF4J (Ssự thúc giục Lkhai thác Facade cho Java) không phải là một triển khai của khung ghi nhật ký, nó là một abstraction for all those logging frameworks in Java similar to log4J. Do đó, bạn không thể so sánh cả hai. Tuy nhiên, luôn khó để thích một trong hai.

Nếu bạn có quyền lựa chọn, việc ghi nhật ký trừu tượng luôn được ưu tiên hơn là khuôn khổ ghi nhật ký. Nếu bạn sử dụng tóm tắt ghi nhật ký, đặc biệt là SLF4J, bạn có thể di chuyển sang bất kỳ khuôn khổ ghi nhật ký nào mà bạn cần tại thời điểm triển khai mà không chọn phụ thuộc duy nhất.

Quan sát sơ đồ sau để hiểu rõ hơn.

Trong chương này, chúng tôi sẽ giải thích cách thiết lập môi trường SLF4J trong Eclipse IDE. Trước khi tiến hành cài đặt, hãy đảm bảo rằng bạn đã cài đặt Eclipse trong hệ thống của mình. Nếu không, hãy tải xuống và cài đặt Eclipse.

Để biết thêm thông tin về Eclipse, vui lòng tham khảo Hướng dẫn về Eclipse của chúng tôi

Bước 1: Tải xuống tệp JAR phụ thuộc

Mở trang chủ chính thức của trang web SLF4J và chuyển đến trang tải xuống.

Bây giờ, hãy tải xuống phiên bản ổn định mới nhất của slf4j-X.X.tar.gzhoặc slf4j-XXzip , theo hệ điều hành của bạn (nếu tệp windows .zip hoặc nếu tệp tar.gz Linux).

Trong thư mục đã tải xuống, bạn sẽ tìm thấy slf4j-api-XXjar . Đây là tệp Jar bắt buộc.

Bước 2: Tạo dự án và thiết lập đường dẫn xây dựng

Mở nhật thực và tạo một dự án mẫu. Nhấp chuột phải vào dự án, chọn tùy chọnBuild Path → Configure Build Path… như hình bên dưới.

bên trong Java Build Path khung trong Libraries tab, nhấp vào Add External JARs…

Chọn slf4j-api.x.x.jar tệp đã tải xuống và nhấp vào Apply and Close.

SLF4J Ràng buộc

Ngoài slf4j-api.x.x.jar tập tin, SLF4Jcung cấp một số tệp Jar khác như được hiển thị bên dưới. Chúng được gọi làSLF4J bindings.

Nơi mỗi ràng buộc dành cho khung ghi nhật ký tương ứng của nó.

Bảng sau liệt kê các ràng buộc SLF4J và các khuôn khổ tương ứng của chúng.

Sr.No Tệp Jar & Khung ghi nhật ký
1

slf4j-nop-x.x.jar

Không hoạt động, loại bỏ tất cả các bản ghi.

2

slf4j-simple-x.x.jar

Thực hiện đơn giản trong đó các tin nhắn cho thông tin và cao hơn được in và giữ lại tất cả các kết quả đầu ra cho System.err.

3

slf4j-jcl-x.x.jar

Khung ghi nhật ký của Jakarta Commons.

4

slf4j-jdk14-x.x.jar

Khung công tác Java.util.logging (JUL).

5

slf4j-log4j12-x.x.jar

Khung Log4J hoạt động. Ngoài ra, bạn cần phải cólog4j.jar.

Để làm cho SLF4J hoạt động cùng với slf4l-api-xxjar, bạn cần thêm tệp Jar tương ứng (ràng buộc) của khung ghi nhật ký mong muốn trong classpath của dự án (đặt đường dẫn xây dựng).

Để chuyển từ khuôn khổ này sang khuôn khổ khác, bạn cần thay thế ràng buộc tương ứng. Nếu không tìm thấy giới hạn, nó sẽ mặc định ở chế độ không hoạt động.

Pom.xml dành cho SLF4J

Nếu bạn đang tạo dự án maven, hãy mở pom.xml và dán nội dung sau vào đó và làm mới dự án.

<project xmlns = "http://maven.apache.org/POM/4.0.0"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0
   http://maven.apache.org/xsd/maven-4.0.0.xsd">
   
   <modelVersion>4.0.0</modelVersion>
   <groupId>Sample</groupId>
   <artifactId>Sample</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <build>
      <sourceDirectory>src</sourceDirectory>
      <plugins>
         <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.7.0</version>
            <configuration>
               <source>1.8</source>
               <target>1.8</target>
            </configuration>
         </plugin>
      </plugins>
   </build>
   <dependencies>
      <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-api</artifactId>
         <version>1.7.25</version>
      </dependency>
   </dependencies>
</project>

Trong chương này, chúng ta sẽ thảo luận về các lớp và phương thức mà chúng ta sẽ sử dụng trong các chương tiếp theo của hướng dẫn này.

Giao diện ghi nhật ký

Giao diện ghi nhật ký của org.slf4jgói là điểm nhập của API SLF4J. Sau đây liệt kê các phương pháp quan trọng của giao diện này.

Sr.No. Phương pháp và Mô tả
1

void debug(String msg)

Phương thức này ghi lại một thông báo ở cấp GỠ GỠ.

2

void error(String msg)

Phương pháp này ghi lại một thông báo ở mức LỖI.

3

void info(String msg)

Phương pháp này ghi lại một tin nhắn ở cấp độ INFO.

4

void trace(String msg)

Phương thức này ghi lại một thông báo ở mức TRACE.

5

void warn(String msg)

Phương pháp này ghi lại một thông báo ở cấp độ WARN.

Lớp LoggerFactory

Lớp LoggerFactory của org.slf4j package là một lớp tiện ích, được sử dụng để tạo các trình ghi nhật ký cho các API ghi nhật ký khác nhau như log4j, JUL, NOP và trình ghi nhật ký đơn giản.

Sr.No. Phương pháp và Mô tả
1

Logger getLogger(String name)

Phương thức này chấp nhận một giá trị chuỗi đại diện cho một tên và trả về Logger đối tượng với tên được chỉ định.

Lớp hồ sơ

Lớp này thuộc về gói org.slf4jđiều này được sử dụng cho mục đích hồ sơ và nó được gọi là hồ sơ người nghèo. Bằng cách sử dụng này, lập trình viên có thể tìm ra thời gian cần thiết để thực hiện các tác vụ kéo dài.

Sau đây là các phương thức quan trọng của lớp này.

Sr.No. Phương pháp và Mô tả
1

void start(String name)

Phương pháp này sẽ bắt đầu một đồng hồ bấm giờ con mới (được đặt tên) và dừng các đồng hồ bấm giờ con trước đó (hoặc, công cụ thời gian).

2

TimeInstrument stop()

Phương pháp này sẽ dừng đồng hồ bấm giờ con gần đây và đồng hồ bấm giờ chung và trả về Công cụ thời gian hiện tại.

3

void setLogger(Logger logger)

Phương thức này chấp nhận một đối tượng Logger và liên kết trình ghi được chỉ định với Profiler hiện tại.

4

void log()

Ghi lại nội dung của công cụ thời gian hiện tại được liên kết với trình ghi nhật ký.

5

void print()

In nội dung của công cụ thời gian hiện tại.

Trong chương này, chúng ta sẽ thấy một chương trình ghi nhật ký cơ bản đơn giản sử dụng SLF4J. Làm theo các bước được mô tả dưới đây để viết một trình ghi nhật ký đơn giản.

Bước 1 - Tạo một đối tượng của giao diện slf4j.Logger

Kể từ khi slf4j.Logger là điểm vào của API SLF4J, trước tiên, bạn cần lấy / tạo đối tượng của nó

Các getLogger() phương pháp của LoggerFactory lớp chấp nhận một giá trị chuỗi đại diện cho một tên và trả về Logger đối tượng với tên được chỉ định.

Logger logger = LoggerFactory.getLogger("SampleLogger");

Bước 2 - Ghi lại tin nhắn cần thiết

Các info() phương pháp của slf4j.Logger giao diện chấp nhận một giá trị chuỗi đại diện cho thông báo được yêu cầu và ghi lại nó ở cấp thông tin.

logger.info("Hi This is my first SLF4J program");

Thí dụ

Sau đây là chương trình trình bày cách viết một trình ghi mẫu trong Java bằng SLF4J.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SLF4JExample {
   public static void main(String[] args) {
      //Creating the Logger object
      Logger logger = LoggerFactory.getLogger("SampleLogger");

      //Logging the information
      logger.info("Hi This is my first SLF4J program");
   }
}

Đầu ra

Khi chạy chương trình sau ban đầu, bạn sẽ nhận được kết quả sau thay vì thông báo mong muốn.

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further
details.

Vì chúng tôi chưa đặt classpath thành bất kỳ ràng buộc nào đại diện cho khung ghi nhật ký, như đã đề cập trước đó trong hướng dẫn này, SLF4J được mặc định là triển khai không hoạt động. Vì vậy, để xem thông báo, bạn cần thêm ràng buộc mong muốn trong classpath của dự án. Vì chúng tôi đang sử dụng nhật thực, hãy đặtbuild path cho tệp JAR tương ứng hoặc, thêm phần phụ thuộc của nó vào tệp pom.xml.

Ví dụ: nếu chúng ta cần sử dụng JUL (Java.util.logging framework), chúng ta cần đặt đường dẫn xây dựng cho tệp jar slf4j-jdk14-x.x.jar. Và nếu chúng ta muốn sử dụng khung ghi nhật ký log4J, chúng ta cần thiết lập đường dẫn xây dựng hoặc thêm các phần phụ thuộc cho các tệp jarslf4j-log4j12-x.x.jarlog4j.jar.

Sau khi thêm liên kết đại diện cho bất kỳ khung ghi nhật ký nào ngoại trừ slf4j-nopx.x.jar vào dự án (classpath), bạn sẽ nhận được kết quả sau.

Dec 06, 2018 5:29:44 PM SLF4JExample main
INFO: Hi Welcome to Tutorialspoint

Trong chương này, chúng tôi sẽ thảo luận về các thông báo lỗi hoặc cảnh báo khác nhau mà chúng tôi nhận được khi làm việc với SLF4J và nguyên nhân / ý nghĩa của các thông báo đó.

Không tải được lớp "org.slf4j.impl.StaticLoggerBinder".

Đây là một cảnh báo được gây ra khi không có liên kết SLF4J nào được cung cấp trong classpath.

Sau đây là cảnh báo đầy đủ -

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further
details.

Để giải quyết vấn đề này, bạn cần thêm một trong các ràng buộc của khung ghi nhật ký. Điều này được giải thích trongHello world chương của hướng dẫn này.

Note - Điều này xảy ra trong các phiên bản SLF4J từ 1.6.0 đến 1.8.0-beta2.

Không tìm thấy nhà cung cấp SLF4J nào

Trong slf4j-1.8.0-beta2, cảnh báo trên nói rõ hơn “No SLF4J providers were found”.

Sau đây là cảnh báo đầy đủ -

SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#noProviders for further details.

Classpath chứa các liên kết SLF4J nhắm mục tiêu các phiên bản slf4j-api trước 1.8

Nếu bạn đang sử dụng phiên bản SLF4J 1.8 và bạn có các ràng buộc của các phiên bản trước trong classpath nhưng không có các ràng buộc của 1.8, bạn sẽ thấy một cảnh báo như hình dưới đây.

SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#noProviders for further details.
SLF4J: Class path contains SLF4J bindings targeting slf4j-api versions prior to
1.8.
SLF4J: Ignoring binding found at
[jar:file:/C:/Users/Tutorialspoint/Desktop/Latest%20Tutorials/SLF4J%20Tutorial/
slf4j-1.7.25/slf4j-jdk14-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#ignoredBindings for an explanation.

NoClassDefFoundError: org / apache / commons / logging / LogFactory

Nếu bạn đang làm việc với slf4j-jcl và nếu bạn chỉ có slf4j-jcl.jar trong classpath của bạn, bạn sẽ nhận được một ngoại lệ chẳng hạn như một ngoại lệ được đưa ra bên dưới.

Exception in thread "main" java.lang.NoClassDefFoundError:
org/apache/commons/logging/LogFactory
   at org.slf4j.impl.JCLLoggerFactory.getLogger(JCLLoggerFactory.java:77)
   at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:358)
   at SLF4JExample.main(SLF4JExample.java:8)
Caused by: java.lang.ClassNotFoundException:
org.apache.commons.logging.LogFactory
   at java.net.URLClassLoader.findClass(Unknown Source)
   at java.lang.ClassLoader.loadClass(Unknown Source)
   at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
   at java.lang.ClassLoader.loadClass(Unknown Source)
   ... 3 more

Để giải quyết vấn đề này, bạn cần thêm commons-logging.jar vào classpath của bạn.

Đã phát hiện cả jcl-over-slf4j.jar VÀ liên kết slf4j-jcl.jar trên classpath ..

Các ràng buộc slf4j-jcl.jar chuyển hướng các lệnh gọi của trình ghi slf4j đến JCL và jcl-over-slf4j.jarchuyển hướng các cuộc gọi của trình ghi nhật ký JCL đến slf4j. Do đó, bạn không thể có cả hai trong classpath của dự án của mình. Nếu bạn làm như vậy, bạn sẽ nhận được một ngoại lệ chẳng hạn như trường hợp được đưa ra bên dưới.

SLF4J: Detected both jcl-over-slf4j.jar AND bound slf4j-jcl.jar on the class
path, preempting StackOverflowError.
SLF4J: See also http://www.slf4j.org/codes.html#jclDelegationLoop for more
details.
Exception in thread "main" java.lang.ExceptionInInitializerError
   at org.slf4j.impl.StaticLoggerBinder.<init>(StaticLoggerBinder.java:71)
   at org.slf4j.impl.StaticLoggerBinder.<clinit>(StaticLoggerBinder.java:42)
   at org.slf4j.LoggerFactory.bind(LoggerFactory.java:150)
   at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:124)
   at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:412)
   at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:357)
   at SLF4JExample.main(SLF4JExample.java:8)
Caused by: java.lang.IllegalStateException: Detected both jcl-over-slf4j.jar
AND bound slf4j-jcl.jar on the class path, preempting StackOverflowError. See
also http://www.slf4j.org/codes.html#jclDelegationLoop for more details.
   at org.slf4j.impl.JCLLoggerFactory.<clinit>(JCLLoggerFactory.java:54)
   ... 7 more

Để giải quyết vấn đề này, hãy xóa một trong các tệp jar.

Tên trình ghi nhật ký đã phát hiện không khớp

Bạn có thể tạo một đối tượng Logger bằng cách -

  • Chuyển tên của trình ghi nhật ký được tạo làm đối số cho getLogger() phương pháp.

  • Truyền một lớp làm đối số cho phương thức này.

Nếu bạn đang cố gắng tạo đối tượng nhà máy ghi nhật ký bằng cách chuyển một lớp làm đối số và nếu bạn đã đặt thuộc tính hệ thống slf4j.detectLoggerNameMismatch thành true, sau đó là tên của lớp bạn truyền làm đối số cho getLogger() và lớp bạn sử dụng phải giống nhau nếu không bạn sẽ nhận được cảnh báo sau:

“Tên trình ghi nhật ký đã phát hiện không khớp.

Hãy xem xét ví dụ sau.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SLF4JExample {
   public static void main(String[] args) {
      System.setProperty("slf4j.detectLoggerNameMismatch", "true");
      
      //Creating the Logger object
      Logger logger = LoggerFactory.getLogger(Sample.class);

      //Logging the information
      logger.info("Hi Welcome to Tutorilspoint");
   }
}

Ở đây, chúng tôi đã đặt thuộc tính slf4j.detectLoggerNameMismatch thành true. Tên của lớp chúng tôi đã sử dụng làSLF4JExample và tên lớp mà chúng ta đã chuyển cho phương thức getLogger () là Sample vì cả hai đều không bằng nhau, chúng tôi sẽ nhận được cảnh báo sau.

SLF4J: Detected logger name mismatch. Given name: "Sample"; computed name:
"SLF4JExample".
SLF4J: See http://www.slf4j.org/codes.html#loggerNameMismatch for an
explanation
Dec 10, 2018 12:43:00 PM SLF4JExample main
INFO: Hi Welcome to Tutorilspoint

Note - Điều này xảy ra sau slf4j 1.7.9

Classpath chứa nhiều liên kết SLF4J.

Bạn chỉ nên có một ràng buộc trong classpath. Nếu bạn có nhiều ràng buộc, bạn sẽ nhận được cảnh báo liệt kê các ràng buộc và vị trí của chúng.

Giả sử, nếu chúng ta có các ràng buộc slf4j-jdk14.jarslf4j-nop.jar trong classpath, chúng ta sẽ nhận được cảnh báo sau.

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in
[jar:file:/C:/Users/Tutorialspoint/Desktop/Latest%20Tutorials/SLF4J%20Tutorial/
slf4j-1.7.25/slf4j-nop-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in
[jar:file:/C:/Users/Tutorialspoint/Desktop/Latest%20Tutorials/SLF4J%20Tutorial/
slf4j-1.7.25/slf4j-jdk14-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an
explanation.
SLF4J: Actual binding is of type [org.slf4j.helpers.NOPLoggerFactory]

Đã phát hiện cả log4j-over-slf4j.jar VÀ liên kết slf4j-log4j12.jar trên đường dẫn lớp

Để chuyển hướng các cuộc gọi trình ghi log4j đến slf4j, bạn cần sử dụng log4j-over-slf4j.jar ràng buộc và nếu bạn muốn chuyển hướng cuộc gọi slf4j đến log4j, bạn cần sử dụng slf4j-log4j12.jar sự ràng buộc.

Do đó, bạn không thể có cả hai trong classpath. Nếu bạn làm vậy, bạn sẽ nhận được ngoại lệ sau.

SLF4J: Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the
class path, preempting StackOverflowError.
SLF4J: See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more
details.
Exception in thread "main" java.lang.ExceptionInInitializerError
   at org.slf4j.impl.StaticLoggerBinder.<init>(StaticLoggerBinder.java:72)
   at org.slf4j.impl.StaticLoggerBinder.<clinit>(StaticLoggerBinder.java:45)
   at org.slf4j.LoggerFactory.bind(LoggerFactory.java:150)
   at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:124)
   at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:412)
   at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:357)
   at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:383)
   at SLF4JExample.main(SLF4JExample.java:8)
Caused by: java.lang.IllegalStateException: Detected both log4j-over-slf4j.jar
AND bound slf4j-log4j12.jar on the class path, preempting StackOverflowError.
See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more details.

Như đã thảo luận trước đó trong hướng dẫn này, SLF4J cung cấp hỗ trợ cho các thông báo nhật ký được tham số hóa.

Bạn có thể sử dụng các tham số trong các thông báo và chuyển các giá trị cho chúng sau này trong cùng một câu lệnh.

Cú pháp

Như được hiển thị bên dưới, bạn cần sử dụng trình giữ chỗ ({}) trong thông báo (Chuỗi) bất cứ nơi nào bạn cần và sau này bạn có thể chuyển giá trị cho trình giữ chỗ vào object biểu mẫu, phân tách thông báo và giá trị bằng dấu phẩy.

Integer age;
Logger.info("At the age of {} ramu got his first job", age);

Thí dụ

Ví dụ sau minh họa ghi nhật ký được tham số hóa (với một tham số) bằng SLF4J.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PlaceHolders {
   public static void main(String[] args) {
      
      //Creating the Logger object
      Logger logger = LoggerFactory.getLogger(PlaceHolders.class);
      Integer age = 23;
      
      //Logging the information
      logger.info("At the age of {} ramu got his first job", age);
   }
}

Đầu ra

Khi thực hiện, chương trình trên tạo ra kết quả sau:

Dec 10, 2018 3:25:45 PM PlaceHolders main
INFO: At the age of 23 Ramu got his first job

Lợi thế của ghi nhật ký tham số

Trong Java, nếu chúng ta cần in các giá trị trong một câu lệnh, chúng ta sẽ sử dụng toán tử nối là:

System.out.println("At the age of "+23+" ramu got his first job");

Điều này liên quan đến việc chuyển đổi giá trị số nguyên 23 thành chuỗi và nối giá trị này với các chuỗi xung quanh nó.

Và nếu đó là một câu lệnh ghi nhật ký và nếu mức độ nhật ký cụ thể đó của câu lệnh của bạn bị vô hiệu hóa thì tất cả phép tính này sẽ không có ích gì.

Trong những trường hợp như vậy, bạn có thể sử dụng ghi nhật ký được tham số hóa. Ở định dạng này, ban đầu SLF4J xác nhận việc ghi nhật ký cho cấp cụ thể có được bật hay không. Nếu vậy thì nó sẽ thay thế các trình giữ chỗ trong các thông báo bằng các giá trị tương ứng.

Ví dụ: nếu chúng ta có một tuyên bố là

Integer age;
Logger.debug("At the age of {} ramu got his first job", age);

Chỉ khi gỡ lỗi được kích hoạt sau đó, SLF4J chuyển đổi tuổi thành số nguyên và nối nó với các chuỗi, nếu không thì nó không có tác dụng gì. Do đó, phát sinh chi phí xây dựng tham số khi cấp độ ghi nhật ký bị vô hiệu hóa.

Hai biến thể đối số

Bạn cũng có thể sử dụng hai tham số trong một tin nhắn là -

logger.info("Old weight is {}. new weight is {}.", oldWeight, newWeight);

Thí dụ

Ví dụ sau minh họa việc sử dụng hai trình giữ chỗ trong ghi nhật ký được tham số hóa.

import java.util.Scanner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class PlaceHolders {
   public static void main(String[] args) {
      Integer oldWeight;
      Integer newWeight;
      Scanner sc = new Scanner(System.in);
      System.out.println("Enter old weight:");
      oldWeight = sc.nextInt();

      System.out.println("Enter new weight:");
      newWeight = sc.nextInt();

      //Creating the Logger object
      Logger logger = LoggerFactory.getLogger(Sample.class);

      //Logging the information
      logger.info("Old weight is {}. new weight is {}.", oldWeight, newWeight);
 
      //Logging the information
      logger.info("After the program weight reduced is: "+(oldWeight-newWeight));
   }
}

Đầu ra

Khi thực hiện, chương trình trên tạo ra kết quả sau.

Enter old weight:
85
Enter new weight:
74
Dec 10, 2018 4:12:31 PM PlaceHolders main
INFO: Old weight is 85. new weight is 74.
Dec 10, 2018 4:12:31 PM PlaceHolders main
INFO: After the program weight reduced is: 11

Nhiều biến thể đối số

Bạn cũng có thể sử dụng nhiều hơn hai trình giữ chỗ như được hiển thị trong ví dụ sau:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PlaceHolders {
   public static void main(String[] args) {
      Integer age = 24;
      String designation = "Software Engineer";
      String company = "Infosys";

      //Creating the Logger object
      Logger logger = LoggerFactory.getLogger(Sample.class);

      //Logging the information
      logger.info("At the age of {} ramu got his first job as a {} at {}", age, designation, company);
   }
}

Đầu ra

Khi thực hiện, chương trình trên tạo ra kết quả sau:

Dec 10, 2018 4:23:52 PM PlaceHolders main
INFO: At the age of 24 ramu got his first job as a Software Engineer at Infosys

Nếu bạn có một dự án ở Jakarta Commons Logging (JCL) hoặc, log4j hoặc, java.util.logging (JUL) và bạn muốn chuyển đổi các dự án này sang SLF4J, bạn có thể làm như vậy bằng cách sử dụng công cụ di chuyển được cung cấp trong bản phân phối SLF4J.

Chạy SLF4J Migrator

SLF4J là một tệp jar đơn đơn giản (slf4j-migrator.jar) và bạn có thể chạy nó bằng lệnh java –jar.

Để chạy nó, trong dấu nhắc lệnh, hãy duyệt qua thư mục mà bạn có tệp jar này và thực hiện lệnh sau.

java -jar slf4j-migrator-1.8.0-beta2.jar
Starting SLF4J Migrator

Thao tác này khởi động trình di chuyển và bạn có thể thấy một ứng dụng java độc lập như sau:

Như được chỉ định trong cửa sổ, bạn cần kiểm tra loại di chuyển bạn muốn thực hiện và chọn thư mục dự án và nhấp vào nút Di chuyển dự án sang SLF4J.

Công cụ này chuyển đến các tệp nguồn mà bạn cung cấp và thực hiện các sửa đổi đơn giản như thay đổi các dòng nhập và khai báo trình ghi từ khung ghi nhật ký hiện tại sang SLF4j.

Thí dụ

Ví dụ: giả sử chúng tôi có một mẫu log4j(2) dự án trong nhật thực với một tệp duy nhất như sau:

import org.apache.log4j.Logger;
import java.io.*;
import java.sql.SQLException;
import java.util.*;

public class Sample {
   /* Get actual class name to be printed on */
   static Logger log = Logger.getLogger(Sample.class.getName());

   public static void main(String[] args)throws IOException,SQLException {
      log.debug("Hello this is a debug message");
      log.info("Hello this is an info message");
   }
}

Để di chuyển mẫu log4j(2) dự án lên slf4j, chúng ta cần kiểm tra nút radio from log4j to slf4j và chọn thư mục của dự án và nhấp vào Exit để di cư.

Trình di chuyển đã thay đổi mã trên như sau. Ở đây nếu bạn quan sát thấy các câu lệnh nhập và trình ghi nhật ký đã được sửa đổi.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.sql.SQLException;
import java.util.*;

public class Sample {
   static Logger log = LoggerFactory.getLogger(Sample.class.getName());
   public static void main(String[] args)throws IOException,SQLException {
      log.debug("Hello this is a debug message");
      log.info("Hello this is an info message");
   }
}

Vì bạn đã có log4j.jar trong dự án của bạn, bạn cần thêm slf4j-api.jarslf4jlog12.jar tệp vào dự án để thực thi nó.

Hạn chế của SLF4JMigrator

Sau đây là những hạn chế của bộ di chuyển SLF4J.

  • Migrator sẽ không sửa đổi các tập lệnh xây dựng như kiến, maven và cây thường xuân mà bạn cần phải tự làm.

  • Migrator không hỗ trợ các thông báo khác với loại Chuỗi.

  • Migrator không hỗ trợ mức FATAL.

  • Trong khi làm việc với log4j, bộ di chuyển sẽ không di chuyển các cuộc gọi đến PropertyConfigurator hoặc DomConfigurator.

SLF4J Phân phối cung cấp slf4j-ext.jar điều này chứa các API cho các chức năng như lập hồ sơ, ghi nhật ký mở rộng, ghi nhật ký sự kiện và ghi nhật ký bằng tác nhân java.

Hồ sơ

Đôi khi lập trình viên muốn đo lường một số thuộc tính như việc sử dụng bộ nhớ, độ phức tạp về thời gian hoặc sử dụng các lệnh cụ thể về chương trình để đo khả năng thực của chương trình đó. Kiểu đo lường như vậy về chương trình được gọi là lập hồ sơ. Hồ sơ sử dụng phân tích chương trình động để thực hiện việc đo lường như vậy.

SLF4J cung cấp một lớp có tên Profiler bên trong org.slf4j.profilergói cho mục đích hồ sơ. Đây được gọi là hồ sơ của người nghèo. Bằng cách sử dụng này, lập trình viên có thể tìm ra thời gian cần thiết để thực hiện các tác vụ kéo dài.

Lập hồ sơ bằng lớp Hồ sơ

Hồ sơ có chứa các đồng hồ bấm giờ và đồng hồ bấm giờ con và chúng ta có thể bắt đầu và dừng các đồng hồ này bằng cách sử dụng các phương thức được cung cấp bởi lớp hồ sơ.

Để tiếp tục việc lập hồ sơ bằng lớp hồ sơ, hãy làm theo các bước dưới đây.

Bước 1 - Khởi tạo lớp hồ sơ

Khởi tạo lớp Profiler bằng cách chuyển một giá trị String đại diện cho tên của profile. Khi chúng tôi khởi tạo lớp Hồ sơ, đồng hồ bấm giờ toàn cầu sẽ được bắt đầu.

//Creating a profiler
Profiler profiler = new Profiler("Sample");

Bước 2 - Khởi động đồng hồ bấm giờ trẻ em

Khi chúng tôi gọi start() phương pháp này sẽ bắt đầu một đồng hồ bấm giờ con mới (được đặt tên) và dừng các đồng hồ bấm giờ con trước đó (hoặc, công cụ thời gian).

Gọi start() phương pháp của Profiler bằng cách chuyển một giá trị Chuỗi đại diện cho tên của đồng hồ bấm giờ con sẽ được tạo.

//Starting a child stopwatch and stopping the previous one.
profiler.start("Task 1");
obj.demoMethod1();

Sau khi tạo các đồng hồ bấm giờ này, bạn có thể thực hiện các tác vụ của mình hoặc gọi các phương thức đó để chạy các tác vụ của bạn.

Bước 3: Bắt đầu một đồng hồ bấm giờ trẻ em khác (nếu bạn muốn)

Nếu bạn cần, hãy tạo một đồng hồ bấm giờ khác bằng cách sử dụng start()phương pháp và thực hiện các nhiệm vụ được yêu cầu. Nếu bạn làm như vậy, nó sẽ bắt đầu một đồng hồ dừng mới và dừng đồng hồ trước đó (tức là nhiệm vụ 1).

//Starting another child stopwatch and stopping the previous one.
profiler.start("Task 2");
obj.demoMethod2();

Bước 4: Dừng đồng hồ

Khi chúng tôi gọi stop() , nó sẽ dừng đồng hồ bấm giờ con gần đây và đồng hồ bấm giờ toàn cầu và trả về Công cụ thời gian hiện tại.

// Stopping the current child stopwatch and the global stopwatch.
TimeInstrument tm = profiler.stop();

Bước 5: In nội dung của công cụ thời gian.

In nội dung của công cụ thời gian hiện tại bằng cách sử dụng print() phương pháp.

//printing the contents of the time instrument
tm.print();

Thí dụ

Ví dụ sau minh họa cấu hình bằng cách sử dụng lớp Profiler của SLF4J. Ở đây chúng tôi đã thực hiện hai tác vụ mẫu, in tổng bình phương của các số từ 1 đến 10000, in tổng các số từ 1 đến 10000. Chúng tôi đang cố gắng lấy thời gian thực hiện cho hai tác vụ này.

import org.slf4j.profiler.Profiler;
import org.slf4j.profiler.TimeInstrument;

public class ProfilerExample {
   public void demoMethod1(){
      double sum = 0;
      for(int i=0; i< 1000; i++){
         sum = sum+(Math.pow(i, 2));
      }
      System.out.println("Sum of squares of the numbers from 1 to 10000: "+sum);
   }
   public void demoMethod2(){
      int sum = 0;
      for(int i=0; i< 10000; i++){
         sum = sum+i;
      }
      System.out.println("Sum of the numbers from 1 to 10000: "+sum);
   }
   public static void main(String[] args) {
      ProfilerExample obj = new ProfilerExample();

      //Creating a profiler
      Profiler profiler = new Profiler("Sample");

      //Starting a child stop watch and stopping the previous one.
      profiler.start("Task 1");
      obj.demoMethod1();

      //Starting another child stop watch and stopping the previous one.
      profiler.start("Task 2");
      obj.demoMethod2();
 
      //Stopping the current child watch and the global watch.
      TimeInstrument tm = profiler.stop();

      //printing the contents of the time instrument
      tm.print();
   }
}

Đầu ra

Khi thực hiện, chương trình trên tạo ra kết quả sau:

Sum of squares of the numbers from 1 to 10000: 3.328335E8
Sum of the numbers from 1 to 10000: 49995000
+ Profiler [BASIC]
|-- elapsed time [Task 1] 2291.827 microseconds.
|-- elapsed time [Task 2] 225.802 microseconds.
|-- Total [BASIC] 3221.598 microseconds.

Ghi lại thông tin hồ sơ

Thay vì in kết quả của một hồ sơ để ghi thông tin này, bạn cần phải -

  • Tạo một trình ghi nhật ký bằng cách sử dụng LoggerFactory lớp học.

  • Tạo một hồ sơ bằng cách khởi tạo lớp Hồ sơ.

  • Liên kết trình ghi nhật ký với trình biên dịch bằng cách chuyển đối tượng trình ghi nhật ký được tạo với setLogger() phương pháp của Profiler lớp học.

  • Cuối cùng, thay vì in nhật ký thông tin của trình biên dịch bằng cách sử dụng log() phương pháp.

Thí dụ

Trong ví dụ sau, không giống như ví dụ trước (thay vì in), chúng tôi đang cố gắng ghi lại nội dung của công cụ thời gian.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.profiler.Profiler;
import org.slf4j.profiler.TimeInstrument;

public class ProfilerExample_logger {
   public void demoMethod1(){
      double sum = 0;
      for(int i=0; i< 1000; i++){
         sum = sum+(Math.pow(i, 2));
      }
      System.out.println("Sum of squares of the numbers from 1 to 10000: "+sum);
   }
   public void demoMethod2(){
      int sum = 0;
      for(int i=0; i< 10000; i++){
         sum = sum+i;
      }
      System.out.println("Sum of the numbers from 1 to 10000: "+sum);
   }
   public static void main(String[] args) {
      ProfilerExample_logger obj = new ProfilerExample_logger();

      //Creating a logger
      Logger logger = LoggerFactory.getLogger(ProfilerExample_logger.class);

      //Creating a profiler
      Profiler profiler = new Profiler("Sample");

      //Adding logger to the profiler
      profiler.setLogger(logger);

      //Starting a child stop watch and stopping the previous one.
      profiler.start("Task 1");
      obj.demoMethod1();

      //Starting another child stop watch and stopping the previous one.
      profiler.start("Task 2");
      obj.demoMethod2();

      //Stopping the current child watch and the global watch.
      TimeInstrument tm = profiler.stop();

      //Logging the contents of the time instrument
      tm.log();
   }
}

Đầu ra

Khi thực hiện, chương trình trên tạo ra kết quả sau.

Sum of squares of the numbers from 1 to 10000: 3.328335E8
Sum of the numbers from 1 to 10000: 49995000