📄 ch12.htm
字号:
<P>There are many third-party tools available to analyze server logfiles, provided they are in a "common log format":<BLOCKQUOTE><TT>hostname identd authuser [date] "request"status length</TT></BLOCKQUOTE><P>The first entry, <TT>hostname</TT>,is the name of the host this connection was received from. Ifthe name cannot be established, this field will display the numericIP address of the caller. The next two fields contain informationfor "login" and authorized user names. The HTTP serverdoes not support remote identification dialogs, so these fieldswill appear as a single dash (<TT>-</TT>).The date field has this format:<BLOCKQUOTE><TT>DD/MMM/YYY:HH:MM:SS GGGG</TT></BLOCKQUOTE><P>All these fields are evident except GGGG, which represents thenumber of time zones away from GMT.<P>The request field is the first line from the request header. <TT>status</TT>is the HTTP response code that was sent, typically 200, and <TT>length</TT>is the total number of file bytes sent in the response. Here isa sample log entry:<BLOCKQUOTE><TT>some.name.com - - [25/Mar/1996:08:48:23-0400] "GET / HTTP/1.0" 200 342</TT></BLOCKQUOTE><P>The 200 indicates that a response containing 342 bytes was sent.<H3><A NAME="BuildingLogInformation">Building Log Information</A></H3><P>HTTP requests are already stored in the HTTPrequest class, soit's reasonable to also store the log information in this class.If the server is ever made to work concurrently, the log informationwill have to travel with each request, so just add it there now:<BLOCKQUOTE><TT>/**<BR> * This class maintains all of the information from a HTTP request<BR> */<BR>public class HTTPrequest<BR>{<BR> ...<BR> public StringBuffer log;<BR><BR> /**<BR> * Create an instance of this class<BR> */<BR> public HTTPrequest()<BR> {<BR> ...<BR> log = null;<BR> }<BR> ...<BR>}</TT></BLOCKQUOTE><P>A StringBuffer is used because the string will grow and be altered.Java String objects are immutable-they can never be altered afterthey are created. If you use the plus operator to grow a String,you are actually creating a new String:<BLOCKQUOTE><TT>String first = new String("Thisis the first string.");<BR>first += " This is the second string";</TT></BLOCKQUOTE><P>The <TT>first</TT> variable now containsa completely different string, constructed from the first stringand the addition of the second string. The original contents ofthe variable are lost.<P>The log string will need some tweaking to bring it in line withthe common log format. That is why a StringBuffer class is used.<P>After a request is parsed, a new routine is added to HTTPrequestto format the initial portions of the log entry:<BLOCKQUOTE><TT>/**<BR> * Log a complete request.<BR> */<BR>public void logRequest()<BR>{<BR> Date current = new Date();<BR><BR> log = new StringBuffer("");<BR> if ( clientSocket == null )<BR> log.append("-");<BR> else<BR> log.append(clientSocket.getInetAddress().getHostName());<BR> log.append(" - - ");<BR> log.append(formatDate(current));<BR> log.append(" \"" + firstLine+ "\" ");<BR>}</TT></BLOCKQUOTE><H4>The Date Class</H4><P>The Date class is part of the java.util package. It provides fullsupport for both date and time. Six different constructors forthe class, shown in the following list, offer a great deal offlexibility in how a date is specified.<BR><P><CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%><TR VALIGN=TOP><TD WIDTH=505><I>Date Class Constructors</I></TD></TR><TR VALIGN=TOP><TD WIDTH=505><BLOCKQUOTE><TT>Date()<BR>Date(long totalSecs)<BR>Date(int yr, int mth, int day)<BR>Date(int yr, int mth, int day, int hrs, int min)<BR>Date(int yr, int mth, int day, int hrs, int min, int sec)<BR>Date(String s)</TT></BLOCKQUOTE></TD></TR></TABLE></CENTER><P><P>The first constructor, the most commonly used, constructs a Dateclass reflecting the current date and time. The other constructorsare used mainly to construct Date objects that are either forwardor backward in time. This could be done for comparison purposes:<BLOCKQUOTE><TT>Date c = new Date();<BR>Date p = new Date( c.getYear() - 1, c.getMonth(), c.getDate());<BR>Date n = new Date( c.getYear() + 1, c.getMonth(), c.getDate());<BR>if ( p.before( c ) )<BR> System.out.println("Date " +p + " is before Date " + c);<BR>if ( n.after( c ) )<BR> System.out.println("Date " +n + " is after Date " + c);</TT></BLOCKQUOTE><P>The Date class provides three useful comparison functions:<UL><LI><TT>boolean before(Date d)</TT><LI><TT>boolean after(Date d)</TT><LI><TT>boolean equals(Date d)</TT></UL><P>Several public methods get and manipulate Date class variables.Table 12.2 lists the remaining public methods of the Date class.<BR><P><CENTER><B>Table 12.2. Public methods of the Date class.</B></CENTER><P><CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%><TR VALIGN=TOP><TD WIDTH=291><I>Method</I></TD><TD WIDTH=227><I>Synopsis</I></TD></TR><TR VALIGN=TOP><TD WIDTH=291><TT>int getYear()</TT></TD><TD WIDTH=227>Year since 1900</TD></TR><TR VALIGN=TOP><TD WIDTH=291><TT>void setYear(int y)</TT></TD><TD WIDTH=227>Year since 1900</TD></TR><TR VALIGN=TOP><TD WIDTH=291><TT>int getMonth()</TT></TD><TD WIDTH=227>Month (0-11)</TD></TR><TR VALIGN=TOP><TD WIDTH=291><TT>void setMonth(int m)</TT></TD><TD WIDTH=227>Month (0-11)</TD></TR><TR VALIGN=TOP><TD WIDTH=291><TT>int getDate()</TT></TD><TD WIDTH=227>Day of month (1-31)</TD></TR><TR VALIGN=TOP><TD WIDTH=291><TT>void setDate(int d)</TT></TD><TD WIDTH=227>Day of month (1-31)</TD></TR><TR VALIGN=TOP><TD WIDTH=291><TT>int getDay()</TT></TD><TD WIDTH=227>Day of week (0-6)[0=Sunday]</TD></TR><TR VALIGN=TOP><TD WIDTH=291><TT>int getHours()</TT></TD><TD WIDTH=227>(0-23)</TD></TR><TR VALIGN=TOP><TD WIDTH=291><TT>void setHours(int h)</TT></TD><TD WIDTH=227>(0-23)</TD></TR><TR VALIGN=TOP><TD WIDTH=291><TT>int getMinutes()</TT></TD><TD WIDTH=227>(0-59)</TD></TR><TR VALIGN=TOP><TD WIDTH=291><TT>void setMinutes(int m)</TT></TD><TD WIDTH=227>(0-59)</TD></TR><TR VALIGN=TOP><TD WIDTH=291><TT>int getSeconds()</TT></TD><TD WIDTH=227>(0-59)</TD></TR><TR VALIGN=TOP><TD WIDTH=291><TT>void setSeconds(int s)</TT></TD><TD WIDTH=227>(0-59)</TD></TR><TR VALIGN=TOP><TD WIDTH=291><TT>long getTime()</TT></TD><TD WIDTH=227>Milliseconds since 1970</TD></TR><TR VALIGN=TOP><TD WIDTH=291><TT>void setTime(long totalSecs)</TT></TD><TD WIDTH=227>Milliseconds since 1970</TD></TR><TR VALIGN=TOP><TD WIDTH=291><TT>int hashCode()</TT></TD><TD WIDTH=227>Return the object's hash code</TD></TR><TR VALIGN=TOP><TD WIDTH=291><TT>String toString()</TT></TD><TD WIDTH=227>Uses UNIX ctime conventions</TD></TR><TR VALIGN=TOP><TD WIDTH=291><TT>String toLocaleString()</TT></TD><TD WIDTH=227>Uses locale conventions</TD></TR><TR VALIGN=TOP><TD WIDTH=291><TT>String toGMTString()</TT></TD><TD WIDTH=227>Uses Internet GMT conventions</TD></TR><TR VALIGN=TOP><TD WIDTH=291><TT>int getTimezoneOffset()</TT></TD><TD WIDTH=227>Minutes from GMT</TD></TR></TABLE></CENTER><P><H4>Creating Common Log Date Format</H4><P>None of the <TT>toString()</TT> variantsin the Date class match common log format. The following routinesuse a Date class to create the correct common log date format:<BLOCKQUOTE><TT> /**<BR> * Return the passed date as a commonlog format String.<BR> * @param d contains the date to convert<BR> */<BR> public String formatDate(Date d)<BR> {<BR> return "["+ formatFor2(d.getDate()) + "/" + getMonthName(d) +<BR> "/"+ (d.getYear() + 1900) +<BR> ":"+ formatFor2(d.getHours()) +<BR> ":"+ formatFor2(d.getMinutes()) +<BR> ":"+ formatFor2(d.getSeconds()) +<BR> "" + getTimezone(d) + "]";<BR> }<BR><BR> /**<BR> * return a String of the passed int. TheString will<BR> * be formatted to take up at least twoplaces.<BR> */<BR> public String formatFor2(int n)<BR> {<BR> String ret;<BR><BR> if ( n < 10)<BR> ret= new String("0" + n);<BR> else<BR> ret= new String("" + n);<BR> return ret;<BR> }<BR><BR> /**<BR> * Return the timezone formatted for commonlog format.<BR> * @param d contains the date to convert<BR> */<BR> public String getTimezone(Date d)<BR> {<BR> String ret;<BR><BR> int tz = d.getTimezoneOffset();<BR> int lf = tz %60; //check for remainders<BR> tz /= 60; //change to hours<BR><BR> // The polarityof getTimezoneOffset is backwards.<BR> // Positive valuesmean you are behind GMT.<BR> // Negative valuesmean GMT is behind you.<BR><BR> if ( tz > 0)<BR> ret= "-";<BR> else if ( tz <0 )<BR> ret= "+";<BR> else<BR> ret= "";<BR> ret += formatFor2(tz)+ formatFor2(lf);<BR> return ret;<BR> }<BR><BR> /**<BR> * Return a String representing the monthname in<BR> * common log format.<BR> * @param d contains the date to convert<BR> */<BR> public String getMonthName(Date d)<BR> {<BR> switch ( d.getMonth())<BR> {<BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -