Julia 的个人资料美丽日子照片日志列表 工具 帮助

日志


CVS的常用命令

概述:CVS是一个C/S系统,多个开发人员通过一个中心版本控制系统来记录文件版本,从而达到保证文件同步的目的。

       CVS服务器(文件版本库)
     /     |       \
(版 本 同 步)
   /       |         \  
开发者1  开发者2   开发者3

以下是本文主要内容:开发人员可以主要挑选2, 6看就可以了,CVS的管理员则更需要懂的更多一些

  1. CVS环境初始化:CVS环境的搭建                                          管理员
  2. CVS的日常使用:日常开发中最常用的CVS命令,              开发人员      管理员
  3. CVS的分支开发:项目按照不同进度和目标并发进行                         管理员
  4. CVS的用户认证:通过SSH的远程用户认证,安全,简单                      管理员
  5. CVSWEB:CVS的WEB访问界面大大提高代码版本比较的效率                    管理员
  6. CVS TAG:将$Id$加入代码注释中,方便开发过程的跟踪       开发人员
  7. CVS vs VSS: CVS和Virsual SourceSafe的比较

一个系统20%的功能往往能够满足80%的需求,CVS也不例外,以下是CVS最常用的功能,可能用到的还不到它全部命令选项的10%,更多的功能请在实际应用过程中体会,学习过程中应该是用多少,学多少,用到了再学也不迟。


CVS环境初始化
============

环境设置:指定CVS库的路径CVSROOT
tcsh
setenv CVSROOT /path/to/cvsroot
bash
CVSROOT=/path/to/cvsroot ; export CVSROOT

后面还提到远程CVS服务器的设置:
CVSROOT=:ext:$USER@test.server.address#port:/path/to/cvsroot CVS_RSH=ssh; export CVSROOT CVS_RSH

初始化:CVS版本库的初始化。
cvs init

一个项目的首次导入
cvs import -m "write some comments here" project_name vendor_tag release_tag
执行后:会将所有源文件及目录导入到/path/to/cvsroot/project_name目录下
vender_tag: 开发商标记
release_tag: 版本发布标记

项目导出:将代码从CVS库里导出
cvs checkout project_name
cvs 将创建project_name目录,并将最新版本的源代码导出到相应目录中。这个checkout和Virvual SourceSafe中的check out不是一个概念,相对于Virvual SourceSafe的check out是cvs update, check in是cvs commit。

CVS的日常使用  
=============

注意:第一次导出以后,就不是通过cvs checkout来同步文件了,而是要进入刚才cvs checkout project_name导出的project_name目录下进行具体文件的版本同步(添加,修改,删除)操作。

将文件同步到最新的版本:
cvs update
不制定文件名,cvs将同步所有子目录下的文件,也可以制定某个文件名/目录进行同步
cvs update file_name
最好每天开始工作前或将自己的工作导入到CVS库里前都要做一次,并养成“先同步 后修改”的习惯,和Virvual SourceSafe不同,CVS里没有文件锁定的概念,所有的冲突是在commit之前解决,如果你修改过程中,有其他人修改并commit到了CVS库中,CVS会通知你文件冲突,并自动将冲突部分用
>>>>>>
content on cvs server
<<<<<<
content in your file
>>>>>>
标记出来,由你确认冲突内容的取舍。
版本冲突一般是在多个人修改一个文件造成的,但这种项目管理上的问题不应该指望由CVS来解决。

确认修改写入到CVS库里:
cvs commit -m "write some comments here" file_name

注意:CVS的很多动作都是通过cvs commit进行最后确认并修改的,最好每次只修改一个文件。在确认的前,还需要用户填写修改注释,以帮助其他开发人员了解修改的原因。如果不用写-m "comments"而直接确认`cvs commit file_name` 的话,cvs会自动调用系统缺省的文字编辑器(一般是vi)要求你写入注释。
注释的质量很重要:所以不仅必须要写,而且必须写一些比较有意义的内容:以方便其他开发人员能够很好的理解
不好的注释,很难让其他的开发人员快速的理解:比如: -m "bug fixed" 甚至 -m ""
好的注释,甚至可以用中文: -m "在用户注册过程中加入了Email地址校验"


修改某个版本注释:每次只确认一个文件到CVS库里是一个很好的习惯,但难免有时候忘了指定文件名,把多个文件以同样注释commit到CVS库里了,以下命令可以允许你修改某个文件某个版本的注释:
cvs admin -m 1.3:"write some comments here" file_name

添加文件
创建好新文件后,比如:touch new_file
cvs add new_file
注意:对于图片,Word文档等非纯文本的项目,需要使用cvs add -b选项,否则有可能出现文件被破坏的情况
比如:cvs add -kb new_file.gif
然后确认修改并注释
cvs ci -m "write some comments here"

删除文件:
将某个源文件物理删除后,比如:rm file_name
cvs rm file_name
然后确认修改并注释
cvs ci -m "write some comments here"
以上面前2步合并的方法为:
cvs rm -f file_name
cvs ci -m "why delete file"

注意:很多cvs命令都有缩写形式:commit=>ci; update=>up; checkout=>co; remove=>rm;


添加目录:
cvs add dir_name

查看修改历史:cvs log file_name
cvs history file_name

查看当前文件不同版本的区别
cvs diff -r1.3 -r1.5 file_name
查看当前文件(可能已经修改了)和库中相应文件的区别
cvs diff file_name
cvs的web界面提供了更方便的定位文件修改和比较版本区别的方法,具体安装设置请看后面的cvsweb使用

正确的通过CVS恢复旧版本的方法:
如果用cvs update -r1.2 file.name
这个命令是给file.name加一个STICK TAG: "1.2" ,虽然你的本意只是想将它恢复到1.2版本
正确的恢复版本的方法是:cvs update -p -r1.2 file_name >file_name
如果不小心已经加成STICK TAG的话:用cvs update -A 解决

移动文件:文件重命名
cvs里没有cvs move或cvs rename,因为这两个操作是先cvs remove old_file_name,然后cvs add new_file_name实现的。

删除,移动目录:
最方便的方法是让管理员直接移动,删除CVSROOT里相应目录(因为CVS一个项目下的子目录都是独立的,移动到$CVSROOT目录下都可以作为新的独立项目:好比一颗树,其实砍下任意一枝都能独立存活),对目录进行了修改后,要求其开发人员重新导出项目cvs checkout project_name 或者用cvs update -dP同步。

CVS Branch:项目多分支同步开发
=============================

确认版本里程碑:多个文件各自版本号不一样,项目到一定阶段,可以给所有文件统一指定一个阶段里程碑版本号,方便以后按照这个阶段里程碑版本号导出项目,同时也是项目的多个分支开发的基础。
cvs tag release_1_0

开始一个新的里程碑:
cvs commit -r 2 标记所有文件开始进入2.x的开发

注意:CVS里的revsion和软件包的发布版本可以没有直接的关系。但所有文件使用和发布版本一致的版本号比较有助于维护。

在开发项目的2.x版本的时候发现1.x有问题,但2.x又不敢用,则从先前标记的里程碑:release_1_0导出一个分支release_1_0_patch
cvs rtag -b -r release_1_0 release_1_0_patch proj_dir

一些人先在另外一个目录下导出release_1_0_patch这个分支:解决1.0中的紧急问题,
cvs checkout -r release_1_0_patch
而其他人员仍旧在项目的主干分支2.x上开发

在release_1_0_patch上修正错误后,标记一个1.0的错误修正版本号
cvs tag release_1_0_patch_1

如果2.0认为这些错误修改在2.0里也需要,也可以在2.0的开发目录下合并release_1_0_patch_1中的修改到当前代码中:
cvs update -j release_1_0_patch_1

CVS的远程认证:通过SSH远程访问CVS
================================

使用cvs本身的远程认证很麻烦,需要定义服务器和用户组,用户名,设置密码等,而且不安全,因此和系统本地帐号认证并通过SSH传输是比较好的办法,通过在客户机的/etc/profile里设置一下内容:
CVSROOT=:ext:$USER@test.server.address#port:/path/to/cvsroot CVS_RSH=ssh; export CVSROOT CVS_RSH
所有客户机所有本地用户都可以映射到CVS服务器相应同名帐号了。

如果CVS所在服务器的SSH端口不在缺省的22,或者和客户端与CVS服务器端SSH缺省端口不一致,有时候设置了:
:ext:$USER@test.server.address#port:/path/to/cvsroot 

仍然不行,比如有以下错误信息:
ssh: test.server.address#port: Name or service not known
cvs [checkout aborted]: end of file from server (consult above messages if any)

解决的方法是做一个脚本指定端口转向(不能使用alias,会出找不到文件错误):
创建一个/usr/bin/ssh_cvs文件:
#!/usr/bin/sh
/path/to/ssh -p 34567 "$@"
然后:chmod +x /usr/bin/ssh_cvs
并CVS_RSH=ssh_cvs; export CVS_RSH

注意:port是指相应服务器SSH的端口,不是cvs pserver的端口

CVSWEB:提高程序员比较文件修改效率
================================

CVSWEB就是CVS的WEB界面,可以大大提高程序员定位修改的效率:
使用的样例可以看:http://www.freebsd.org/cgi/cvsweb.cgi

CVSWEB的下载:CVSWEB从最初的版本已经演化出很多功能界面更丰富的版本,这个是个人感觉觉得安装设置比较方便的:
http://www.spaghetti-code.de/software/linux/cvsweb/

下载解包:
tar zxf cvsweb.tgz
把配置文件cvsweb.conf放到安全的地方(比如和apache的配置放在同一个目录下),
修改:cvsweb.cgi让CGI找到配置文件:
$config = $ENV{'CVSWEB_CONFIG'} || '/path/to/apache/conf/cvsweb.conf';

转到/path/to/apache/conf下并修改cvsweb.conf:

  1. 修改CVSROOT路径设置:
    %CVSROOT = (
    'Development' => '/path/to/cvsroot', #<==修改指向本地的CVSROOT
    );
  2. 缺省不显示已经删除的文档:
    "hideattic" => "1",#<==缺省不显示已经删除的文档
  3. 在配置文件cvsweb.conf中还可以定制页头的描述信息,你可以修改$long_intro成你需要的文字

CVSWEB可不能随便开放给所有用户,因此需要使用WEB用户认证:
先生成 passwd:
/path/to/apache/bin/htpasswd -c cvsweb.passwd user

修改httpd.conf: 增加
<Directory "/path/to/apache/cgi-bin/cvsweb/">
AuthName "CVS Authorization"
AuthType Basic
AuthUserFile /path/to/cvsweb.passwd
require valid-user
</Directory>

CVS TAGS: who? when?
====================

将$Id$ 加在程序文件开头的注释里是一个很好的习惯,cvs能够自动解释更新其中的内容成:file_name version time user_name 的格式,比如:cvs_card.txt,v 1.1 2002/04/05 04:24:12 chedong Exp,可以这些信息了解文件的最后修改人和修改时间

几个常用的缺省文件:
default.php
<?php
/*
* Copyright (c) 2002 Company Name.
* $Header$
*/

?>

====================================
Default.java: 注意文件头一般注释用 /* 开始 JAVADOC注释用 /** 开始的区别
/*
* Copyright (c) 2002 Company Name.
* $Header$
*/

package com.netease;

import java.io;

/**
* comments here
*/
public class Default {
    /**
    *
    * @param
    * @return
    */
    public toString() {

    }
}

====================================
default.pl:
#!/usr/bin/perl -w
# Copyright (c) 2002 Company Name.
# $Header$

# file comments here

use strict;

CVS vs VSS 
===========

CVS没有文件锁定模式,VSS在check out同时,同时记录了文件被导出者锁定。

CVS是update commit, VSS是check out check in

在CVS中,标记自动更新功能缺省是打开的,这样也带来一个潜在的问题,就是不用-kb方式添加binary文件的话在cvs自动更新时可能会导致文件失效。

Virsual SourceSafe中这个功能称之为Keyword Explaination,缺省是关闭的,需要通过OPITION打开,并指定需要进行源文件关键词扫描的类型:*.txt,*.java,*.html...

对于Virsual SourceSafe和CVS都通用的TAG有:
$Header$
$Author$
$Date$
$Revision$

尽量使用通用的关键词保证代码在CVS和VSS都能方便的跟踪。

 

相关资源:

CVS HOME:
http://www.cvshome.org

CVS FAQ:
http://www.loria.fr/~molli/cvs-index.html

相关网站:
http://directory.google.com/Top/Computers/Software/Configuration_Management/Tools/Concurrent_Versions_System/

CVS 免费书:
http://cvsbook.red-bean.com/

CVS 命令的速查卡片:
http://www.refcards.com/about/cvs.html

PowerDesigner教程五 概念数据模型

目标:
本文主要介绍数据项、新增数据项、数据项的唯一性代码选项和重用选项等。

一、数据项
数据项(Data Item)是信息存储的最小单位,它可以附加在实体上作为实体的属性。
注意:模型中允许存在没有附加至任何实体上的数据项。

二、新建数据项
1)使用“Model”---> Data Items 菜单,在打开的窗口中显示已有的数据项的列表,点击 “Add a Row”按钮,创建一个新数据项,如图所示


2)当然您可以继续设置具体数据项的Code、DataType、Length等等信息。这里就不再详细说明了。

三、数据项的唯一性代码选项和重用选项
使用Tools--->Model Options->Model Settings。在Data Item组框中定义数据项的唯一性代码选项(Unique Code)与重用选项(Allow Reuse)。
注意:
如果选择Unique Code复选框 ,每个数据项在同一个命名空间有唯一的代码,而选择Allow reuse ,一个数据项可以充当多个实体的属性。


四、在实体中添加数据项
1)双击一个实体符号,打开该实体的属性窗口。
2)单击Attributes选项卡,打开如下图所示窗口


注意:
Add a DataItem 与 Reuse a DataItem的区别在于
Add a DataItem 情况下,选择一个已经存在的数据项,系统会自动复制所选择的数据项。如果您设置了UniqueCode选项,那系统在复制过程中,新数据项的Code会自动生成一个唯一的号码,否则与所选择的数据项完全一致。


Reuse a DataItem情况下,只引用不新增,就是引用那些已经存在的数据项,作为新实体的数据项。

PowerDesigner教程四 概念数据模型

目标:
本文主要介绍如何定义实体的主、次标识符。

一、标识符
标识符是实体中一个或多个属性的集合,可用来唯一标识实体中的一个实例。要强调的是,CDM中的标识符等价于PDM中的主键或候选键。
每个实体都必须至少有一个标识符。如果实体只有一个标识符,则它为实体的主标识符。如果实体有多个标识符,则其中一个被指定为主标识符,其余的标识符就是次标识符了。

二、如果定义主、次标识符
1)选择某个实体双击弹出实体的属性对话框。在Identifiers选项卡上可以进行实体标识符的定义。如下图所示



2)选择第一行“主标识符”,点击属性按钮或双击第一行“主标识符”,弹出属性对话框,如图所示

3)选择"Attributes"选项卡,再点击“Add Attributes”工具,弹出如图所示窗口,选择某个属性作为标识符就行了。

PowerDesigner教程三 概念数据模型

目标:
本文主要介绍属性的标准检查约束、如何定义属性的附加检查。

一、定义属性的标准检查约束
标准检查约束是一组确保属性有效的表达式。在实体属性的特性窗口,打开如图所示的检查选项卡。


在这个选项卡可以定义属性的标准检查约束,窗口中每项的参数的含义,如下
参数 说明
Minimum 属性可接受的最小数
Maximum  属性可接受的最大数
Default 属性不赋值时,系统提供的默认值
Unit 单位,如公里、吨、元
Format 属性的数据显示格式
Lowercase 属性的赋值全部变为小写字母
Uppercase 属性的赋值全部变为大写字母
Cannot modify 该属性一旦赋值不能再修改
List Of Values 属性赋值列表,除列表中的值,不能有其他的值
Label 属性列表值的标签

二、定义属性的附加检查
当Standard checks 或Rules 不能满足检查的要求时,可以在Additional Checks选项卡的Server子页上,通过SQL语句中使用%MINMAX%、%LISTVAL%、%RULES%、%UPPER%、%LOWER% 几个变量来定义Standard和Rule,如图所示


%MINMAX%、%LISTVAL%、%UPPER%、%LOWER%
在Standard Check中定义的Minimum 和Maximum、List values 、uppervalues、lowervalues

%RULES%
在Rules特性窗口Expression选项卡中定义的有效性规则表达式

PowerDesigner教程二 概念数据模型

目标:
本文主要介绍PowerDesigner概念数据模型以及实体、属性创建。

一、新建概念数据模型
1)选择File-->New,弹出如图所示对话框,选择CDM模型(即概念数据模型)建立模型。


2)完成概念数据模型的创建。以下图示,对当前的工作空间进行简单介绍。(以后再更详细说明)


3)选择新增的CDM模型,右击,在弹出的菜单中选择“Properties”属性项,弹出如图所示对话框。在“General”标签里可以输入所建模型的名称、代码、描述、创建者、版本以及默认的图表等等信息。在“Notes”标签里可以输入相关描述及说明信息。当然再有更多的标签,可以点击 "More>>"按钮,这里就不再进行详细解释。


二、创建新实体
1)在CDM的图形窗口中,单击工具选项版上的Entity工具,再单击图形窗口的空白处,在单击的位置就出现一个实体符号。点击Pointer工具或右击鼠标,释放Entitiy工具。如图所示

2)双击刚创建的实体符号,打开下列图标窗口,在此窗口“General”标签中可以输入实体的名称、代码、描述等信息。


三、添加实体属性
1)在上述窗口的“Attribute”选项标签上可以添加属性,如下图所示。


注意:
数据项中的“添加属性”和“重用已有数据项”这两项功能与模型中Data Item的Unique code 和Allow reuse选项有关。
P列表示该属性是否为主标识符;D列表示该属性是否在图形窗口中显示;M列表示该属性是否为强制的,即该列是否为空值。

如果一个实体属性为强制的,那么, 这个属性在每条记录中都必须被赋值,不能为空。

2)在上图所示窗口中,点击插入属性按钮,弹出属性对话框,如下图所示。

注意:这里涉及到域的概念,即一种标准的数据结构,它可应用至数据项或实体的属性上。在以下的教程中将另立章节详细说明。

PowerDesigner教程一 概念数据模型

一、概念数据模型概述
数据模型是现实世界中数据特征的抽象。数据模型应该满足三个方面的要求:
1)能够比较真实地模拟现实世界
2)容易为人所理解
3)便于计算机实现

概念数据模型也称信息模型,它以实体-联系(Entity-RelationShip,简称E-R)理论为基础,并对这一理论进行了扩充。它从用户的观点出发对信息进行建模,主要用于数据库的概念级设计。


通常人们先将现实世界抽象为概念世界,然后再将概念世界转为机器世界。换句话说,就是先将现实世界中的客观对象抽象为实体(Entity)和联系 (Relationship),它并不依赖于具体的计算机系统或某个DBMS系统,这种模型就是我们所说的CDM;然后再将CDM转换为计算机上某个 DBMS所支持的数据模型,这样的模型就是物理数据模型,即PDM。

CDM是一组严格定义的模型元素的集合,这些模型元素精确地描述了系统的静态特性、动态特性以及完整性约束条件等,其中包括了数据结构、数据操作和完整性约束三部分。
1)数据结构表达为实体和属性;
2)数据操作表达为实体中的记录的插入、删除、修改、查询等操作;
3)完整性约束表达为数据的自身完整性约束(如数据类型、检查、规则等)和数据间的参照完整性约束(如联系、继承联系等);

二、实体、属性及标识符的定义
实体(Entity),也称为实例,对应现实世界中可区别于其他对象的“事件”或“事物”。例如,学校中的每个学生,医院中的每个手术。
每个实体都有用来描述实体特征的一组性质,称之为属性,一个实体由若干个属性来描述。如学生实体可由学号、姓名、性别、出生年月、所在系别、入学年份等属性组成。

实体集(Entity Set)是具体相同类型及相同性质实体的集合。例如学校所有学生的集合可定义为“学生”实体集,“学生”实体集中的每个实体均具有学号、姓名、性别、出生年月、所在系别、入学年份等性质。

实体类型(Entity Type)是实体集中每个实体所具有的共同性质的集合,例如“患者”实体类型为:患者{门诊号,姓名,性别,年龄,身份证号.............}。实体是实体类型的一个实例,在含义明确的情况下,实体、实体类型通常互换使用。

实体类型中的每个实体包含唯一标识它的一个或一组属性,这些属性称为实体类型的标识符(Identifier),如“学号”是学生实体类型的标识符,“姓名”、“出生日期”、“信址”共同组成“公民”实体类型的标识符。

有些实体类型可以有几组属性充当标识符,选定其中一组属性作为实体类型的主标识符,其他的作为次标识符。
三、实体、属性及标识符的表达


 
 
 

mysql中一些常用的操作

1.添加管理员:
grant all privileges on *.* to root@IP identified by ‘密码’;
flush privileges;  ///刷新数据库

2.查看环境变量
show variables

3.显示所有数据库和库里的所有表
show databases
show tables

4.数据库复制相关master/slave
show master status
show slave status
load data from master (从master同步数据,慎用,执行时master数据库会被锁住)
slave start
slave stop
flash logs(截断日志)

5.显示当前操作
show processlist

6 备份和恢复
/usr/local/mysql/bin/mysqldump -uroot -p linux > /root/linux.sql  备份
/usr/local/mysql/bin/mysql -uroot -p linux < /home/beinan/linuxsir031130.sql

如果要备份某个数据库中某个表为

/usr/local/mysql/bin/mysqldump -uroot -p linux table > /root/linux.sql

7 查找某个表

show tables like '%table%';

8 显示创建某个表的语句

show create table table_name; 

9 导入本地文件到pet数据库中

LOAD DATA INFILE '/work/document/database/pet.txt' INTO TABLE pet;
导入pet.txt到pet表中,pet.txt各字段用tab分割

10 清空表中数据保留字段truncate pet;

11 其他

 select name,birth,curdate(), (year (curdate())-year(birth))-(right(curdate(),5)<right(birth,5)) as age from pet;
此处,YEAR()提取日期的年部分,RIGHT()提取日期的MM-DD (日历年)部分的最右面5个字符。比
较MM-DD值的表达式部分的值一般为1或0,如果CURDATE()的年比birth的年早,则年份应减去1。
整个表达式有些难懂,使用alias (age)来使输出的列标记更有意义。

select name,birth from pet where month(birth) = month(date_add(curdate(),interval 1 month));
找出下个月生日的动物

select * from menagerie.pet where name like '%fy';
查找menagerie数据库中pet表中name以fy结尾的

update pet set birth='1989-08-31' where name='Bowser';
更新

create table pet (name VARCHAR(20),owner VARCHAR(20), species VARCHAR(20),sex CHAR(1),birth DATE,death DATE);
创建表

select version();
查询数据库当前版本

select name,species,birth from pet order by species,birth desc;
排序(desc降序,默认升序)

select * from pet where (species='cat' and sex='m') or (species='dog' and sex='f');
查询

show variables like "have_%";
show grants for root@'localhost';
查看root权限
select id from information_schema.processlist where user= '你的用户名';
查看用户名名下所有进程ID
SHOW TABLE STATUS FROM test LIKE 'customers';
显示customers表的状态。显示引擎

设计自己的Annotation入门与实践

第一部分:了解一下java1.5起默认的三个annotation类型:
一个是@Override:只能用在方法之上的,用来告诉别人这一个方法是改写父类的。
一个是@Deprecated:建议别人不要使用旧的API的时候用的,编译的时候会用产生警告信息,可以设定在程序里的所有的元素上.
一个是@SuppressWarnings:这一个类型可以来暂时把一些警告信息消息关闭.
如果不清楚上面三个类型的具体用法,各位可以baidu或google一下的,很简单的。

第二部分:讲一下annotation的概念先,再来讲一下怎样设计自己的annotation.
首先在jdk自带的java.lang.annotation包里,打开如下几个源文件:

1、源文件Target.java
Java代码 复制代码
  1. @Documented  
  2. @Retention(RetentionPolicy.RUNTIME)  
  3. @Target(ElementType.ANNOTATION_TYPE)  
  4. public @interface Target {  
  5.    ElementType[] value();  
  6. }  
   @Documented
   @Retention(RetentionPolicy.RUNTIME)
   @Target(ElementType.ANNOTATION_TYPE)
   public @interface Target {
      ElementType[] value();
   }


其中的@interface是一个关键字,在设计annotations的时候必须把一个类型定义为@interface,而不能用class或interface关键字(会不会觉得sun有点吝啬,偏偏搞得与interface这么像).

2、源文件Retention.java
Java代码 复制代码
  1. @Documented  
  2. @Retention(RetentionPolicy.RUNTIME)  
  3. @Target(ElementType.ANNOTATION_TYPE)  
  4. public @interface Retention {  
  5.    RetentionPolicy value();  
  6. }  
   @Documented
   @Retention(RetentionPolicy.RUNTIME)
   @Target(ElementType.ANNOTATION_TYPE)
   public @interface Retention {
      RetentionPolicy value();
   }


看到这里,大家可能都模糊了,都不知道在说什么,别急,往下看一下.
在上面的文件都用到了RetentionPolicy,ElementType这两个字段,你可能就会猜到这是两个java文件.的确,这两个文件的源代码如下:

3、源文件RetentionPolicy.java
Java代码 复制代码
  1. public enum RetentionPolicy {  
  2.  SOURCE,  
  3.  CLASS,  
  4.  RUNTIME  
  5. }  
    public enum RetentionPolicy {
     SOURCE,
     CLASS,
     RUNTIME
    }

这是一个enum类型,共有三个值,分别是SOURCE,CLASS 和 RUNTIME.
SOURCE代表的是这个Annotation类型的信息只会保留在程序源码里,源码如果经过了编译之后,Annotation的数据就会消失,并不会保留在编译好的.class文件里面。
ClASS的意思是这个Annotation类型的信息保留在程序源码里,同时也会保留在编译好的.class文件里面,在执行的时候,并不会把这一些信息加载到虚拟机(JVM)中去.注意一下,当你没有设定一个Annotation类型的Retention值时,系统默认值是CLASS.
第三个,是RUNTIME,表示在源码、编译好的.class文件中保留信息,在执行的时候会把这一些信息加载到JVM中去的.
 举一个例子,如@Override里面的Retention设为SOURCE,编译成功了就不要这一些检查的信息;相反,@Deprecated里面的 Retention设为RUNTIME,表示除了在编译时会警告我们使用了哪个被Deprecated的方法,在执行的时候也可以查出该方法是否被 Deprecated.


4、源文件ElementType.java
Java代码 复制代码
  1. public enum ElementType {  
  2.  TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR,  
  3.  LOCAL_VARIABLE, ANNOTATION_TYPE,PACKAGE  
  4. }  
   public enum ElementType {
    TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR,
    LOCAL_VARIABLE, ANNOTATION_TYPE,PACKAGE
   }

@Target里面的ElementType是用来指定Annotation类型可以用在哪一些元素上的.说明一下:TYPE(类型), FIELD(属性), METHOD(方法), PARAMETER(参数), CONSTRUCTOR(构造函数),LOCAL_VARIABLE(局部变量), ANNOTATION_TYPE,PACKAGE(包),其中的TYPE(类型)是指可以用在Class,Interface,Enum和 Annotation类型上.
另外,从1的源代码可以看出,@Target自己也用了自己来声明自己,只能用在ANNOTATION_TYPE之上.
如果一个Annotation类型没有指明@Target使用在哪些元素上,那么它可以使用在任何元素之上,这里的元素指的是上面的八种类型.
举几个正确的例子:
@Target(ElementType.METHOD)
@Target(value=ElementType.METHOD)
@Target(ElementType.METHOD,ElementType.CONSTRUCTOR)
具体参考一下javadoc文档

上面一下1和2的源文件,它们都使用了@Documented,@Documented的目的就是让这一个Annotation类型的信息能够显示在javaAPI说明文档上;没有添加的话,使用javadoc生成API文档的时候就会找不到这一个类型生成的信息.
另外一点,如果需要把Annotation的数据继承给子类,那么就会用到@Inherited这一个Annotation类型.

第三部分:下面讲的设计一个最简单的Annotation例子,这一例子共用四个文件;
1、Description.java
Java代码
  1. package lighter.javaeye.com;  
  2.   
  3. import java.lang.annotation.Documented;  
  4. import java.lang.annotation.ElementType;  
  5. import java.lang.annotation.Retention;  
  6. import java.lang.annotation.RetentionPolicy;  
  7. import java.lang.annotation.Target;  
  8.   
  9. @Target(ElementType.TYPE)  
  10. @Retention(RetentionPolicy.RUNTIME)  
  11. @Documented  
  12. public @interface Description {  
  13.     String value();  
  14. }  
   package lighter.javaeye.com;

   import java.lang.annotation.Documented;
   import java.lang.annotation.ElementType;
   import java.lang.annotation.Retention;
   import java.lang.annotation.RetentionPolicy;
   import java.lang.annotation.Target;

   @Target(ElementType.TYPE)
   @Retention(RetentionPolicy.RUNTIME)
   @Documented
   public @interface Description {
       String value();
   }

说明:所有的Annotation会自动继承java.lang.annotation这一个接口,所以不能再去继承别的类或是接口.
最重要的一点,Annotation类型里面的参数该怎么设定:
第一,只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型.
第二,参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和 String,Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,String value();这里的参数成员就为String.
第三,如果只有一个参数成员,最好把参数名称设为"value",后加小括号.例:上面的例子就只有一个参数成员.

2、Name.java
Java代码
  1. package lighter.javaeye.com;  
  2.   
  3. import java.lang.annotation.Documented;  
  4. import java.lang.annotation.ElementType;  
  5. import java.lang.annotation.Retention;  
  6. import java.lang.annotation.RetentionPolicy;  
  7. import java.lang.annotation.Target;  
  8.   
  9.  //注意这里的@Target与@Description里的不同,参数成员也不同  
  10. @Target(ElementType.METHOD)  
  11. @Retention(RetentionPolicy.RUNTIME)  
  12. @Documented  
  13. public @interface Name {  
  14.     String originate();  
  15.     String community();  
  16. }  
   package lighter.javaeye.com;

   import java.lang.annotation.Documented;
   import java.lang.annotation.ElementType;
   import java.lang.annotation.Retention;
   import java.lang.annotation.RetentionPolicy;
   import java.lang.annotation.Target;

    //注意这里的@Target与@Description里的不同,参数成员也不同
   @Target(ElementType.METHOD)
   @Retention(RetentionPolicy.RUNTIME)
   @Documented
   public @interface Name {
       String originate();
       String community();
   }


3、JavaEyer.java
Java代码
  1. package lighter.javaeye.com;  
  2.   
  3. @Description("javaeye,做最棒的软件开发交流社区")  
  4. public class JavaEyer {  
  5.     @Name(originate="创始人:robbin",community="javaEye")  
  6.     public String getName()  
  7.     {  
  8.         return null;  
  9.     }  
  10.       
  11.     @Name(originate="创始人:江南白衣",community="springside")  
  12.     public String getName2()  
  13.     {  
  14.         return "借用两位的id一用,写这一个例子,请见谅!";  
  15.     }  
  16. }  
package lighter.javaeye.com;

@Description("javaeye,做最棒的软件开发交流社区")
public class JavaEyer {
	@Name(originate="创始人:robbin",community="javaEye")
	public String getName()
	{
		return null;
	}
	
	@Name(originate="创始人:江南白衣",community="springside")
	public String getName2()
	{
		return "借用两位的id一用,写这一个例子,请见谅!";
	}
}

4、最后,写一个可以运行提取JavaEyer信息的类TestAnnotation
Java代码
  1.  package lighter.javaeye.com;  
  2.   
  3.   import java.lang.reflect.Method;  
  4.   import java.util.HashSet;  
  5.   import java.util.Set;  
  6.   
  7.   public class TestAnnotation {  
  8.     /** 
  9.      * author lighter 
  10.      * 说明:具体关天Annotation的API的用法请参见javaDoc文档 
  11.      */  
  12.        public static void main(String[] args) throws Exception {  
  13.        String  CLASS_NAME = "lighter.javaeye.com.JavaEyer";  
  14.        Class  test = Class.forName(CLASS_NAME);  
  15.        Method[] method = test.getMethods();  
  16.        boolean flag = test.isAnnotationPresent(Description.class);  
  17.         if(flag)  
  18.         {  
  19.             Description des = (Description)test.getAnnotation(Description.class);  
  20.             System.out.println("描述:"+des.value());  
  21.             System.out.println("-----------------");  
  22.         }  
  23.           
  24.         //把JavaEyer这一类有利用到@Name的全部方法保存到Set中去  
  25.         Set<Method> set = new HashSet<Method>();  
  26.         for(int i=0;i<method.length;i++)  
  27.         {  
  28.             boolean otherFlag = method[i].isAnnotationPresent(Name.class);  
  29.             if(otherFlag) set.add(method[i]);  
  30.         }  
  31.         for(Method m: set)  
  32.         {  
  33.             Name name = m.getAnnotation(Name.class);  
  34.             System.out.println(name.originate());  
  35.             System.out.println("创建的社区:"+name.community());  
  36.         }  
  37.      }  
  38. }  
 package lighter.javaeye.com;

  import java.lang.reflect.Method;
  import java.util.HashSet;
  import java.util.Set;

  public class TestAnnotation {
	/**
	 * author lighter
	 * 说明:具体关天Annotation的API的用法请参见javaDoc文档
	 */
       public static void main(String[] args) throws Exception {
       String  CLASS_NAME = "lighter.javaeye.com.JavaEyer";
       Class  test = Class.forName(CLASS_NAME);
       Method[] method = test.getMethods();
       boolean flag = test.isAnnotationPresent(Description.class);
        if(flag)
        {
        	Description des = (Description)test.getAnnotation(Description.class);
        	System.out.println("描述:"+des.value());
        	System.out.println("-----------------");
        }
        
        //把JavaEyer这一类有利用到@Name的全部方法保存到Set中去
        Set<Method> set = new HashSet<Method>();
        for(int i=0;i<method.length;i++)
        {
        	boolean otherFlag = method[i].isAnnotationPresent(Name.class);
        	if(otherFlag) set.add(method[i]);
        }
        for(Method m: set)
        {
        	Name name = m.getAnnotation(Name.class);
        	System.out.println(name.originate());
        	System.out.println("创建的社区:"+name.community());
        }
     }
}

5、运行结果:
描述:javaeye,做最棒的软件开发交流社区
-----------------
创始人:robbin
创建的社区:javaEye
创始人:江南白衣
创建的社区:springside
 
 
 
后续
如何控制一个annotation里的某些属性可以填可以不填,难道都是必填?
不是必填的,我举一个例子,可以更清楚一些,在把上面的Name.java改为
java 代码
  1. @Target(ElementType.METHOD)          
  2. @Retention(RetentionPolicy.RUNTIME)          
  3. @Documented         
  4. public @interface Name {          
  5.   String originate();          
  6.   String community();          
  7.   public enum CommunityNumber(LITTLE,ORDINARY,WELL)       
  8.   CommunityNumber  number()  default  CommunityNumber.WELL;       
  9. }   
    这里的default是这一个关键字,指定默认值.(在上面文章上没有说明)
    所以你可以在JavaEyer类上的方法指定用
    @Name(originate="创始人:robbin",community="javaEye")或
    @Name(originate="创始人:robbin",community="javaEye",number=Name.CommunityNumber.WELL)均可
    这里的number的属性就不是必填的
    另外,在enum CommunityNumber中,不一定非得要enum类型,用其他的合法类型也可,这里只是举一个例子而已

build.xml-ANT文件详解

Ant的概念
可能有些读者并不连接什么是Ant以及入可使用它,但只要使用通过Linux系统得读者,应该知道

make这个命令。当编译Linux内核及一些软件的源程序时,经常要用这个命令。Make命令其实就

是一个项目管理工具,而Ant所实现功能与此类似。像make,gnumake和nmake这些编译工具都有

一定的缺陷,但是Ant却克服了这些工具的缺陷。最初Ant开发者在开发跨平台的应用时,用样也

是基于这些缺陷对Ant做了更好的设计。

Ant 与 makefile
Makefile有一些不足之处,比如很多人都会碰到的烦人的Tab问题。最初的Ant开发者多次强调”

只是我在Tab前面加了一个空格,所以我的命令就不能执行”。有一些工具在一定程度上解决了

这个问题,但还是有很多其他的问题。Ant则与一般基于命令的工具有所不同,它是Java类的扩

展。Ant运行需要的XML格式的文件不是Shell命令文件。它是由一个Project组成的,而一个

Project又可分成可多target,target再细分又分成很多task,每一个task都是通过一个实现特

定接口的java类来完成的。

Ant的优点

Ant是Apache软件基金会JAKARTA目录中的一个子项目,它有以下的优点。
跨平台性。Ant是存Java语言编写的,所示具有很好的跨平台性。
操作简单。Ant是由一个内置任务和可选任务组成的。Ant运行时需要一个XML文件(构建文件)。

Ant通过调用target树,就可以执行各种task。每个task实现了特定接口对象。由于Ant构建文件

时XML格式的文件,所以和容易维护和书写,而且结构很清晰。
Ant可以集成到开发环境中。由于Ant的跨平台性和操作简单的特点,它很容易集成到一些开发环

境中去。

Ant 开发

Ant的构建文件
当开始一个新的项目时,首先应该编写Ant构建文件。构建文件定义了构建过程,并被团队开发

中每个人使用。Ant构建文件默认命名为build.xml,也可以取其他的名字。只不过在运行的时候

把这个命名当作参数传给Ant。构建文件可以放在任何的位置。一般做法是放在项目顶层目录中

,这样可以保持项目的简洁和清晰。下面是一个典型的项目层次结构。
(1) src存放文件。
(2) class存放编译后的文件。
(3) lib存放第三方JAR包。
(4) dist存放打包,发布以后的代码。
Ant构建文件是XML文件。每个构建文件定义一个唯一的项目(Project元素)。每个项目下可以定

义很多目标(target元素),这些目标之间可以有依赖关系。当执行这类目标时,需要执行他们所

依赖的目标。
每个目标中可以定义多个任务,目标中还定义了所要执行的任务序列。Ant在构建目标时必须调

用所定义的任务。任务定义了Ant实际执行的命令。Ant中的任务可以为3类。
(1) 核心任务。核心任务是Ant自带的任务。
(2) 可选任务。可选任务实来自第三方的任务,因此需要一个附加的JAR文件。
(3) 用户自定义的任务。用户自定义的任务实用户自己开发的任务。
1.<project>标签
  每个构建文件对应一个项目。<project>标签时构建文件的根标签。它可以有多个内在属性,

就如代码中所示,其各个属性的含义分别如下。
(1) default表示默认的运行目标,这个属性是必须的。
(2) basedir表示项目的基准目录。
(3) name表示项目名。
(4) description表示项目的描述。
每个构建文件都对应于一个项目,但是大型项目经常包含大量的子项目,每一个子项目都可以有

自己的构建文件。

2.<target>标签
一个项目标签下可以有一个或多个target标签。一个target标签可以依赖其他的target标签。例

如,有一个target用于编译程序,另一个target用于声称可执行文件。在生成可执行文件之前必

须先编译该文件,因策可执行文件的target依赖于编译程序的target。Target的所有属性如下。
(1).name表示标明,这个属性是必须的。
(2).depends表示依赖的目标。
(3)if表示仅当属性设置时才执行。
(4)unless表示当属性没有设置时才执行。
(5)description表示项目的描述。
Ant的depends属性指定了target的执行顺序。Ant会依照depends属性中target出现顺序依次执行

每个target。在执行之前,首先需要执行它所依赖的target。程序中的名为run的target的

depends属性compile,而名为compile的target的depends属性是prepare,所以这几个target执

行的顺序是prepare->compile->run。
一个target只能被执行一次,即使有多个target依赖于它。如果没有if或unless属性,target总

会被执行。

3.<mkdir>标签
该标签用于创建一个目录,它有一个属性dir用来指定所创建的目录名,其代码如下:
<mkdir dir=”${class.root}”/>
通过以上代码就创建了一个目录,这个目录已经被前面的property标签所指定。

4<jar>标签
该标签用来生成一个JAR文件,其属性如下。
(1) destfile表示JAR文件名。
(2) basedir表示被归档的文件名。
(3) includes表示别归档的文件模式。
(4) exchudes表示被排除的文件模式。

5.<javac标签>
该标签用于编译一个或一组java文件,其属性如下。
(1).srcdir表示源程序的目录。
(2).destdir表示class文件的输出目录。
(3).include表示被编译的文件的模式。
(4).excludes表示被排除的文件的模式。
(5).classpath表示所使用的类路径。
(6).debug表示包含的调试信息。
(7).optimize表示是否使用优化。
(8).verbose 表示提供详细的输出信息。
(9).fileonerror表示当碰到错误就自动停止。

6.<java>标签
该标签用来执行编译生成的.class文件,其属性如下。
(1).classname 表示将执行的类名。
(2).jar表示包含该类的JAR文件名。
(3).classpath所表示用到的类路径。
(4).fork表示在一个新的虚拟机中运行该类。
(5).failonerror表示当出现错误时自动停止。
(6).output 表示输出文件。
(7).append表示追加或者覆盖默认文件。

7.<delete>标签
该标签用于删除一个文件或一组文件,去属性如下。
(1)/file表示要删除的文件。
(2).dir表示要删除的目录。
(3).includeEmptyDirs 表示指定是否要删除空目录,默认值是删除。
(4).failonerror 表示指定当碰到错误是否停止,默认值是自动停止。
(5).verbose表示指定是否列出所删除的文件,默认值为不列出。

8.<copy>标签
该标签用于文件或文件集的拷贝,其属性如下。
(1).file 表示源文件。
(2).tofile 表示目标文件。
(3).todir 表示目标目录。
(4).overwrite 表示指定是否覆盖目标文件,默认值是不覆盖。
(5).includeEmptyDirs 表示制定是否拷贝空目录,默认值为拷贝。
(6).failonerror 表示指定如目标没有发现是否自动停止,默认值是停止。
(7).verbose 表示制定是否显示详细信息,默认值不显示。

Ant的数据类型
在构建文件中为了标识文件或文件组,经常需要使用数据类型。数据类型包含在

org.apache.tool.ant.types包中。下面镜简单介绍构建文件中一些常用的数据类型。

1. argument 类型
 由Ant构建文件调用的程序,可以通过<arg>元素向其传递命令行参数,如apply,exec和java任

务均可接受嵌套<arg>元素,可以为各自的过程调用指定参数。以下是<arg>的所有属性。
(1).values 是一个命令参数。如果参数种有空格,但又想将它作为单独一个值,则使用此属性


(2).file表示一个参数的文件名。在构建文件中,此文件名相对于当前的工作目录。
(3).line表示用空格分隔的多个参数列表。
(4).path表示路径。

2.ervironment 类型
  由Ant构建文件调用的外部命令或程序,<env>元素制定了哪些环境变量要传递给正在执行的系

统命令,<env>元素可以接受以下属性。
(1).file表示环境变量值得文件名。此文件名要被转换位一个绝对路径。
(2).path表示环境变量的路径。Ant会将它转换为一个本地约定。
(3).value 表示环境变量的一个直接变量。
(4).key 表示环境变量名。
注意  file path 或 value只能取一个。

3.filelist类型
 Filelist 是一个支持命名的文件列表的数据类型,包含在一个filelist类型中的文件不一定是

存在的文件。以下是其所有的属性。
(1).dir是用于计算绝对文件名的目录。
(2).files 是用逗号分隔的文件名列表。
(3).refid 是对某处定义的一个<filelist>的引用。
注意  dir 和 files 都是必要的,除非指定了refid(这种情况下,dir和files都不允许使用)。

4.fileset类型
Fileset 数据类型定义了一组文件,并通常表示为<fileset>元素。不过,许多ant任务构建成了

隐式的fileset,这说明他们支持所有的fileset属性和嵌套元素。以下为fileset 的属性列表。
(1).dir表示fileset 的基目录。
(2).casesensitive的值如果为false,那么匹配文件名时,fileset不是区分大小写的,其默认

值为true.
(3).defaultexcludes 用来确定是否使用默认的排除模式,默认为true。
(4).excludes 是用逗号分隔的需要派出的文件模式列表。
(5).excludesfile 表示每行包含一个排除模式的文件的文件名。
(6).includes 是用逗号分隔的,需要包含的文件模式列表。
(7).includesfile 表示每行包括一个包含模式的文件名。

5.patternset 类型
Fileset 是对文件的分组,而patternset是对模式的分组,他们是紧密相关的概念。

<patternset>支持4个属性:includes excludex includexfile 和 excludesfile,与fileset相

同。Patternset 还允许以下嵌套元素:include,exclude,includefile 和 excludesfile.

6.filterset 类型
Filterset定义了一组过滤器,这些过滤器将在文件移动或复制时完成文件的文本替换。
主要属性如下:
(1).begintoken 表示嵌套过滤器所搜索的记号,这是标识其开始的字符串。
(2).endtoken表示嵌套过滤器所搜索的记号这是标识其结束的字符串。
(3).id是过滤器的唯一标志符。
(4).refid是对构建文件中某处定义一个过滤器的引用。

7.Path类型
Path元素用来表示一个类路径,不过它还可以用于表示其他的路径。在用作揖个属性时,路经中

的各项用分号或冒号隔开。在构建的时候,此分隔符将代替当前平台中所有的路径分隔符,其拥

有的属性如下。
(1).location 表示一个文件或目录。Ant在内部将此扩展为一个绝对路径。
(2).refid 是对当前构建文件中某处定义的一个path的引用。
(3).path表示一个文件或路径名列表。

8.mapper类型
Mapper类型定义了一组输入文件和一组输出文件间的关系,其属性如下。
(1).classname 表示实现mapper类的类名。当内置mapper不满足要求时,用于创建定制mapper.
(2).classpath表示查找一个定制mapper时所用的类型路径。
(3).classpathref是对某处定义的一个类路径的引用。
(4).from属性的含义取决于所用的mapper.
(5).to属性的含义取决于所用的mapper.
(6).type属性的取值为identity,flatten glob merge  regexp  其中之一,它定义了要是用的

内置mapper的类型。


Ant 的运行
安装好Ant并且配置好路径之后,在命令行中切换到构建文件的目录,输入Ant命令就可以运行

Ant.若没有指定任何参数,Ant会在当前目录下查询build.xml文件。如果找到了就用该文件作为

构建文件。如果使用了 –find 选项,Ant 就会在上级目录中找构建文件,直至到达文件系统得

跟目录。如果构建文件的名字不是build.xml ,则Ant运行的时候就可以使用 –buildfile file

,这里file 指定了要使用的构建文件的名称,示例如下:
Ant
如下说明了表示当前目录的构建文件为build.xml 运行 ant 执行默认的目标。

Ant –buildfile  test.xml
使用当前目录下的test.xml 文件运行Ant ,执行默认的目标

 

eclipseGH DM R properties插件

   开发java程序的时候要编辑properties文件,里面要用到中文,就要使用java里面的native2ascii工具来进行转化,把gbk的编码转成unicode编码,可以手工运行native2ascii文件进行编辑,或者使用ant里面的相关任务来进行操作.但是这样都比较麻烦,并且转化以后的文件用编辑器打开以后就不能直接看到中文,要进行修改比较麻烦.
    eclipse下面有一些工具可以帮助进行操作,jinto http://www.guh-software.de/jinto_en.html 和propertieseditor http://propedit.sourceforge.jp/index_en.html 两个都可以.
 
    其中properties editor好像是日本人开发的,可以支持jbuider,eclipse,standlone,不考虑使用了.
   jinto是eclipse下面的插件,可以同时把多个properties文件同时显示出来,对网页的国际化开发比较方便,功能比较适合,一直使用他.
 
好东西大家分享:eclipse下面的properties插件
 

关于 LOG4J 级别和显示配置

使用LOG4J : 可以在console中打印LOG信息.可设置LOG级别和显示的配置.
至少需要一个log4j.properties文件,位于SRC根下;
 
#log4j.properties:
 
#以下部分是log4j基本设置
#如rootLogger代表logger根,即默认级别; 其它设置为console显示方式的内容
log4j.rootLogger = WARN, console
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern = %d [%t] %-5p %c - %m%n
 
#以下部分是用于特别指定某块程序的log级别
#log4j.logger后面部分用来指定特定的程序块,即包名. 如log4j.logger.org = INFO,即设置org整个包为INFO级别
log4j.logger.org = INFO
log4j.logger.org.hibernate = INFO
log4j.logger.gboxs = DEBUG
log4j.logger.test = DEBUG
 
下面的文件log4j.jsp,位于WEBCONTENT目录下,可用于在程序运行时临时修改LOG级别.
只用打开该页面,并作相应选择即可.但不会改变log4j.properties内容.即不影响重启后系统设置.
#log4j.jsp :
<%
 //
 org.apache.log4j.Logger tmp = org.apache.log4j.Logger
   .getRootLogger();
 out.println("root level " + tmp.getLevel());
 String set = request.getParameter("set");
 if (set != null) {
  String logger = request.getParameter("logger");
  if (logger != null) {
   org.apache.log4j.Logger log = org.apache.log4j.Logger
   .getLogger(logger);
   org.apache.log4j.Level l = log.getLevel();
   out.println("<br/>");
   out.println(logger + " old level " + l);
   String i = request.getParameter("level");
   if ("1".equals(i))
  //log.setLevel(Level.TRACE);
  ;
   else if ("2".equals(i))
  log.setLevel(org.apache.log4j.Level.DEBUG);
   else if ("3".equals(i))
  log.setLevel(org.apache.log4j.Level.INFO);
   else if ("4".equals(i))
  log.setLevel(org.apache.log4j.Level.WARN);
   else if ("5".equals(i))
  log.setLevel(org.apache.log4j.Level.ERROR);
   else if ("6".equals(i))
  log.setLevel(org.apache.log4j.Level.ALL);
  }
 }
 String show = request.getParameter("show");
 if (show != null) {
  String logger = request.getParameter("logger");
  if (logger != null) {
   org.apache.log4j.Logger log = org.apache.log4j.Logger
   .getLogger(logger);
   org.apache.log4j.Level l = log.getLevel();
   out.println("level " + l);
  }
 }
 application.log("log4j has changed");
%>
<html>
<body>
<form method="Post"><input value="org.apache.struts" name="logger" size="60" /> <select name="level">
  <option value="2">trace</option>
  <option value="2" selected="selected">debug</option>
  <option value="3">info</option>
  <option value="4">warn</option>
  <option value="5">error</option>
  <option value="6">all</option>
</select> <input type="submit" value="set" name="set" /> <input type="submit" value="show" name="show" />
<p /><select name="pre" onchange="if(this.value > 0)this.form.logger.value = (this.options[this.value].text);">
  <option value="0">--select--</option>
  <option value="1">org.apache.commons.beanutils.BeanUtils</option>
  <option value="2">org.apache.struts</option>
  <option value="3">org.hibernate.type</option>
  <option value="4">org.springframework</option>
  <option value="5">org.hibernate</option>
  <option value="6">org.hibernate.jdbc</option>
  <option value="7">org.hibernate.type</option>
  <option value="8">org.springframework.orm</option>
  <option value="9">org.springframework.transaction</option>
  <option value="10">gboxs</option>
</select>
</form>
</body>
</html>

关于鼠标右键的输出源码

将以下两个文件存到 D:\ 下.双击运行test.reg文件即可!
##d:\test.html:
 
<script language="javascript"> 
 function obj(o) {
  if(typeof(o) != 'object')return o;
  var inf = "{";
  var a;
  for(var i in o) {
   try{
    a = o[i];
    if(typeof(a) == "array") {
     inf += i + " = {" + obj(a) + "},";
    } else {
     inf += i + " = " + a + ",";
    }
   }catch(e) {
    inf += i + " !cantaccess, ";
   }
  }
  inf += "}"
  return inf;
 }
var win = external.menuArguments;
var ev= win.event;
var src = ev.srcElement;
var level = 0;
if(ev.ctrlKey) {
 level = new Number(win.prompt("Trace Level","1"));
}
var target = src;
for (var i = 0;i < level;i ++) {
 if(target.parentNode)target = target.parentNode;
}
var infostr=target.outerHTML;
if(target.style){
 infostr += "\n";
 for(var i in target.style) {
  if(target.style[i] != '') {
   infostr += i + "=" + target.style[i] + "\n";
  }
 }
}
if(!confirm(infostr)){
 if(confirm("open in new window?")) {
  try{
   var newWin = window.open("about:blank");
   if(newWin == null){
    newWin= win;
   }
   newWin.document.write("<pre id=info>");
   newWin.info.innerText = (infostr);
   newWin.document.write("</pre>");
  }catch(ee){
   alert(obj(ee));
  }
 }
}
</script>
 
##test.reg:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\MenuExt\test&w]
@="d:\\test.html"

 

 

MAVEN 基础使用

  maven是一个源代码开放的JAVA项目管理工具,在其支持网站(http://maven.apache.org)上可以上载到最新的软件包,MAVEN需要JDK的支持。在安装MAVEN之前请确认JDK已经安装,并设置好了JAVA_HOME和CLASSPATH这些环境变量.
  把下载的MAVEN解压到D:\MAVEN目录后,设置MAVEN_HOME=D:\MAVEN,同时,在PATH中加上D:\MAVEN\BIN,然后执行 >maven -v 来验证是否正确.
  现在就可以把项目纳入MAVEN的管理之下了.假设项目的根目录是D:\PROJECT\,其中源代码在D:\PROJECT\SRC\JAVA\目录之下.
  MAVEN使用POM来对项目进行表示,而用于描述POM的XML文件则由三个主要部分组成:
1\ 项目管理部分
    包括项目的组织,开发人员名单,源代码位置等信息;
2\ 项目关联部分
    包括有关项目相关性的所有信息;
3\ 项目构建部分
    包含项目构建过程及要在构建中生成的项目报告等信息;
 
要使用MAVEN来管理我们的这个项目,需要在项目的根目录D:\PROJECT\下创建一个名为project.xml的文件,其完整内容如下所示:
 
project.xml
<project>
  <id>linuxgam</id>
  <build>
    <sourceDirectory>
      ${basedir}/src/java
    </sourceDirectory>
  </build>
</project>
 
  在用MAVEN进行项目构建管理时所有的行为都是基于目标(GOAL)的,MAVEN中的GOAL类似于ANT中的TARGET,指的是在某种情况下应该执行的动作集合.
 
D:\PROJECT>MAVEN JAVA:COMPILE
对项目进行编译,只要在项目的根目录下执行MAVEN预定义的JAVA:COMPILE目标就可以了
 
D:\PROJECT>MAVEN JAR
将编译生成的.CLASS文件打成JAR包,并保存在D:\PROJECT\TARGET目录下
 
D:\PROJECT>MAVEN CLEAN
清除编译结果(CLASS JAR)
 
  需要注意的是,在第一次执行MAVEN中预定义的目标时,它将首先自动从网络上下载一些依赖的JAR包,然后才能开始政党的编译过程。编译完成后,MAVEN会将生成的.CLASS文件保存到D:\PROJECT\TARGET\CLASSES\目录下.
而文件名则由PROJECT.XML中的id和currentVersion元素共同决定.
  JAVA:COMPILE \ JAR \ CLEAN 是使用MAVEN管理JAVA项目时最常用的三个目标,MAVEN中预定义的几碍个目标基本上能够满足绝大多数应用场合的需要.为了能更好的管理这些目标,MAVEN引入了插件概念,几乎所有的MAVEN功能都是以插件的形式提供的,而MAVEN本身可以看成是一个用来对这些插件进行管理的内核. 
 
  在了解了MAVEN的一些基本功能之后,下面再来看看MAVEN是如何将第三方工具缝的集成到项目构建过程中的,我们选择JUNIT测试工具作为例子.首先,需要在PROJECT.XML中添加UNITTESTSOURCEDIRECTORY元素:
 project.xml
<project>
  <id>linuxgam</id>
  <currentVersion>1.0</currentVersion>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artfactId>junit</artfactId>
      <version>3.8.1</version>
    <dependency>
  </dependencies>
  <build>
    <sourceDirectory>
      ${basedir}/src/java
    </sourceDirectory>
    <unitTestSourceDirectory>
      ${basedir}/src/test
    </unitTestSourceDirectory>
    <unitTest/>
  </build>
</project>
 

之后,如果要进行单元测试,只需要在项目根目录下执行MAVEN预定义的TEST目标就可以了
D:\PROJECT>MAVEN TEST
要对配置的JUNIT部分进行单元测试
在PROJECT.XML中添加reports元素:
project.xml
<project>
  <id>linuxgam</id>
  <currentVersion>1.0</currentVersion>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artfactId>junit</artfactId>
      <version>3.8.1</version>
    <dependency>
  </dependencies>
  <build>
    <sourceDirectory>
      ${basedir}/src/java
    </sourceDirectory>
    <unitTestSourceDirectory>
      ${basedir}/src/test
    </unitTestSourceDirectory>
    <unitTest/>
  </build>
  <reports>
    <report>maven-changelog-plugin</report>
    <report>maven-file-activity-plugin</report>
    <report>maven-developer-activity-plugin</report>
然后在根目录下执行SITE命令,MAVEN就会在D:\PROJECT\TARGET\DOCS\目录下为项目生成相应的文档,打开该目录下的INDEX.HTML,你会发现MAVEN已经自动生成项目信息,邮件列表,更改记录等文档.
D:\PROJECT>MAVEN SITE
 
 
MAVEN提出一个叫生命周期的定义。
每个阶段会包含此前所有阶段的操作。
用户可以根据自己的需要决定用MAVEN执行哪些操作。从而选用某个阶段对应的命令。