js处理导航菜单当前位置高亮

在wordpress中,当用Category或Page当导航菜单的话,wordpress已经处理好当前li标签的class了,所以用wordpress的Category或Page当导航菜单不用作本文的处理。我在bbpress中,想把每个父版块做成导航菜单的时候碰到这个问题的。

Jeremy Keith 在《JavaScript DOM编程艺术》一书中为我们做了一个小的例子,例子中使用了一段简单的高亮当前位置的 js 代码,代码如下:

function highlightPage() {
       if (!document.getElementsByTagName) return false;
       if (!document.getElementById) return false;
       if (!document.getElementById("navigation")) return false;

       var nav = document.getElementById("navigation");
       var links = nav.getElementsByTagName("a");

       for (var i=0; i<Links.length; i++){
              var linkurl = links[i].getAttribute("href");
              var currenturl = window.location.href;
              if (currenturl.indexOf(linkurl) != -1) {
                    links[i].className = "here";
                    var linktext = links[i].lastChild.nodeValue.toLowerCase();
                    document.body.setAttribute("id",linktext);
              }
        }
}

原理很简单,就是首先获取当前的网址,然后遍历菜单栏,如果当前网址包含了菜单栏内的链接地址,就给这个链接的 class 定义为 here,从而达到高亮的效果。但是我在使用的过程中遇到了一些特殊情况,这段代码就不能满足我的要求了。

先看以下菜单栏:

<div id="menu">
   <ul>
      <li><a href="http://yoursite.net/">首页</a></li>
      <li><a href="http://yoursite.net/2">第二页</a></li>
      <li><a href="http://yoursite.net/3">第三页</a></li>
   </ul>
</div>

如果我是用了上述 js 代码,那么当我停留在第二页或者第三页的时候首页同时也会被高亮,这并不是我想要的结果,解决方法有二:

第一种方法,可以在首页的网址后边再加一个 index.php 或者其他的后缀,这样子就可以解决问题,优点是简单,缺点是无法解决更复杂的菜单,比如在一个使用了 URL 静态化的二级页面,这种方法将无法实施。

第二种方法,采用 split() 获得更精确的定位。

split() 方法用于把一个字符串分割成字符串数组,这里我们将网址通过“/”进行拆分,首先是拆分当前网址:

  
var windowLocation = window.location.href.split("/");

现在我们将网址拆分成一个数组,然后我们将获得网址最后的部分,但是需要注意的是,http://yoursite.net/ 和 http://yoursite.net 是两个不同的网址,如果我们漏掉了其中的一个,可能会导致我们的脚本无效,因此我们需要判断这个网址的末尾是否含有”/”。

JS 代码:

var windowLocation = window.location.href.split("/");
var locationLong = windowLocation.length;
var locationHref;

if(windowLocation[locationLong-1] == "") {
    locationHref = windowLocation[locationLong-2];
} else {
    locationHref = windowLocation[locationLong-1];
}

当当前的网址含有”/”也就是 windowLocation 的最后一个为”"的时候,我们就取倒数第二个值,否则我们就取倒数第一个值。取好当前网址的值后,同理我们也要这样子取一下菜单栏的地址:

var menu = document.getElementById("menu");
var menuLinks = menu.getElementsByTagName("a");

for(var i=0; i<menuLinks.length; i++){
     var linksHref = menuLinks[i].split("/");
     var linksLong = linksHref.length;
     var linksRighthref;

     if(linksHref[linksLong-1] == "") {
          linksRighthref = linksHref[linksLong-2];
     } else {
          linksRighthref = linksHref[linksLong-1];
     }
     //hight menu
    if(locationHref == linksRighthref) {
          menuLinks[i].className = "here";
     }
}

当然,如果页面还有存在页面翻页参数,如在同一个菜单下默认第一页链接是http://yoursite.net/,第二页链接是http://yoursite.net/?page=2,这样必须在后面的截取段进行进一步的if匹配判断,方法类似。
这样代码就可以解决我们的问题了,优点是实用性较高,但是代码有些复杂。

本文部分内容来自:http://blog.admin9.com/?p=888

jquery实现有默认内容的展开收起效果

前些天在实现一个网站的需求:1、展示一个分类里边的条目;2、默认显示前十条,并显示一个展开按钮,点击展开按钮,点击后下拉显示该分类下所有条目;3、展开后,按钮变为收起按钮,点击收起恢复为默认显示条目。

试图想用jquery的slideToggle()animate()函数实现,发现行不通,处理不了剩余内容的展开收起。后来想到通过联系展开按钮的class与主题内容的id匹配,在按钮的click事件里通过修改css和jquery的animate()函数结合实现想要的效果,代码如下(这边显示一段文字,默认显示文字前面的一部分内容):

jquery部分:

$(".more-btn").click(function(){
			 if($("#"+this.parentNode.className).css("height")=="100px"){
			  	$("#"+this.parentNode.className).css("height","auto");
			  	this.value="收起";
			  }
			 else{
			 	$("#"+this.parentNode.className).animate({height:"100px"},"slow");
			 	this.value="展开";
			 	}
		  });

css部分:

body {
			margin:0;
			padding:40px 40px;
			background:#fff;
			font:Arial, Helvetica, sans-serif;
			font-size:13px;
			line-height:180%;
		}
		.case{
			width:240px;
		}
		.entry{
			clear: both;
			line-height: 1.6em;
			width:223px;
			height:100px;
			overflow:hidden;
			line-height:18px;
			border-top:#ff9933 1px solid;
			border-left:#ff9933 1px solid;
			border-right:#ff9933 1px solid;
			padding-left:5px;
		}
		.more-btn{
			padding:0;
			width:230px;
			border-left:#ff9933 1px solid;
			border-right:#ff9933 1px solid;
			height:27px;
			background:#f4dc92;
			font-size:14px;
			font-weight:bolder;
			color:#000;
		}             

html代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>demo</title>
</head>
<body>
	<div class="case">    	
	<div class="entry" id="entry-1">	
	      	显示的内容在此。。。
	</div><!--entry-->
	<div class="entry-1"><input type="button"  class="more-btn" value="更多" /></div>	
	</div> <!--case-->
</body>
</html>

demo:猛击此查看demo

原创wordpress主题BlueShowyo发布

终于实现了对自己的承诺,发布了第一个wordpress主题,将就把它叫做BlueShowyo,因为清一色蓝色调,晾出来勉励一下自己(配色方面还是要多学习了,争取做出像样点的主题),让自己能够一直学习下去,保持对设计方面的兴趣。整个主题的效果也就是我现在用的主题那样,个人觉得比较简单(但不清新),欢迎有兴趣试用的朋友批评,下载地址如下:

猛击此下载BlueShowyo Theme

github地址:Fork from github

发现问题请留言提出,谢谢。

话不多说,主题截图如下:

想预览大图请猛击以上图片。

查看Theme演示:Demo

Const,Const函数,Const变量,函数后面的Const 的区别

看到const 关键字,C++程序员首先想到的可能是const 常量。这可不是良好的条件反射。如果只知道用const 定义常量,那么相当于把火药仅用于制作鞭炮。const 更大的魅力是它可以修饰函数的参数、返回值,甚至函数的定义体。

const 是constant 的缩写,“恒定不变”的意思。被const 修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。所以很多C++程序设计书籍建议:“Use const whenever you need”。

1.用const 修饰函数的参数

如果参数作输出用,不论它是什么数据类型,也不论它采用“指针传递”还是“引用传递”,都不能加const 修饰,否则该参数将失去输出功能。const 只能修饰输入参数:

如果输入参数采用“指针传递”,那么加const 修饰可以防止意外地改动该指针,起到保护作用。

例如StringCopy 函数:

void StringCopy(char *strDestination, const char *strSource);

其中strSource 是输入参数,strDestination 是输出参数。给strSource 加上const修饰后,如果函数体内的语句试图改动strSource 的内容,编译器将指出错误。

如果输入参数采用“值传递”,由于函数将自动产生临时变量用于复制该参数,该输入参数本来就无需保护,所以不要加const 修饰。

例如不要将函数void Func1(int x) 写成void Func1(const int x)。同理不要将函数void Func2(A a) 写成void Func2(const A a)。其中A 为用户自定义的数据类型。

对于非内部数据类型的参数而言,象void Func(A a) 这样声明的函数注定效率比较底。因为函数体内将产生A 类型的临时对象用于复制参数a,而临时对象的构造、复制、析构过程都将消耗时间。

为了提高效率,可以将函数声明改为void Func(A &a),因为“引用传递”仅借用一下参数的别名而已,不需要产生临时对象。但是函数void Func(A &a) 存在一个缺点:

“引用传递”有可能改变参数a,这是我们不期望的。解决这个问题很容易,加const修饰即可,因此函数最终成为void Func(const A &a)。

以此类推,是否应将void Func(int x) 改写为void Func(const int &x),以便提高效率?完全没有必要,因为内部数据类型的参数不存在构造、析构的过程,而复制也非常快,“值传递”和“引用传递”的效率几乎相当。

问题是如此的缠绵,我只好将“const &”修饰输入参数的用法总结一下。

对于非内部数据类型的输入参数,应该将“值传递”的方式改为“const 引用传递”,目的是提高效率。例如将void Func(A a) 改为void Func(const A &a)。

对于内部数据类型的输入参数,不要将“值传递”的方式改为“const 引用传递”。否则既达不到提高效率的目的,又降低了函数的可理解性。例如void Func(int x) 不应该改为void Func(const int &x)。

2 用const 修饰函数的返回值
如果给以“指针传递”方式的函数返回值加const 修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const 修饰的同类型指针。例如函数
const char * GetString(void);
如下语句将出现编译错误:
char *str = GetString();
正确的用法是
const char *str = GetString();
如果函数返回值采用“值传递方式”,由于函数会把返回值复制到外部临时的存储单元中,加const 修饰没有任何价值。
例如不要把函数int GetInt(void) 写成const int GetInt(void)。
同理不要把函数A GetA(void) 写成const A GetA(void),其中A 为用户自定义的数据类型。
如果返回值不是内部数据类型,将函数A GetA(void) 改写为const A & GetA(void)的确能提高效率。但此时千万千万要小心,一定要搞清楚函数究竟是想返回一个对象的“拷贝”还是仅返回“别名”就可以了,否则程序会出错。
函数返回值采用“引用传递”的场合并不多,这种方式一般只出现在类的赋值函数中,目的是为了实现链式表达。

例如:
class A
{
A & operate = (const A &other); // 赋值函数
};
A a, b, c; // a, b, c 为A 的对象

a = b = c; // 正常的链式赋值
(a = b) = c; // 不正常的链式赋值,但合法
如果将赋值函数的返回值加const 修饰,那么该返回值的内容不允许被改动。上例中,语句 a = b = c 仍然正确,但是语句 (a = b) = c 则是非法的。
3 const 成员函数
任何不会修改数据成员的函数都应该声明为const 类型。如果在编写const 成员函数时,不慎修改了数据成员,或者调用了其它非const 成员函数,编译器将指出错误,这无疑会提高程序的健壮性。以下程序中,类stack 的成员函数GetCount 仅用于计数,从逻辑上讲GetCount 应当为const 函数。编译器将指出GetCount 函数中的错误。
class Stack
{
public:
void Push(int elem);
int Pop(void);
int GetCount(void) const; // const 成员函数
private:
int m_num;
int m_data[100];
};
int Stack::GetCount(void) const
{
++ m_num; // 编译错误,企图修改数据成员m_num
Pop(); // 编译错误,企图调用非const 函数
return m_num;
}
const 成员函数的声明看起来怪怪的:const 关键字只能放在函数声明的尾部,大概是因为其它地方都已经被占用了。
关于Const函数的几点规则:

a. const对象只能访问const成员函数,而非const对象可以访问任意的成员函数,包括const成员函数.
b. const对象的成员是不可修改的,然而const对象通过指针维护的对象却是可以修改的.
c. const成员函数不可以修改对象的数据,不管对象是否具有const性质.它在编译时,以是否修改成员数据为依据,进行检查.
d. 然而加上mutable修饰符的数据成员,对于任何情况下通过任何手段都可修改,自然此时的const成员函数是可以修改它的

文章来源:http://www.cnblogs.com/Fancyboy2004/archive/2008/12/23/1360810.html

需求建立过程——让客户满意也让自己满意

本文纯属个人最近一次需求调研浅见,觉得本文肤浅、无价值的可游过~

注:之前一直从事幕后“积木搭建”工作,此次是第一次从需求调研开始到需求评审通过全程跟踪经历。在调研前,作者所属调研组计划在两周之内搞定需求过程,完成最终文档的评审工作,最后,现实花了我们一个月的时间完成预期的工作内容。

一、网上释义

对于需求调研,网上评价较高的相关文章是这样解释的:

1、需求调研是为需求说明书做前期工作,可以说需求说明书是从需求调研表中得到或抽取而出。

2、需求调研是要了解现实世界中做实际工作的人们真正需要什么样的程序的过程,再把这些需求进行细节整理由设计及开发部门设计开发,最后产出用户真正需要的产品。

二、需求文档的重要性及初期架设

结合以上解释,需求文档显然是重中之重,它将是需求的终极成果,在调研之初就要在做好最初架设工作。因此:

1、从需求调研开始调研者就应该对要呈现客户面前的需求文档结构(一般公司有提供模板)有一个清醒的认识;

2、在调研之初,根据合同要求的项目签订模块内容,架设自己脑中的项目原型(可以虚拟,至少有一个笼统性的意识);

3、把对项目的架设方案在文档中以清晰地层次关系记录编写,形成文档雏形(即使只有简单的各主标题、下层级标题的空文档)。

显然,在文档的初期架设并不是一个简单的过程,其中要求的一个很重要的条件是系统分析师必须对整个系统要有非常的深刻的认识,而且在对相关系统认识的面上要广。在作者接触的该需求过程中,因为之前都是完成逐个模块化功能完成“搭积木式”的开发工作,并没有对相关系统有一个全面深刻的认识,所以在需求文档的初步架设时,没能做好工作,也导致之后的需求调研会上的尴尬,吸取了不少经验教训。好在作者并不是一个人,强大的调研组让作者不用面对很多来自客户及第三方的尴尬。

三、建立、磨合与甲方项目负责人、相关人的关系

甲方项目负责人(以下简称项目负责人)负责整个项目的周期,负责系统研发过程中的甲方乙方的交流协同工作,是系统使用者与开发人员的沟通桥梁,把握好与项目负责人之间的微妙关系至关重要。项目相关人可能是上级领导、系统直接使用人、第三方开发者等,也直接关系到需求获取、变更、系统体验获取、改善等环节的交流,是项目研发过程不可缺少的成员,其重要性也可见一斑。至于如何把握好人际关系相信读者自有体会,在此不做相关讨论,作者只从项目需求角度作简要分析:

1、根据对甲方的预期需求的理解,针对不清楚之处,向项目负责人提出疑问,得到适当回答内容,做相应记录;

2、询问项目负责人相关项目的项目组人员,并由项目负责人介绍,会见相关人员;

3、初次会面时,针对相关人员、领导,介绍项目总体情况,征求相关意见并要求相关人员调研过程中给予配合,尤其是系统的直接使用者。

4、定期向项目负责人发送周报(非必要)。

四、做好每次调研会议计划

调研会议是需求调研中最为重要的环节,需求过程中所有的调研会议是需求获取的主要来源(其他来源还有项目负责人等,因为项目负责人对自己公司业务熟悉,对相关人员的业务描述较容易转化为系统实现,且会做相关的补充),要完成一次完美的调研会议,显然会议计划必不可少。基于本次的调研过程,作者认为调研会议计划需要注意:

1、系统分析人员事前必须非常清楚自己想要什么,要项目相关人员做些什么,要他们提供什么信息,这样才能有目的性的提出相关问题,避免偏题跑题的会议;

2、必须清楚本次调研内容的归口人,也就是说要有针对性地确定参会人员,每次会议都让一批人来听两个人的讨论会令人反感;

五、做好调研会的提问、讲解及演示

毫无疑问,这是调研人员必备素质,是调研过程中最为重要的内容。调研会议过程能体现出系统分析是的专业程度及项目分析方法的掌握程度,没有扎实的专业功底,在该环节会出现诸多尴尬,作者由于相关专业知识欠缺,便在这环节除了不少问题,此文就且当做经验之谈吧,寄望能在系统分析方面茁壮成长。基于本次各个调研会议,作者有以下认识:

1、提问时,对要问的问题有条理性,要想想当前功能点能否实现,之前是怎么实现的,可以怎么样实现等,相关功能点的提问尽量全面;

2、可以在提问的时候尽量引导客户往对项目和系统实际应用最佳的方式走,因为可能业务人员之前没用过相关系统,没有相关概念,很多标准是在需求时调研组帮客户定的,当然关键的是帮客户定的标准要保证充分的科学性;

3、在调研的提问、讲解及演示过程中,尽量少用业内专业术语,不要用系统研发方式语言跟客户进行交流,站在用户的角度提问、答问,这样才能让人知所以然,可能你觉得很简单的术语,在业务人员看来很生涩,这样会浪费更多的时间在解释上;

4、在交流过程中记得做关键点的记录,很多时候你觉得你明白的某个功能点经过几个小时的会议之后,又会是一片模糊,记得养成会议记录的习惯,这样不至于浪费更多的时间在同样问题上,而且方便需求获取的信息整理,方便需求文档的编写;

5、存在第三方接口的调研情况下,应该事先跟第三方达成一致,完后才跟客户进行确认、答疑,对客户或第三方提出不能实现的功能,给予回绝或转包;

6、需求讲解、演示的时候尽量抓重点讲,不用每个点都很细致地讲解,把握时间与会议内容的平衡,才不至于拖延会议时间或者没最终完成会议演示计划;

7、当客户谈及与系统无关或偏离系统需求的事情时,找适当时机把话题转回来,不要发生会议主题变质;

8、适当拉动调研会议气氛,让会议朝你想象的方向走。

六、需求文档该注意的

前面说过,需求文档是调研成果的体现,决不能在需求文档上含糊,需求文档是系统分析人员的基本功之一,系统分析人员应该把需求文档当成产品看待,让客户看到的各文档版本应该是可读、条理、规范、专业的产品化文档。作者在调研需求文档编写过程中,出现了很多专业分析员不应该出现的问题(作者目前非专业系统分析员),需求文档看上去只是很简单的一个文档,但是把调研过程的需求获取内容清晰有条理、以专业化的语言整合到一起,以文档形式展现,并非易事。在此暂不讨论需求文档如何编写之类问题,作者只谈需求整合过程中的感受:

1、每次调研会议结束后,理顺对每次的调研会议记录内容,根据会议内容对需求文档更新;

2、文档编写过程中,对功能点的描述尽量详细,有条理,让人知其所以然,做到让开发人员看到文档知道要做成什么样的功能,不要一笔带过、简单描述或内容杂糅。例如一个审批流程每个节点每个过程分点描述,不宜在一段话中描述一个流程从始至终的操作过程,这样会让阅读者感到吃力;

3、需求文档的编写是不断完善、不断改进的过程,不可能在一次的编写就完成主要功能点的描述,需要不断地鹅推敲、琢磨;

4、确认需求文档版本,保证每次提交给项目负责人及相关人员的文档版本不一样。

以上纯属作者实践后理论性理解,篇幅原因,文章较少实例分析,希望对阅读者略有帮助。

本文章归目油菜所有,转载请注明出处

关于WordPress固定链接自定义设置的问题

这是今天在WordPress后台设置中碰到的问题:

首页的所有文章点击评论、阅读全文等相关链接全部失效,因为之前忘数据库中导过备份,所以一直以为是数据的问题,试过多种设置,甚至把数据库导到本地环境。发现本地环境并没有相应的问题,而偏就它有问题了,这是为什么呢?

哈菜想了很久,最终,还是茫然,无奈,狠下心来,重新建个数据库,重装wp,一步一步测试,到底什么问题。

显然,刚装上的wp是没问题的,任你随便点都米问题。最后,让我点出灵感了,清晰地记得之前有设置过固定链接设置,于是乎,过去把固定链接自定义结构设置成之前设置的格式(哈菜设置成http://www.xiuchezu.com/2010/02/01/之类的格式),保存。再次首页秒点,果然,终于点不出来了,在回头改过来,保存,再秒点,果然,终于又出来了。最后,哈菜得出结论:问题就出在固定链接自定义格式上。可能是url解析之类的问题,种种原因,目前哈菜只是从很表面上解决问题,不晓得是不是wp的bug,望碰到相同问题已有更好解决方法或知其所以然的仁兄给以指点。

关于log4j.xml日志输出的配置

一、概述

在应用程序中添加日志记录总的来说基于三个目的:监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析工作;跟踪代码运行时轨迹,作为日后审计的依据;担当集成开发环境中的调试器的作用,向文件或控制台打印代码的调试信息。 Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

二、实例简析

以下是某个系统log4j.xml具体的配置,在此以注释做简要解析,具体配置详述见详述说明:

<?xml version="1.0" encoding="GBK"?>
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
<!—================================================—>
<!— 控制台输出通道 —>
<!—================================================—>
<!—appender标签:设置通道A1和输出方式:org.apache.log4j.ConsoleAppender即控制台输
出方式—>
<appender name="A1">
<!—layout标签:定义输出样式—>
<layout>
<!—ConversionPattern参数:设置输出文件项目和格式—>
<param name="ConversionPattern" value="%d %-4r %-5p (%F:%L) %10c %3x - %m%n"/>
</layout>
<!—filter标签:滤镜设置输出的级别,此处设置的过滤最大和最小级别参数都为FATAL,
因此,在控制台输出的消息都为FATAL级别的消息—>
<filter>
<param name="levelMin" value="FATAL"/>
<param name="levelMax" value="FATAL"/>
</filter>
</appender>
<!—===================================================—>
<!— 文件输出通道 —>
<!—===================================================—>
<!—第二个appender标签:设置通道A2和输出方式:
org.apache.log4j.DailyRollingFileAppender即文件输出方式—>
<appender name="A2">
<!—设置File参数:日志输出路径及文件名:D:/DOCUMENT/logs/log.log—>
<param name="File" value="D:/DOCUMENT/logs/log.log"/>
<!—同第一个appender节点的layout标签—>
<layout>
<param name="ConversionPattern" value="%d %-4r %-5p (%F:%L) %10c %3x - %m%n"/>
</layout>
<!--filter标签:此处设置的过滤最小级别参数为WARN,最大级别参数为FATAL,
因此,在该日志文件输出的消息为WARN到FATAL级别的消息-->
<filter>
<param name="levelMin" value="WARN"/>
<param name="levelMax" value="FATAL"/>
</filter>
</appender>
<!—==============================================================—>
<!— category节点设置 —>
<!— category节点里边priority定义了相应类别相应级别以上的日 —>
<!— 志往appender传送,同时必须满足appender里边的最小输出级别 —>
<!—==============================================================—>
<category name="org.apache" additivity="true">
<priority value="WARN"/>
</category>
<category name="net.sf.hibernate" additivity="true">
<priority value="WARN"/>
</category>
<category name="com.sun.faces" additivity="true">
<priority value="INFO"/>
</category>
<category name="org.quartz.impl.jdbcjobstore" additivity="true">
<priority value="INFO"/>
</category>
<category name="com.opensymphony.oscache" additivity="true">
<priority value="WARN"/>
</category>
<!—===============================================================================—>
<!— root节点设置 —>
<!—设置接收所有输出的通道,当上面的category节点找不到相应的appender输出级别 —>
<!—设置的情况下,采用root节点里边的设置级别,同时采用的级别满足appender里 —>
<!—设置的最小级别,如此处设置warn,但A1这个appender设置的最小级别为FATAL, —>
<!—则采用的最小级别为FATAL —>
<!—===============================================================================—>
<root>
<priority value="WARN"/>
<!—appender-ref标签:定义日志输出的appender id—>
<appender-ref ref="A1"/>
<appender-ref ref="A2"/>
</root>
</log4j:configuration>

三、配置说明

(1).几个主要节点说明 appender里边filter定义了”levelMin”和”levelMax”,设置了最小和最大输出级别; category里边priority定义了什么级别以上的日志往appender传送,同时必须满足appender里边的最小输出级别; 当不配置category时,以root里边priority定义了什么级别以上的日志往appender传送,同时必须满足appender里边的最小输出级别,未在category范围内的输出日志遵照root里边级别; root里边appender-ref定义的是日志输出有哪些appender。

(2). 输出方式appender一般有5种: log4j提供了以下几种常用的输出目的地: org.apache.log4j.ConsoleAppender,将日志信息输出到控制台 org.apache.log4j.FileAppender,将日志信息输出到一个文件 org.apache.log4j.DailyRollingFileAppender,将日志信息输出到一个,并且每天输出到一个新的日志文件,按照不同的配置可以定义每月一个日志文件,或者每周,每天,每小时,每分钟等输出一个新的日志文件。 org.apache.log4j.RollingFileAppender,将日志信息输出到一个文件,通过指定文件的的尺寸,当文件大小到达指定尺寸的时候会自动把文件改名,如名为example.log的文件会改名为example.log.1,同时产生一个新的example.log文件。如果新的文件再次达到指定尺寸,又会自动把文件改名为example.log.2,同时产生一个example.log文件。依此类推,直到example.log. MaxBackupIndex,MaxBackupIndex的值可在配置文件中定义。 org.apache.log4j.WriterAppender,将日志信息以流格式发送到任意指定的地方。 org.apache.log4j.jdbc.JDBCAppender,通过JDBC把日志信息输出到数据库中。 org.apache.log4j.net.SMTPAppender,将日志信息以邮件的方式发送到指定的邮箱。

(3).appender中Layout标签说明 有时用户希望根据自己的喜好格式化自己的日志输出。Log4j可以在Appender的后面附加Layout来完成这个功能。Layout提供了四种日志输出样式,如根据HTML样式、自由指定样式、包含日志级别与信息的样式和包含日志时间、线程、类别等信息的样式等等。 其语法表示为: org.apache.log4j.HTMLLayout(以HTML表格形式布局), org.apache.log4j.PatternLayout(可以灵活地指定布局模式), org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串), org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息) PatternLayout 中ConversionPattern参数的格式含义如下:

