Logger is quite simple, and there are not many things. The most important thing is a Logger interface:
[Java]
Public interface Logger {
Public static final int FATAL = Integer. MIN_VALUE;
Public static final int ERROR = 1;
Public static final int WARNING = 2;
Public static final int INFORMATION = 3;
Public static final int DEBUG = 4;
Public Container getContainer ();
Public void setContainer (Container container );
Public String getInfo ();
Public int getVerbosity ();
Public void setVerbosity (int verbosity );
Public void addPropertyChangeListener (PropertyChangeListener listener );
Public void log (String message );
Public void log (Exception exception, String msg );
Public void log (String message, Throwable throwable );
Public void log (String message, int verbosity );
Public void log (String message, Throwable throwable, int verbosity );
Public void removePropertyChangeListener (PropertyChangeListener listener );
}
Logger can have its own Logger. The setContainer is used to associate the Logger with a specific container. The setVerbosity is used to set the log Level and the log is a specific log record function. FATAL, ERROR, WARNING, INFORMATION, and DEBUG indicate the five levels of log records. Here we will mainly explain the FileLogger class. This is one of Tomcat's logger, which records logs in one file. The FileLogger startup method and shutdown are only for starting a lifecycle event, do not do other things:
[Java]
Public void start () throws LifecycleException {
// Validate and update our current component state
If (started)
Throw new LifecycleException
(Sm. getString ("fileLogger. alreadyStarted "));
Lifecycle. fireLifecycleEvent (START_EVENT, null); // triggers a lifecycle event
Started = true;
}
Here is a line of code sm. getString ("fileLogger. alreadyStarted"), which involves international issues. Let's talk about this issue later. Now let's look at the logger first. open a file using the FileLogger open method to record logs:
[Java]
Private void open (){
// Create the directory if necessary
File dir = new File (directory); // directory equals to logs, that is, creating a log File under the logs folder
If (! Dir. isAbsolute ())
Dir = new File (System. getProperty ("catalina. base"), directory );
Dir. mkdirs ();
// Open the current log file
Try {
String pathname = dir. getAbsolutePath () + File. separator +
Prefix + date + suffix;
Writer = new PrintWriter (new FileWriter (pathname, true), true );
} Catch (IOException e ){
Writer = null;
}
}
Here we get a PrintWriter output stream writer, which will be used when the log method logs. The following describes the log method:
[Java]
Public void log (String msg ){
// Construct the timestamp we will use, if requested
Timestamp ts = new Timestamp (System. currentTimeMillis ());
String tsString = ts. toString (). substring (0, 19 );
String tsDate = tsString. substring (0, 10 );
// If the date has changed, switch log files
If (! Date. equals (tsDate) {// if the date changes, a new log file is created.
Synchronized (this ){
If (! Date. equals (tsDate )){
Close ();
Date = tsDate;
Open ();
}
}
}
// Log this message, timestamped if necessary
If (writer! = Null ){
If (timestamp ){
Writer. println (tsString + "" + msg); // enter the write time and log information in the log file.
} Else {
Writer. println (msg );
}
}
}
Writer. println writes time and log information into the log file. Of course, this Logger is generally used by Tomcat itself. We can also implement the Logger interface, and then rewrite its open method (open our own log file) and log methods (used to record log information in our own log files ).
Now let's take a look at the code sm. getString ("fileLogger. alreadyStarted "). Before understanding this code, Let's first look at a jdk class ResourceBundle, which provides international convenience. This class reads the. properties file, but obtains the language information of the current system based on the file name, and then reads the attribute value of the corresponding file. Of course, you must first have different attribute files in different countries to internationalize Tomcat. Each Tomcat package has several different attribute files. The org. apache. catalina. logger package has the following three attribute files:
[Java] www.2cto.com
LocalStrings_es.properties
LocalStrings_ja.properties
LocalStrings. properties
Attribute files in three languages. The LocalStrings. properties property file is the default property file. Check the content in the LocalStrings. properties attribute:
[Java]
FileLogger. alreadyStarted = File Logger has already been started
FileLogger. notStarted = File Logger has not yet been started
TomcatLogger. alreadyStarted = Tomcat Logger has already been started
TomcatLogger. notStarted = Tomcat Logger has not yet been started
The ResourceBundle class is obtained through the getBundle method. The parameter is the prefix of the package name of the attribute file. The above is the package name plus LocalStrings. Use the getString (String key) method to obtain parameters in the property file:
Now let's take a look at the code sm. getString ("fileLogger. alreadyStarted"). sm is an instance of StringManager and has been initialized in FileLogger:
[Java]
Private StringManager sm = StringManager. getManager (Constants. Package );
Constants. Package to get the Package name. The getManager method code is as follows:
[Java]
Public synchronized static StringManager getManager (String packageName ){
StringManager mgr = (StringManager) managers. get (packageName );
If (mgr = null ){
Mgr = new StringManager (packageName); // create a StringManager
Managers. put (packageName, mgr );
}
Return mgr;
}
The code is easy to understand. If a StringManager instance already exists, it will be taken directly from managers (this is a Hashtable). If no StringManager instance exists, a new one will be created. The StringManager construction method is as follows:
[Java]
Private StringManager (String packageName ){
String bundleName = packageName + ". LocalStrings ";
Bundle = ResourceBundle. getBundle (bundleName );
}
We can see the familiar ResourceBundle class. According to the above explanation, ResourceBundle. getBundle (bundleName) can get the default attribute file, that is, the LocalStrings. properties File above. Return to sm. getString ("fileLogger. alreadyStarted") and check the getString method of sm:
[Java]
Public String getString (String key ){
If (key = null ){
String msg = "key is null ";
Throw new NullPointerException (msg );
}
String str = null;
Try {
Str = bundle. getString (key );
} Catch (MissingResourceException mre ){
Str = "Cannot find message associated with key'" + key + "'";
}
Return str;
}
The focus is budle. getString (key). This code can get the value of the key attribute of the LocalStrings. properties File (fileLogger. alreadyStarted here), that is, File Logger has already been started. In this way, we can define multiple attribute files, one for English, one for Chinese, and one for a language, so that the application can be internationalized.
Author: haitao111313