Image 標(biāo)簽 <IMG src="../images/03.gif" border="0"> 所有屬性包括
Basic 屬性包括
alt
Class
Id
Long
Longdesc
Name
Src
Title
Usemap
Display 屬性包括
Align
Border
Dir
Height
Hspace
Ismap
Mapfile
Style
Vspace
Width
Events 屬性包括
Onclick
Ondbclick
Onhelp
Onkeydown
Onkeypress
Onkeyup
Onmounsedown
Onmousemove
Onmouseout
Onmouseover
Onmouseup
二、 HTML-Form
Image Button<INPUT type="image" src="../images/03.gif" />
Basic 屬性包括
Accept
Accesskey
Alt
Checked
Class
Disabled
Id
Long
Maxlength
Name
readonly
Src
Tabindex
Title
Type
Usemap
Value
Display 屬性包括
Align
Border
Dir
Height
Ismap
Isstyle
Size
Style
Width
Events 屬性包括
Onblur
Onchange
Onclick
Ondbclick
Onfocus
Onhelp
Onkeydown
Onkeypress
Onkeyup
Onmounsedown
Onmousemove
Onmouseout
Onmouseover
Onmouseup
Onselect
三、 Struts - Basic
Image <html:img page="/images/03.gif" border="0" />
Basic 屬性包括
Action
Alt
AltKey
Bundle
imageName
locale
lowsrc
Name
Page
PageKey
Paramname
Paramproperty
Paramscope
Src
SrcKey
Title
titleKey
Usemap
Display 屬性包括
Align
Border
Height
Hsapce
Ismap
Style
StyleClass
StyleId
Vsapce
Width
Events 屬性包括
Onclick
Ondbclick
Onkeydown
Onkeypress
Onkeyup
Onmounsedown
Onmousemove
Onmouseout
Onmouseover
Onmouseup
Other 屬性包括
contextRealtive
module
paramId
useLocalEncoding
四、 Struts-Form
Image Button <html:image page="/images/03.gif" />
Basic 屬性包括
Accesskey
Alt
altKey
bundle
Disabled
Indexed
Locale
Page
pageKey
property
Src
SrcKey
Tabindex
Title
titleKey
Value
Display 屬性包括
Align
Border
Style
styleClass
styleId
Events 屬性包括
Onblur
Onchange
Onclick
Ondbclick
Onfocus
Onkeydown
Onkeypress
Onkeyup
Onmounsedown
Onmousemove
Onmouseout
Onmouseover
Onmouseup
在 Struts 必須使用 Struts - Basic 下的 Image 標(biāo)簽 和 Struts-Form 下的 Image Button 按鈕。其中可以使用 servlet 隨機(jī)生成的圖片,或者 jsp 文件。 JSP 下的彩色驗(yàn)證碼的解決:
隨機(jī)驗(yàn)證圖片的生成文件
<%@ page contentType="image/jpeg" import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*" %>
<%!
Color getRandColor(int fc,int bc){// 給定范圍獲得隨機(jī)顏色
Random random = new Random();
if(fc>255) fc=255;
if(bc>255) bc=255;
int r=fc+random.nextInt(bc-fc);
int g=fc+random.nextInt(bc-fc);
int b=fc+random.nextInt(bc-fc);
return new Color(r,g,b);
}
%>
<%
// 設(shè)置頁(yè)面不緩存
response.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","no-cache");
response.setDateHeader("Expires", 0);
// 在內(nèi)存中創(chuàng)建圖象
int width=60, height=20;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 獲取圖形上下文
Graphics g = image.getGraphics();
// 生成隨機(jī)類(lèi)
Random random = new Random();
// 設(shè)定背景色
g.setColor(getRandColor(200,250));
g.fillRect(0, 0, width, height);
// 設(shè)定字體
g.setFont(new Font("Times New Roman",Font.PLAIN,18));
// 畫(huà)邊框
//g.setColor(new Color());
//g.drawRect(0,0,width-1,height-1);
// 隨機(jī)產(chǎn)生 155 條干擾線,使圖象中的認(rèn)證碼不易被其它程序探測(cè)到
g.setColor(getRandColor(160,200));
for (int i=0;i<155;i++)
{
int x = random.nextInt(width);
int y = random.nextInt(height);
int xl = random.nextInt(12);
int yl = random.nextInt(12);
g.drawLine(x,y,x+xl,y+yl);
}
// 取隨機(jī)產(chǎn)生的認(rèn)證碼 (4 位數(shù)字 )
String sRand="";
for (int i=0;i<4;i++){
String rand=String.valueOf(random.nextInt(10));
sRand+=rand;
// 將認(rèn)證碼顯示到圖象中
g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));// 調(diào)用函數(shù)出來(lái)的顏色相同,可能是因?yàn)榉N子太接近,所以只能直接生成
g.drawString(rand,13*i+6,16);
}
// 將認(rèn)證碼存入 SESSION
session.setAttribute("rand",sRand);
// 圖象生效
g.dispose();
// 輸出圖象到頁(yè)面
ImageIO.write(image, "JPEG", response.getOutputStream());
%>
使用頁(yè)面:
<%@ page contentType="text/html;charset=gb2312" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title> 認(rèn)證碼輸入頁(yè)面 </title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache">
<META HTTP-EQUIV="Expires" CONTENT="0">
</head>
<body>
<form method=post action="check.jsp">
<table>
<tr>
<td align=left> 系統(tǒng)產(chǎn)生的認(rèn)證碼: </td>
<td><img border=0 src="image.jsp"></td>
</tr>
<tr>
<td align=left> 輸入上面的認(rèn)證碼: </td>
<td><input type=text name=rand maxlength=4 value=""></td>
</tr>
<tr>
<td colspan=2 align=center><input type=submit value=" 提交檢測(cè) "></td>
</tr>
</table>
</form>
一直以來(lái)都是用jdk1.5,這次重返電信由于其系統(tǒng)是在jdk1.4上編譯的,編譯的時(shí)候出現(xiàn)了unsupported major.minor version49.0的錯(cuò)誤,上網(wǎng)查看了一下還是一個(gè)很普遍的錯(cuò)誤,搗鼓了兩天終于搗鼓出一些東西,現(xiàn)分享給大家。 何謂 major.minor,且又居身于何處呢?先感性認(rèn)識(shí)并找到 major.minor 來(lái)。順便寫(xiě)一段 代碼,然后用 JDK 1.5 的編譯器編譯成class,用UltraEdit或者其他能打開(kāi)非十進(jìn)制文件的軟件打開(kāi)此class,見(jiàn)下圖: ![]() 從上圖中我們看出來(lái)了什么是 major.minor version 了,它相當(dāng)于一個(gè)軟件的主次版本號(hào),只是在這里是標(biāo)識(shí)的一個(gè) Java Class 的主版本號(hào)和次版本號(hào),同時(shí)我們看到 minor_version 為 0x0000,major_version 為 0x0031,轉(zhuǎn)換為十制數(shù)分別為0 和 49,即 major.minor 就是 49.0 了。 現(xiàn)在不妨從 JDK 1.1 到 JDK 1.7 編譯器編譯出的 class 的默認(rèn) minor.major version 吧。(又走到 Sun 的網(wǎng)站上翻騰出我從來(lái)都沒(méi)用過(guò)的古董來(lái))
當(dāng)然你也可以用其他方法查看版本號(hào),比如javap -verbose XXXX(class名)。 那么現(xiàn)在如果碰到這種問(wèn)題該知道如何解決了吧,還會(huì)像我所見(jiàn)到有些兄弟那樣,去找個(gè) 1.4 的 JDK 下載安裝,然后用其重新編譯所有的代碼嗎?且不說(shuō)這種方法的繁瑣,而且web應(yīng)用程序還不一定能成功,其實(shí)大可不必如此費(fèi)神,我們一定還記得 javac 還有個(gè) -target 參數(shù),對(duì)啦,可以繼續(xù)使用 1.5 JDK,編譯時(shí)帶上參數(shù) -target 1.4 -source 1.4 就 OK 啦,不過(guò)你一定要對(duì)哪些 API 是 1.5 JDK 加入進(jìn)來(lái)的了如指掌,不能你的 class 文件拿到 JVM 1.4 下就會(huì) method not found。目標(biāo) JVM 是 1.3 的話,編譯選項(xiàng)就用 -target 1.3 -source 1.3 了。 相應(yīng)的如果使用 ant ,它的 javac 任務(wù)也可對(duì)應(yīng)的選擇 target 和 source
![]() 其實(shí)理解 major.minor 就像是我們可以這么想像,同樣是微軟件的程序,32 位的應(yīng)用程序不能拿到 16 位系統(tǒng)中執(zhí)行那樣。 |
概述
各種企業(yè)應(yīng)用幾乎都會(huì)碰到任務(wù)調(diào)度的需求,就拿論壇來(lái)說(shuō):每隔半個(gè)小時(shí)生成精華文章的RSS文件,每天凌晨統(tǒng)計(jì)論壇用戶(hù)的積分排名,每隔30分鐘執(zhí)行鎖定用戶(hù)解鎖任務(wù)。對(duì)于一個(gè)典型的MIS系統(tǒng)來(lái)說(shuō),在每月1號(hào)凌晨統(tǒng)計(jì)上個(gè)月各部門(mén)的業(yè)務(wù)數(shù)據(jù)生成月報(bào)表,每半個(gè)小時(shí)查詢(xún)用戶(hù)是否已經(jīng)有快到期的待處理業(yè)務(wù)……
Quartz 是開(kāi)源任務(wù)調(diào)度框架中的翹首,它提供了強(qiáng)大任務(wù)調(diào)度機(jī)制,同時(shí)保持了使用的簡(jiǎn)單性。Quartz 允許開(kāi)發(fā)人員靈活地定義觸發(fā)器的調(diào)度時(shí)間表,并可以對(duì)觸發(fā)器和任務(wù)進(jìn)行關(guān)聯(lián)映射。此外,Quartz提供了調(diào)度運(yùn)行環(huán)境的持久化機(jī)制,可以保存并恢復(fù)調(diào)度現(xiàn)場(chǎng),即使系統(tǒng)因故障關(guān)閉,任務(wù)調(diào)度現(xiàn)場(chǎng)數(shù)據(jù)并不會(huì)丟失。此外,Quartz還提供了組件式的偵聽(tīng)器、各種插件、線程池等功能。
Spring為創(chuàng)建Quartz的Scheduler、Trigger和JobDetail提供了便利的FactoryBean類(lèi),以便能夠在Spring 容器中享受注入的好處。此外Spring還提供了一些便利工具類(lèi)直接將Spring中的Bean包裝成合法的任務(wù)。Spring進(jìn)一步降低了使用Quartz的難度,能以更具Spring風(fēng)格的方式使用Quartz。概括來(lái)說(shuō)它提供了兩方面的支持:
創(chuàng)建JobDetail
可以直接使用Quartz的JobDetail在Spring中配置一個(gè)JobDetail Bean,但是JobDetail使用帶參的構(gòu)造函數(shù),對(duì)于習(xí)慣通過(guò)屬性配置的Spring用戶(hù)來(lái)說(shuō)存在使用上的不便。為此Spring通過(guò)擴(kuò)展JobDetail提供了一個(gè)更具Bean風(fēng)格的JobDetailBean。此外,Spring提供了一個(gè)MethodInvokingJobDetailFactoryBean,通過(guò)這個(gè)FactoryBean可以將Spring容器中Bean的方法包裝成Quartz任務(wù),這樣開(kāi)發(fā)者就不必為Job創(chuàng)建對(duì)應(yīng)的類(lèi)。
JobDetailBean
JobDetailBean擴(kuò)展于Quartz的JobDetail。使用該Bean聲明JobDetail時(shí),Bean的名字即是任務(wù)的名字,如果沒(méi)有指定所屬組,即使用默認(rèn)組。除了JobDetail中的屬性外,還定義了以下屬性:
● jobClass:類(lèi)型為Class,實(shí)現(xiàn)Job接口的任務(wù)類(lèi);
● beanName:默認(rèn)為Bean的id名,通過(guò)該屬性顯式指定Bean名稱(chēng),對(duì)應(yīng)任務(wù)的名稱(chēng);
● jobDataAsMap:類(lèi)型為Map,為任務(wù)所對(duì)應(yīng)的JobDataMap提供值。之所以需要提供這個(gè)屬性,是因?yàn)槌悄闶止ぷ?cè)一 個(gè)編輯器,你不能直接配置JobDataMap類(lèi)型的值,所以Spring通過(guò)jobDataAsMap設(shè)置JobDataMap的值;
●applicationContextJobDataKey:你可以將Spring ApplicationContext的引用保存到JobDataMap中,以便在Job的代碼中訪問(wèn)ApplicationContext。為了達(dá)到這個(gè)目的,你需要指定一個(gè)鍵,用以在jobDataAsMap中保存ApplicationContext,如果不設(shè)置此鍵,JobDetailBean就不將ApplicationContext放入到JobDataMap中;
●jobListenerNames:類(lèi)型為String[],指定注冊(cè)在Scheduler中的JobListeners名稱(chēng),以便讓這些監(jiān)聽(tīng)器對(duì)本任務(wù)的事件進(jìn)行監(jiān)聽(tīng)。
下面配置片斷使用JobDetailBean在Spring中配置一個(gè)JobDetail:
在②處獲取size值,在③處還可以根據(jù)鍵“applicationContext”獲取ApplicationContext,有了ApplicationContext的引用,Job就可以毫無(wú)障礙訪問(wèn)Spring容器中的任何Bean了。MyJob可以在execute()方法中對(duì)JobDataMap進(jìn)行更改,如④所示。如果MyJob實(shí)現(xiàn)Job接口,這個(gè)更改對(duì)于下一次執(zhí)行是不可見(jiàn)的,如果MyJob實(shí)現(xiàn)StatefulJob接口,這種更改對(duì)下一次執(zhí)行是可見(jiàn)的。
MethodInvokingJobDetailFactoryBean
通常情況下,任務(wù)都定義在一個(gè)業(yè)務(wù)類(lèi)方法中。這時(shí),為了滿(mǎn)足Quartz Job接口的規(guī)定,還需要定義一個(gè)引用業(yè)務(wù)類(lèi)方法的實(shí)現(xiàn)類(lèi)。為了避免創(chuàng)建這個(gè)只包含一行調(diào)用代碼的Job實(shí)現(xiàn)類(lèi),Spring為我們提供了MethodInvokingJobDetailFactoryBean,借由該FactoryBean,我們可以將一個(gè)Bean的某個(gè)方法封裝成滿(mǎn)足Quartz要求的Job。來(lái)看一個(gè)具體的例子:
jobDetail_1將MyService#doJob()封裝成一個(gè)任務(wù),同時(shí)通過(guò)concurrent屬性指定任務(wù)的類(lèi)型,默認(rèn)情況下封裝為無(wú)狀態(tài)的任務(wù),如果希望目標(biāo)封裝為有狀態(tài)的任務(wù),僅需要將concurrent設(shè)置為false就可以了。Spring通過(guò)名為concurrent的屬性指定任務(wù)的類(lèi)型,能夠更直接地描述到任務(wù)執(zhí)行的方式(有狀態(tài)的任務(wù)不能并發(fā)執(zhí)行,無(wú)狀態(tài)的任務(wù)可并發(fā)執(zhí)行)。
MyService服務(wù)類(lèi)擁有一個(gè)doJob()方法,它的代碼如下所示:
doJob()方法即可以是static也可以是非static的,但不能擁有方法入?yún)ⅰMㄟ^(guò)MethodInvokingJobDetailFactoryBean產(chǎn)生的JobDetail不能被序列化,所以不能被持久化到數(shù)據(jù)庫(kù)中的,如果希望使用持久化任務(wù),則你只能創(chuàng)建正規(guī)的Quartz的Job實(shí)現(xiàn)類(lèi)了。
創(chuàng)建Trigger
Quartz中另一個(gè)重要的組件就是Trigger,Spring按照相似的思路分別為SimpleTrigger和CronTrigger提供了更具Bean風(fēng)格的SimpleTriggerBean和CronTriggerBean擴(kuò)展類(lèi),通過(guò)這兩個(gè)擴(kuò)展類(lèi)更容易在Spring中以Bean的方式配置Trigger。
SimpleTriggerBean
默認(rèn)情況下,通過(guò)SimpleTriggerBean配置的Trigger名字即為Bean的名字,并屬于默認(rèn)組Trigger組。SimpleTriggerBean在SimpleTrigger的基礎(chǔ)上,新增了以下屬性:
● jobDetail:對(duì)應(yīng)的JobDetail;
● beanName:默認(rèn)為Bean的id名,通過(guò)該屬性顯式指定Bean名稱(chēng),它對(duì)應(yīng)Trigger的名稱(chēng);
● jobDataAsMap:以Map類(lèi)型為T(mén)rigger關(guān)聯(lián)的JobDataMap提供值;
● startDelay:延遲多少時(shí)間開(kāi)始觸發(fā),單位為毫秒,默認(rèn)為0;
● triggerListenerNames:類(lèi)型為String[],指定注冊(cè)在Scheduler中的TriggerListener名稱(chēng),以便讓這些監(jiān)聽(tīng)器對(duì)本觸發(fā)器的事件進(jìn)行監(jiān)聽(tīng)。
下面的實(shí)例使用SimpleTriggerBean定義了一個(gè)Trigger,該Trigger和jobDetail相關(guān)聯(lián),延遲10秒后啟動(dòng),時(shí)間間隔為20秒,重復(fù)執(zhí)行100次。此外,我們還為T(mén)rigger設(shè)置了JobDataMap數(shù)據(jù):
需要特別注意的是,①處配置的JobDataMap是Trigger的JobDataMap,任務(wù)執(zhí)行時(shí)必須通過(guò)以下方式獲取配置的值:
CronTriggerBean
CronTriggerBean擴(kuò)展于CronTrigger,觸發(fā)器的名字即為Bean的名字,保存在默認(rèn)組中。在CronTrigger的基礎(chǔ)上,新增的屬性和SimpleTriggerBean大致相同,配置的方法也和SimpleTriggerBean相似,下面給出一個(gè)簡(jiǎn)單的例子:
SchedulerFactoryBean的triggers屬性為T(mén)rigger[]類(lèi)型,可以通過(guò)該屬性注冊(cè)多個(gè)Trigger,在①處,我們注冊(cè)了一個(gè)Trigger。Scheduler擁有一個(gè)類(lèi)似于ServletContext的SchedulerContext。SchedulerFactoryBean允許你以Map的形式設(shè)置SchedulerContext的參數(shù)值,如②所示。默認(rèn)情況下,Quartz在類(lèi)路徑下查詢(xún)quartz.properties配置文件,你也可以通過(guò)configLocation屬性顯式指定配置文件位置,如③所示。
除了實(shí)例中所用的屬性外,SchedulerFactoryBean還擁有一些常見(jiàn)的屬性:
●calendars:類(lèi)型為Map,通過(guò)該屬性向Scheduler注冊(cè)Calendar;
●jobDetails:類(lèi)型為JobDetail[],通過(guò)該屬性向Scheduler注冊(cè)JobDetail;
●autoStartup:SchedulerFactoryBean在初始化后是否馬上啟動(dòng)Scheduler,默認(rèn)為true。如果設(shè)置為false,需要手工啟動(dòng)Scheduler;
●startupDelay:在SchedulerFactoryBean初始化完成后,延遲多少秒啟動(dòng)Scheduler,默認(rèn)為0,表示馬上啟動(dòng)。如果并非馬上擁有需要執(zhí)行的任務(wù),可通過(guò)startupDelay屬性讓Scheduler延遲一小段時(shí)間后啟動(dòng),以便讓Spring能夠更快初始化容器中剩余的Bean;
SchedulerFactoryBean的一個(gè)重要功能是允許你將Quartz配置文件中的信息轉(zhuǎn)移到Spring配置文件中,帶來(lái)的好處是,配置信息的集中化管理,同時(shí)我們不必熟悉多種框架的配置文件結(jié)構(gòu)。回憶一個(gè)Spring集成JPA、Hibernate框架,就知道這是Spring在集成第三方框架經(jīng)常采用的招數(shù)之一。SchedulerFactoryBean通過(guò)以下屬性代替框架的自身配置文件:
●dataSource:當(dāng)需要使用數(shù)據(jù)庫(kù)來(lái)持久化任務(wù)調(diào)度數(shù)據(jù)時(shí),你可以在Quartz中配置數(shù)據(jù)源,也可以直接在Spring中通過(guò)dataSource指定一個(gè)Spring管理的數(shù)據(jù)源。如果指定了該屬性,即使quartz.properties中已經(jīng)定義了數(shù)據(jù)源,也會(huì)被此dataSource覆蓋;
●transactionManager:可以通過(guò)該屬性設(shè)置一個(gè)Spring事務(wù)管理器。在設(shè)置dataSource時(shí),Spring強(qiáng)烈推薦你使用一個(gè)事務(wù)管理器,否則數(shù)據(jù)表鎖定可能不能正常工作;
●nonTransactionalDataSource:在全局事務(wù)的情況下,如果你不希望Scheduler執(zhí)行化數(shù)據(jù)操作參與到全局事務(wù)中,則可以通過(guò)該屬性指定數(shù)據(jù)源。在Spring本地事務(wù)的情況下,使用dataSource屬性就足夠了;
●quartzProperties:類(lèi)型為Properties,允許你在Spring中定義Quartz的屬性。其值將覆蓋quartz.properties配置文件中的設(shè)置,這些屬性必須是Quartz能夠識(shí)別的合法屬性,在配置時(shí),你可以需要查看Quartz的相關(guān)文檔。下面是一個(gè)配置quartzProperties屬性的例子:
在實(shí)際應(yīng)用中,我們并不總是在程序部署的時(shí)候就可能確定需要哪些任務(wù),往往需要在運(yùn)行期根據(jù)業(yè)務(wù)數(shù)據(jù)動(dòng)態(tài)產(chǎn)生觸發(fā)器和任務(wù)。你完全可以在運(yùn)行期通過(guò)代碼調(diào)用SchedulerFactoryBean獲取Scheduler實(shí)例,進(jìn)行動(dòng)態(tài)的任務(wù)注冊(cè)和調(diào)度。
小結(jié)
Spring為Quartz的JobDetail和Trigger提供了更具Bean風(fēng)格的支持類(lèi),這使我們能夠更地方便地在Spring中通過(guò)配置定制這些組件實(shí)例。Spring的SchedulerFactoryBean讓我們可以脫離Quartz自身的配置體系,而以更具Spring風(fēng)格的方式定義Scheduler。此外,還可以享受Scheduler生命周期和Spring 容器生命周期綁定的好處。
使用下面的命令行啟動(dòng)eclipse:
如果通過(guò)快捷方式啟動(dòng)eclipse,這樣操作:“右鍵->屬性->目標(biāo)(輸入框)”,參照上面的命令行在輸入框中修改其中的命令行。
myEclipse也可以參照這樣使用。
以下設(shè)置在大多數(shù)系統(tǒng)應(yīng)該產(chǎn)生比出廠設(shè)置更好的性能。
-XX:+UseConcMarkSweepGC
是相互排斥的。
簡(jiǎn)單的說(shuō)log4j就是用于幫助開(kāi)發(fā)人員進(jìn)行日志輸出管理的API類(lèi)庫(kù)。它最重要的特點(diǎn)是可以配置文件靈活的設(shè)置日志信息的優(yōu)先級(jí)、日志信息的輸出目的地以及日志信息的輸出格式。Log4j除了可以記錄程序運(yùn)行日志信息外還有一重要的功能就是用來(lái)顯示調(diào)試信息。
1、定義配置文件
首先使用配置文件將使我們的應(yīng)用程序更加靈活配置。log日志輸出方式包括輸出優(yōu)先級(jí)、輸出目的地、輸出格式。Log4j支持兩種配置文件格式,一種是XML格式的文件,一種是Java特性文件log4j.properties(鍵=值)。下面將介紹使用log4j.properties文件作為配置文件的方法:
①配置根Logger,其語(yǔ)法為:0
log4j.rootLogger = [ level ] , appenderName, appenderName, …
其中,level 是日志記錄的優(yōu)先級(jí),分為OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者自定義的級(jí)別。Log4j建議只使用四個(gè)級(jí)別,優(yōu)先級(jí)從高到低分別是ERROR、WARN、INFO、DEBUG。通過(guò)在這里定義的級(jí)別,您可以控制到應(yīng)用程序中相應(yīng)級(jí)別的日志信息的開(kāi)關(guān)。比如在這里定義了INFO級(jí)別,則應(yīng)用程序中所有DEBUG級(jí)別的日志信息將不被打印出來(lái)。 appenderName就是指定日志信息輸出到哪個(gè)地方。可同時(shí)指定多個(gè)輸出目的地。
②配置日志信息輸出目的地Appender,其語(yǔ)法為:
log4j.appender.appenderName = fully.qualified.name.of.appender.class
log4j.appender.appenderName.option1 = value1
…
log4j.appender.appenderName.option = valueN
其中,Log4j提供的appender有以下幾種:
org.apache.log4j.ConsoleAppender(控制臺(tái)),
org.apache.log4j.FileAppender(文件),
org.apache.log4j.DailyRollingFileAppender(每天產(chǎn)生一個(gè)日志文件),
org.apache.log4j.RollingFileAppender(文件大小到達(dá)指定尺寸的時(shí)候產(chǎn)生一個(gè)新的文件),
org.apache.log4j.WriterAppender(將日志信息以流格式發(fā)送到任意指定的地方)
③配置日志信息的格式(布局),其語(yǔ)法為:
log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
log4j.appender.appenderName.layout.option1 = value1
…
log4j.appender.appenderName.layout.option = valueN
其中,Log4j提供的layout有以下幾種:
org.apache.log4j.HTMLLayout(以HTML表格形式布局),
org.apache.log4j.PatternLayout(可以靈活地指定布局模式),
org.apache.log4j.SimpleLayout(包含日志信息的級(jí)別和信息字符串),
org.apache.log4j.TTCCLayout(包含日志產(chǎn)生的時(shí)間、線程、類(lèi)別等等信息)
Log4J采用類(lèi)似C語(yǔ)言中的printf函數(shù)的打印格式格式化日志信息,打印參數(shù)如下: %m 輸出代碼中指定的消息
%p 輸出優(yōu)先級(jí),即DEBUG,INFO,WARN,ERROR,F(xiàn)ATAL
%r 輸出自應(yīng)用啟動(dòng)到輸出該log信息耗費(fèi)的毫秒數(shù)
%c 輸出所屬的類(lèi)目,通常就是所在類(lèi)的全名
%t 輸出產(chǎn)生該日志事件的線程名
%n 輸出一個(gè)回車(chē)換行符,Windows平臺(tái)為“\r\n”,Unix平臺(tái)為“\n”
%d 輸出日志時(shí)間點(diǎn)的日期或時(shí)間,默認(rèn)格式為ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},輸出類(lèi)似:2002年10月18日 22:10:28,921
%l 輸出日志事件的發(fā)生位置,包括類(lèi)目名、發(fā)生的線程,以及在代碼中的行數(shù)。舉例:Testlog4.main(TestLog4.java:10)
2、在代碼中使用Log4j
①得到記錄器
使用Log4j,第一步就是獲取日志記錄器,這個(gè)記錄器將負(fù)責(zé)控制日志信息。其語(yǔ)法為:
public static Logger getLogger( String name)
通過(guò)指定的名字獲得記錄器,如果必要的話,則為這個(gè)名字創(chuàng)建一個(gè)新的記錄器。Name一般取本類(lèi)的名字,比如:
static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () )
②讀取配置文件
當(dāng)獲得了日志記錄器之后,第二步將配置Log4j環(huán)境,其語(yǔ)法為:
BasicConfigurator.configure (): 自動(dòng)快速地使用缺省Log4j環(huán)境。
PropertyConfigurator.configure ( String configFilename) :讀取使用Java的特性文件編寫(xiě)的配置文件。
例:PropertyConfigurator.configure(".\\src\\log4j.properties")
DOMConfigurator.configure ( String filename ) :讀取XML形式的配置文件。
③插入記錄信息(格式化日志信息)
當(dāng)上兩個(gè)必要步驟執(zhí)行完畢,就可輕松地使用不同優(yōu)先級(jí)別的日志記錄語(yǔ)句插入到您想記錄日志的任何地方,其語(yǔ)法如下:
Logger.debug ( Object message ) ;
Logger.info ( Object message ) ;
Logger.warn ( Object message ) ;
Logger.error ( Object message ) ;
下面是配置文件log4j.properties的內(nèi)容:
程序說(shuō)明:
① log4j.rootCategory=DEBUG, stdout,R
要顯示所有優(yōu)先權(quán)等于和高于Debug的信息。
"stdout",”R”表示定義了兩個(gè)輸出端。
②下面的三行說(shuō)stdout輸出端其實(shí)是標(biāo)準(zhǔn)輸出Console,也就是屏幕。輸出的格式是PatternLayout。轉(zhuǎn)換方式是%5p (%F:%L) - %m%n,即前五格用來(lái)顯示優(yōu)先權(quán),再顯示當(dāng)前的文件名,加當(dāng)前的行數(shù)。最后是logger.debug()或logger.info()或logger.warn()或logger.error()里的信息。%n表示回車(chē)空行。
③再加上下面六行則說(shuō)明log信息不光顯示在屏幕上,而且被保存在一個(gè)叫"log.txt"的文件里,文件最大為100KB。如果文件大小超過(guò)100KB,文件會(huì)被備份成"log.txt.1",新的"log.txt"繼續(xù)記錄log信息。
我們可以改變log4j.properties,而不需重新編譯就可以控制log信息是否顯示、log信息的輸出端類(lèi)型、輸出方式、輸出格式,等等。舉例如下:
①在log4j.properties文件里把"log4j.rootCategory=DEBUG,stdout,R"改寫(xiě)成"log4j.rootCategory=OFF, stdout,R",這樣所有的log信息都不會(huì)顯示了;解決了本文開(kāi)始提出的問(wèn)題。
②在log4j.properties文件里把"log4j.rootCategory=DEBUG,stdout,R"改寫(xiě)成"log4j.rootCategory=INFO, stdout,R",這樣只顯示INFO, WARN, ERROR的log信息,而DEBUG信息不會(huì)被顯示;
在web程序中使用log4j注意問(wèn)題
1、 由于jsp或servlet在執(zhí)行狀態(tài)時(shí)沒(méi)有當(dāng)前路徑概念,所有使用PropertyConfigurator.configure(String)語(yǔ)句找log4j.properties文件時(shí)要給出相對(duì)于當(dāng)前jsp或servlet的路徑轉(zhuǎn)化成為一個(gè)絕對(duì)的文件系統(tǒng)路徑。方法是使用servletcontext.getrealpath(string)語(yǔ)句。例:
2、相應(yīng)的log4j.properties設(shè)置某個(gè)屬性時(shí)也要在程序中設(shè)置絕對(duì)路徑。例:
log4j.appender.R.File屬性設(shè)置日志文件存放位置。可以用讀寫(xiě).properties配置文件的方法進(jìn)行靈活設(shè)置。
附:[配置文件]