%c 输出日志信息所属的类的全名

%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy-MM-dd HH:mm:ss },输出类似:2002-10-18- 22:10:28 ;比如 %d{HH:mm:ss,SSS} 或 %d{dd MMM yyyy HH:mm:ss,SSS}格式可以参考 java类 SimpleDateFormat,不过按照此类的设置会影响速度。可以选择更快的方式%d{ISO8601},%d{ABSOLUTE}, %d{RELATIVE}.或者使用log4j的ISO8601DateFormat, AbsoluteTimeDateFormat,RelativeTimeDateFormat 和 DateTimeDateFormat 方式。

%f 输出日志信息所属的类的类名

%l 输出日志事件的发生位置,即输出日志信息的语句处于它所在的类的第几行

%m 输出代码中指定的信息,如log(message)中的message

%M 输出日志信息中所发生的方法名。

%n 输出一个回车换行符,Windows平台为“\r\n”,Unix平台为“\n”

%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL。如果是调用debug()输出的,则为DEBUG,依此类推

%r 输出自应用启动到输出该日志信息所耗费的毫秒数

%t 输出产生该日志事件的线程名
(4). 日记记录的优先级priority priority优先级由高到低分为: OFF ,FATAL ,ERROR ,WARN ,INFO ,DEBUG ,ALL。 Log4j建议只使用FATAL ,ERROR ,WARN ,INFO ,DEBUG这五个级别。 这几个级别声明如下: Logger.debug(Object message);//调试信息 Logger.info(Object message);//一般信息 Logger.warn(Object message);//警告信息 Logger.error(Object message);//错误信息 Logger.fatal(Object message);//致命错误信息

本文部分内容来自网上,有侵犯到您权益或发现错误内容请提出,将更正,目油菜保留部分内容得所有权。