您的位置:首页 > 编程语言 > Java开发

Java静态检测工具的简单介绍 - Sonar、Findbugs

2012-03-30 16:06 417 查看
静态检查:静态测试包括代码检查、静态结构分析、代码质量度量等。它可以由人工进行,充分发挥人的逻辑思维优势,也可以借助软件工具自动进行。代码检查代码检查包括代码走查、桌面检查、代码审查等,主要检查代码和设计的一致性,代码对标准的遵循、可读性,代码的逻辑表达的正确性,代码结构的合理性等方面;可以发现违背程序编写标准的问题,程序中不安全、不明确和模糊的部分,找出程序中不可移植部分、违背程序编程风格的问题,包括变量检查、命名和类型审查、程序逻辑审查、程序语法检查和程序结构检查等内容。”。看了一系列的静态代码扫描或者叫静态代码分析工具后,总结对工具的看法:静态代码扫描工具,和编译器的某些功能其实是很相似的,他们也需要词法分析,语法分析,语意分析...但和编译器不一样的是他们可以自定义各种各样的复杂的规则去对代码进行分析。静态检测工具:PMD
1)PMD是一个代码检查工具,它用于分析Java源代码,找出潜在的问题:
1)潜在的bug:空的try/catch/finally/switch语句
2)未使用的代码:未使用的局部变量、参数、私有方法等
3)可选的代码:String/StringBuffer的滥用
4)复杂的表达式:不必须的if语句、可以使用while循环完成的for循环
5)重复的代码:拷贝/粘贴代码意味着拷贝/粘贴bugs

2)PMD特点:
1)与其他分析工具不同的是,PMD通过静态分析获知代码错误。也就是说,在
不运行Java程序的情况下报告错误。
2)PMD附带了许多可以直接使用的规则,利用这些规则可以找出Java源程序的许
多问题
3)用户还可以自己定义规则,检查Java代码是否符合某些特定的编码规范。

3)同时,PMD已经与JDeveloper、Eclipse、jEdit、JBuilder、BlueJ、
CodeGuide、NetBeans、SunJavaStudioEnterprise/Creator、
IntelliJIDEA、TextPad、Maven、Ant、Gel、JCreator以及Emacs
集成在一起。

4)PMD规则是可以定制的:可用的规则并不仅限于内置规则。您可以添加新规则:
可以通过编写Java代码并重新编译PDM,或者更简单些,编写XPath表
达式,它会针对每个Java类的抽象语法树进行处理。

5)只使用PDM内置规则,PMD也可以找到你代码中的一些真正问题。某些问题可能
很小,但有些问题则可能很大。PMD不可能找到每个bug,你仍然需要做单元测
试和接受测试,在查找已知bug时,即使是PMD也无法替代一个好的调试器。
但是,PMD确实可以帮助你发现未知的问题。
FindBugs
1)FindBugs是一个开源的静态代码分析工具,基于LGPL开源协议,无需
运行就能对代码进行分析的工具。不注重style及format,注重检测真正
的bug及潜在的性能问题,尤其注意了尽可能抑制误检测(falsepositives)
的发生。以bytecode(*.class、*.jar)为对象进行检查。除了单独动作,还可
以用作Eclipse的plug-in,以及嵌入Ant作为task之一进行利用。

2)findbugs自带检测器的介绍:findbugs自带60余种Badpractice,80余种
Correntness,1种Internationalization,12种Maliciouscode
vulnerability,27种Multithreadedcorrentness,23种Performance,
43种Dodgy。

3)Findbugs的一些特点:
1)FindBugs主要着眼于寻找代码中的缺陷,这就与其他类似工具有些区别了,
直接操作类文件(class文件)而不是源代码。
2)FindBugs可以通过命令行、各种构建工具(如Ant、Maven等)、独立的
SwingGUI或是以Eclipse和NetBeansIDE插件的方式来运行。
3)FindBugs输出结果既可以是XML的,也可以是文本形式的。
4)开发者可以通过多种方式来使用FindBugs,最常见的是在新编写模块的代码
分析以及对现有代码进行更大范围的分析。
5)不注重style及format,注重检测真正的bug及潜在的性能问题,
尤其注意了尽可能抑制误检测(falsepositives)的发生。

4)FindBugs可检测的bugpattern举例:
检测javaprograming中容易陷入的bugpattern,equals()实现时的一般规约违反
Nullpointer的参照,Method的返回值的check遗漏,初始化前field的访问,
Multi-thread的正确性,同期化处理的矛盾,无条件的wait(),Code的脆弱性,
可以变更的静态object,内部数列参照的return等
Checkstyle
1)定义:Checkstyle是一款检查Java程序源代码样式的工具。
2)特点:
1)它可以有效的帮助我们检视代码以便更好的遵循代码编写标准,特
别适用于小组开发时彼此间的样式规范和统一。
2)Checkstyle提供了高可配置性,以便适用于各种代码规范,所以
除了使用它提供的几种常见标准之外,你也可以定制自己的标准。
3)Checkstyle提供了支持大多数常见IDE的插件,大部分插件中就含有
最新的Checkstyle,就不用费心再部署一份了。
4)Checkstyle可以检查代码的很多方面,从传统观点看,它主要是用来
检查代码层面的,自从第三版以后,它的内部架构作了重大改变,很多
其它意图的检测加了进来,现在Checkstyle可以检查像类设计的问题,
重复代码,如锁的双重检查的bug模式。
3)CheckStyle的主要流程是:
1)对Java文件进行词法语法分析,生成语法树。
2)载入配置文件(checkstyle-metadata.xml以及自定义的配置文件)
registercheck事件。
3)按照深度优先遍历对语法树进行解析,按照注册的事件,在到达某些节点
(AST)时进行style检查(AST,Achild-SiblingTree,是语法
树中的某个节点,其类型在TokenTypes类中定义。)
4)我们所说的自定义Style的检查,就是在第二步设定的。
这里牵涉到一个叫com.puppycrawl.tools.checkstyle.api.Check的类,
我们通常需要重载其中的两个函数:publicint[]getDefaultTokens()
和publicvoidvisitToken(DetailASTast).这两个函数的含义为,
在遍历语法树的过程中,每当到达getDefaultTokens函数所返回的AST类型,
程序就进入visitToken进行具体的检查和分析,即,真正的分析检查过程是在
visitToken中实现的。
Hammurapi
1)定义:Hammurapi它是一个开源的代码审查/评审(review)工具。它可以帮助改进
Java代码的质量。它可以基于一套设计规范来分析代码库。当它碰到违反规
范的地方,会在报告中标识。就像Checkstyle一样,它与Ant无缝集成并且
由基于XML配置文件来驱动。

2)特点:
1)Hammurapi是用来强制代码设计规范的。
2)Hammurapi是一个遵循设计的工具,提供了自动而且一致的方式来实现设计规范,
因此使代码评审更加有效而轻松。
3)Hammurapi如何工作:
Hammurapi这样的代码分析工具都带有语言分析器。语言分析器是一种输入
语言代码并输出抽象语法树的工具。这个树上的节点代表语言标识。例如,考
虑一下简单的算术表达式:3+4.语言分析器会解析他成为一个如图5所示的语
法树。在这个树中,节点+代表操作符标识。节点3和4是操作数标识Hammurapi
使用ANTLR(另一个语言识别工具)作为语言分析器。然而ANTLRAPI是相当底层的。
为改善可用性,Hammurapi使用另一个API,基于ANTLR的JSEL(Java源程序
工程类库),来访问抽象语法树。一旦树构建完成,一种树遍历算法就被用来访
问树中每一个节点。每次访问到一个节点,一种回调机制(Visitor模式)被用来
提示相应的检查器。在这些回调方法中,检查器收集相关的信息来确定是否有违反
规范的地方存在。  
Lint4j
1)定义:Lint4J是一个针对Java的源代码分析工具,它可以对Java源码和字节
码进行静态分析,判断其中是否存在死锁、性能问题或者伸缩性问题。
它可以集成到任何IDE种或构建系统
2)特点:
1)检测代码语法规则
2)潜在的bug
3)检测编码模式对代码可读性及大小的影响
4)检测是否违反EJB规范
Sonar
1)定义:代码质量管理工具Sonar提供了设计与架构度量。Sonar2.0引入了
针对Java应用的设计分析、架构与面向对象的度量,Sonar2.1可以
检测到未使用的方法以及对不建议使用方法的调用。是一个集成了
CheckStyle,PMD,Findbugs的代码校验规则,重复代码发现,
代码测试覆盖率,代码注释率,及所有的检测率变化追踪的完美
代码质量检查工具。它包含了代码质量检测的七个方面,如下图

2)特点:
1)代码覆盖:通过单元测试,将会显示哪行代码被选中。
2)改善编码规则。
3)搜寻编码规则:按照名字,插件,激活级别和类别进行查询。
4)项目搜寻:按照项目的名字进行查询。
5)对比数据:比较同一张表中的任何测量的趋势。
6)单元测试

3)Sonar2.1:
Sonar还基于Squid引入了一个全新的规则引擎、Sonar解析器既可以处
理源代码,也可以处理字节码,解析器带有内建的规则,可以检测未使用
的私有与保护方法以及客户端对不建议使用的方法的调用。
Squid通过分析应用源代码、JavaAPI和外部程序库
的字节码来决定哪些方法、类和属性是不建议使用的。
Sonar2.1的新特性:
1)一个全新的“Libraries”页面,显示了项目中所有的程序库和依赖,该特性要求使用
Maven来构建项目。
一旦在Sonar站点的主页上选择了一个项目,该服务就会以
可视化的树形结构展示出项目依赖。此外,还有一个可选的
动态过滤器,可以根据名称过滤程序库以便在应用的依赖间导航。
2)用于搜索程序库使用情况的“Dependencies”页面。比如说,可以
搜索到使用了第三方框架如CommonsLogging1.1的所有项目。
3)可以使用各种插件扩展Sonar的功能。现在有一个全新的
“SystemInfo”页面显示了系统属性、已装插件和Java虚拟机内存
统计信息。该页面还给出了关于Sonar配置和数据库统计的详细信息。
4)一个用于管理已装插件和系统信息的管理控制台。
最新版的Sonar为这些插件引入了一个测试框架和一个客户化的Maven
生命周期管理工具。它还带有一个用于集成项目事件的
WebService并在项目的sizewidget中增加了一个新的度量模块。
JDepend
1)JDepend一个开放源代码的可以用来评价Java程序质量的优秀工具,
它遍历Javaclass的文件目录,以Java包(package)为
单位,为每一个包/类自动生成包的依赖程度,稳定性,可靠度等
的评价报告,根据这些报告,我们可以得到包或类之间的依赖关
系,并分析出包的稳定程度,抽象程度,是否存在循环依耐关系等。
可以根据JDepend给出的报告数据,分析出我们的包是否是
可靠的,稳定的,健壮的包,是否符合面向对象的设计原则。

2)特点:
1)评价设计质量
2)翻转依赖性
3)支持并行开发和极限编程
4)独立的发布模块
5)识别package的循环依赖

3)Depend生成的Java包的质量评价报告主要包括:
1)NumberofClassesandInterfaces:实现类与抽象接口的数目
2)Abstractness(A):包的抽象度。指一个包内包含的抽象类或接口
占整个包中的类的比重。
3)AfferentCouplings(Ca):向心耦合。依赖该包(包含的类)的外
部包(类)的数目(i.e.incomingdependencies),该数值越大,
说明该包的担当的职责越大,也就越稳定。
4)EfferentCouplings(Ce):离心耦合。被该包依赖的外部包的数目
(i.e.outgoingdependencies),该数值越大,说明该包越不独
立(因为依赖了别的包),也越不稳定。
5)Instability(I):衡量一个包的不稳定程度。I=Ce/(Ce+Ca)。它的值处于
[0,1]之间。I=0时说明包是最稳定的,反之I=1则说明包极不稳定。
6)DistancefromtheMainSequence(D):该指标主要用来评价包的抽象
程度与稳定程度的平衡关系,它可以用二维直线图A+I=1来表示。
7)PackageDependencyCycles:包的循环依赖度。

8.IBMCheckingToolforBugsErrorsandMistakes(简称BEAM)
1)定义:是IBM开发的一个静态分析工具,可以用于分析并查找出C,C++和Java
代码中的一些不容易发现的潜在错误,从而达到提高代码质量的目的。同动态
分析工具和其它静态分析工具相比,它拥有一些可贵的特性。
2)特点:
1)对代码进行语法扫描,通过算法对代码进行检查分析
2)和一些bug模式进行比较,最终标明问题区域,输出分析结果
3)使用了额外的定理证明(theoremproving)技术来判断一个潜在的错误是否
是真正的错误,从而减轻了程序员判断错误真伪所需的工作量

9.LDRATestbed
1)定义:LDRATestbed为应用软件的确认和验证提供强大的源代码测试和分析功能,
是独特的质量控制工具。它有助于提高计算机软件必需的可靠性,健壮性和尽
可能的零缺陷,它的使用带来时间、成本和效率上真实的节省,这些都是无法衡
量其价值的。它是强大和完整的集成工具包,使先进的软件分析技术应用在开发生
命周期的关键阶段。
2)LDRATestbed提供强大的分析功能,用于两个主要的测试领域,静态分析和动态分析。
1)静态分析:分析代码,并且提供对代码结构的理解。
2)动态分析:利用源代码的插装版本,使用测试数据执行,在运行时发现软件
缺陷
3)使用LDRAtestbed的好处
软件开发和测试过程的成本效率分析工具
单元、集成和系统测试的理想工具
贯穿于软件开发的整个生命周期

LDRATestbed应用于许多不同的领域
过程改进
软件测试
软件维护

LDRATestbed的优点:
改进软件质量
定位软件缺陷
强制执行工业标准
减少维护费用40%以上
减少开发和测试成本75%以上
通过自动化过程提高员工动力

10.Yasca
1)定义:yasca是一个开源静态代码分析工具插件框架, 集成流行的多语言静态分析工
具如findbugs/pmd/jlint/rats/cppcheck,由于插件本身多样故可支持java
c++等语言静态分析.Yasca是一个用来寻找安全漏洞,在程序的源代码中检测代
码质量、性能以及一致性的软件。它集成了其他开源项目,其中包括FindBugs
PMD,JLint,Cppcheck,并扫描某些文件类型,以及自定义扫描书面的
Yasca这是一个命令行工具,与报告中生成的HTML,CSV格式,XML的,的
SQLite,和其他格式。
/article/4330421.html
CGI跟我学■CGI脚本是什么?■CGI脚本怎样工作的?■一个简单的例子■我能用CGI脚本吗?■你的服务器配置允许CGI脚本吗?■你能编程吗?■你应该用什么编程语言?■你的服务器设置正确吗?■如果你的服务器不是UNIX系统呢?■解剖CGI脚本■输出头部■输出数据部■带阐述的脚本■传递其他信息给脚本■创建特殊的脚本输出■以装载另一个文本响应■无响应■处理表单的脚本■表单格式和表单脚本■GET和POST■URL编码■问题■CGI变量■解码程序■uncgi■cgi-lib.pl■解码文件上传的输入■自己做■非解剖的头部脚本■总结■JavaCGI应用源码■学习CGI脚本(脚本)CGI意思为CommonGatewayInterface,一种基于浏览器的输入、在Web服务器上运行的程序方法.CGI脚本使你的浏览器与用户能交互,为了在数据库中寻找一个名词,提供你写入的评论,或者从一个表单中选择几个条目并且能得到一个明确的回答.如果你曾经遇到过在web上填表或进行搜索,你就是用的CGI脚本.你那时也许没有意识到,因为大部分工作是在服务器上运行的,你看到的只是结果.作为一个网页设计者,你创建客户端的CGI脚本,服务器端的程序用来处理用户输入,结果返回给用户.在这里你将学习关于CGI脚本的一切:■CGI脚本是什么?它是怎样工作的■一个CGI脚本输出象什么?■怎样用参数或无参数创建一个CGI脚本■怎样创建一个返回规定响应的CGI脚本■怎样创建一个输入表单的CGI脚本■有关在使用CGI脚本中的问题■你能在脚本中使用的CGI变量--------------------------------------------------------------------------------本章节假设在UNIX系统下的。--------------------------------------------------------------------------------CGI脚本是什么?CGI脚本简单地讲是个运行在Web服务器上的程序,有浏览器的输入触发.这个脚本通常象服务器和系统中其他程序如数据库的桥梁。CGI脚本难道不是一个真正的脚本?按照你的服务器的支持,他们可能是一个编译好的程序或者批命令文件或者其他可执行的东西.为了简单起见,我们统称他们为脚本scripts.--------------------------------------------------------------------------------CGI脚本是任何运行在web服务器上的程序.CGI意思是CommonGatewayInterface。--------------------------------------------------------------------------------CGI脚本是用下列两种方法使用的:作为一个表单的ACTION或作为一个页中的直接link。CGI脚本是怎样工作的?CGI脚本有服务器调用,基于浏览器的数据输入.图1显示在浏览器、服务器和脚本之间是怎样的一个流程.图1.从浏览器到服务器到脚本到程序记住再回来噢!这有个简短的示意解释:1.一个URL指向一个CGI脚本.一个CGI脚本的URL能如普通的URL一样在任何地方出现。2.服务器接收请求,按照那个URL指向的脚本文件(注意文件的位置和扩展名),执行脚本.3.脚本执行基于输入数据的操作,包括查询数据库、计算数值或调用系统中其他程序.4.脚本产生某种Web服务器能理解的输出结果.5.服务器接收来自脚本的输出并且把它传回浏览器,让用户了解结果。一个简单的例子这里详细一步一步地解释所有有关发生的细节。图2:DisplayDate处是个指向CGI脚本的连接.它的HTML是这样的:<AHREF="http://www.popchina.com/cgi-bin/getdate">DisplaytheDate</A>说明是个CGI脚本是因为这里面有个cgi-bin的路径.在许多服务器cgi-bin是仅能够放置CGI脚本的目录.当你选择这个连接时,你的浏览器将向www.popchina.com服务器提出请求.服务器接收这个请求计算出URL处的脚本文件名然后执行这个脚本.这个getdate脚本,在UNIX系统中执行是这样的:#!/bin/shechoContent-type:text/plainecho/bin/date第一行是个特殊的命令,告诉UNIX系统这是个shell脚本;真实的情况是从这行开始的下一行,这个脚本做两件事:它输出行Content-type:text/plain,接着开始一个空行;第二,它调用UNIX系统时间date程序,这样输出日期和时间.脚本执行后输出应该这样:Content-type:text/plainTueOct2516:15:57EDT1994这个Content-type是什么东东?它是个特殊的编码,Web服务器用来告诉浏览器输出这个文本是什么类型的.这与HTML中Content-type含义是一样的。这样浏览器的输出就如图3.这是最基本的,实际情况要复杂得多,总之可以用来理解浏览器、服务器和脚本之间是怎样工作的。我能用CGI脚本吗?在你使用CGI脚本之前,有两件事你也许要解决:CGI脚本是个高级的Web特性并且需要你和Web服务器管理者一样好的知识。肯定吗?就是做不到,学学也可以?好吧!让我们继续.你的服务器配置允许CGI脚本吗?为了能写和运行CGI脚本,你需要一个Web服务器.不象通常的HTML文件,你不能在本地系统上写或试验你的CGI脚本;你得通过Web服务器来做这个.但是即使你有一个Web服务器,这个服务器必须特别地为运行CGI脚本配置一下.那意味着你所有的脚本必须放置在一个叫做cgi-bin的目录下.在编写CGI脚本之前,询问你的服务器管理者是否允许你安装和运行CGI脚本,并且如果可以的话,他们必须放置在哪儿?还有,你必须有个真正的Web服务器,如果是FTP或Gopher服务器,那你就不能用CGI.如果你在自己的服务器上运行,你必须特别地创造一个叫cgi-bin的目录,并配置你的服务器认可这个目录为一个脚本目录.也必须记住下面有关CGI脚本特点:■每个脚本是个程序,它运行在浏览器可以请求的系统上,执行时使用CPU时间和内存.如果有成打上千的这些脚本同时运行,会怎样?你的系统将不忍负载直至崩溃。■如果你不仔细地编写你的CGI脚本,你将有可能让别人通过你的CGI脚本参数进入伤害你的系统.你会编程吗?初学者注意!一般地,你必须具备一些基本编程概念与方法。你必须有类似系统工作的经验。如果你没有这些背景,你必须去学习,好了,费话不多说.你必须用什么编程语言?你可以用你熟悉的任何语言编写CGI脚本,只要你的脚本遵守下一节所陈列的规则即可,只要那个语言能在你的Web服务器系统上运行.在这本学习手册中,仅用两种语言编写CGI脚本:UNIXshell和Perl语言.这个shell是适合在任何相近的UNIX系统上运行并且容易学习,但是处理复杂的情况就困难了.Perl,就要用这个语言了,它是免费的,这个语言是稳定和强大的,类似C,但它也是较难学习的.你的服务器设置正确了吗?为了运行任何一个CGI脚本,不管简单或复杂的,你的服务器必须设置成能够运行他们,必须放置在一个特定的目录,必须有一个依赖你服务器设定的文件扩展名.如果你是租用服务器,就要是否允许运行CGI脚本.如果你拥有自己的服务器,检查你的服务器说明书是怎样处理CGI脚本的.如果你用的不是UNIX?只好再找别的学习手册了。解剖一个CGI脚本如果你编写它很久,克服很多警告和配置,恭喜你,你已经会些CGI脚本,并且可以在你的网页上使用了.在这一章,将学习脚本是怎样执行,你的服务器又是怎样与他们对话产生回应的。输出头部虽然你的CGI脚本可以让你做任何事情,但是脚本的输出还是必须有一个规定形式.--------------------------------------------------------------------------------这个"脚本输出"意思是指你的脚本发回服务器的数据.在UNIX系统中,输出是发向标准输出,服务器从那儿检测它.在其他系统和服务器,你的脚本输出也许不一样了.--------------------------------------------------------------------------------这个头部是实际不是文本的一部分,是服务器与浏览器之间的信息协议,你实际看不到。有三个类型的头部:Content-type,Location,和Status.Content-type最普遍的。有关content-type解释可以见有关HTML的说明,一个你可以发出的特定编码象这样:Content-type:text/html在这个例子中,输出数据的类型是text/html;换句话说,他是个HTML文件.表1.通用格式和content-types.FormatContent-TypeHTMLtext/htmlTexttext/plainGIFimage/gifJPEGimage/jpegPostScriptapplication/postscriptMPEGvideo/mpeg注意content-type后面必须跟一个空行.如果你没有空行,服务器将无法搞清这个头部在哪里结束。输出数据你输出的数据应该符合你所规定的content-type;如果content-type是text/html,输出安置应该是在HTML.如果content-type是image/gif,输出应该是在一个二进制的GIF文件.练习1:小试试.T这是个简单的输出日期的简单脚本,这个CGI脚本还检查看看我是否已经登陆到我的Web服务器,并且报告发现了什么(如在图4).这是个很简单的例子,他能这样备调用:<AHREF="http://www.popchina.com/cgi-bin/pinglaura">IsLauraLoggedin?</A>这是没有输入的脚本,它只运行并且返回数据.根据前面的阐述,这个脚本内容是这样::#!/bin/shechoContent-type:text/htmlecho"<HTML><HEAD>"echo"<TITLE>IsLauraThere?</TITLE>"echo"</HEAD><BODY>"为了测试我是否已经登陆系统,用who命令(我的登陆名假设为lemay),储存结果在变量ison中.如果我登陆,变量ison将有些内容,否则则是空的.ison='who|greplemay'试验结果及返回相应提示的脚本是这样:if[!-z"$ison"];thenecho"<P>Lauraisloggedin."</P>elseecho"<P>Lauraisn'tloggedin."</P>fi最后关闭HTML:echo"</BODY></HTML>"现在你通过从命令行运行他,测试一下,你将得到一个结果说我未登陆你的系统,当然不可能的,他的输出是这样的:Content-type:text/html<HTML><HEAD><TITLE>AreYouThere?</TITLE></HEAD><BODY><P>Lauraisnotloggedin.</BODY></HTML>这是输出的一个HTML文本,这样你的浏览器能正常显示他,因为他是个HTML文件。--------------------------------------------------------------------------------现在将他copy到你的服务器的cgi-bin目录下,去执行,如果你不能达到CGI-bin目录,你必须询问你的服务器管理者,你不能理所当然地自己建立个CGI-bin目录,那没用的。--------------------------------------------------------------------------------这个例子完整的脚本如下:#!/bin/shecho"Content-type:text/html"echoecho"<HTML><HEAD>"echo"<TITLE>IsLauraThere?</TITLE>"echo"</HEAD><BODY>"ison='who|greplemay'if[!-z"$ison"];thenecho"<P>Lauraisloggedin"elseecho"<P>Lauraisn'tloggedin"fiecho"</BODY></HTML>"带有参数的脚本为了传递一个参数给脚本,可以在URL中使用(?)插入脚本名词和参数之间,用加号(+)表示每个单一的参数,如:<AHREF="/cgi-bin/myscript?arg1+arg2+arg3">runmyscript</A>当服务器接收到这个请求,它传递arg1,arg2,和arg3参数给脚本.你然后能在脚本中使用这些参数.这个方法有时叫查询,因为早期它用在搜索功能中.练习2:检查是否有人登陆.既然你知道怎样使用参数,让我们继续上面的例子pinglaura,通过修改这个例子我们得到下面这个脚本pinggeneric.我们取个不同题目:#!/bin/shecho"Content-type:text/html"echoecho"<HTML><HEAD>"echo"<TITLE>AreYouThere?</TITLE>"echo"</HEAD><BODY>"在上面的例子中,下一步应该是测试我是否登陆,在这里我们用参数${1}代替我的名字lemay,${1}作为第一个参数,${2}作为第二个,${3}作为第三个.ison='who|grep"${1}"'----------------------------------------------------------------------------------------------------------------------------------------------------------------剩下的所有修改如下:if[!-z"$ison"];thenecho"<P>$1isloggedin"elseecho"<P>$1isn'tloggedin"fiecho"</BODY></HTML>"好了,让我们修改HTML页中的连接吧!原来是这样:<AHREF="http://www.lne.com/cgi-bin/pinglaura">IsLauraLoggedin?</A>修改为通用查询功能后是这样,比如查询名字叫john的人是否登陆:<AHREF="http://www.lne.com/cgi-bin/pinggeneric?john">IsJohnLoggedin?</A>在你的服务器上试试,看是否有结果。传递其他信息给脚本有第二种方法传递信息给CGI脚本.它叫作路径信息pathinformation用作那些在脚本调用是不用变更的参数,象一个临时文件名或调用脚本自己的文件名.正如你看到的,在上面的例子问号后面的参数是因用户表单的输入而改变的.路径信息Pathinfo用作其他信息传递给脚本,实际上,你可以用它作任何事情.--------------------------------------------------------------------------------路径信息Pathinformation是一种不象通常参数脚本那样频繁传递信息的方法.路径Pathinformation通常是指Web服务器上的那些比如配置文件、临时文件或者被脚本因问题调用的文件等等此类文件.--------------------------------------------------------------------------------看下面一个路径信息pathinformation例子,:http://myhost/cgi-bin/myscript/remaining_path_info?arg1+arg2当脚本运行时,在路径中的信息将被放置于环境参数PATH_INFO.你能在你的脚本内容中使用这些信息.比如说,让我们假设你在多页上已有多个连接到同一个脚本.你能用这个路径信息显示那个有连接的HTML文件名.这样,在你完成处理你的脚本之后,当你发回一个HTML文件时,你能在这个文件里包含一个连接,发回用户一开始那个页。你会在下一章节学到更多路径信息:有用的表单和脚本.待后来登出创建一个特殊的脚本输出现在你已经学习了诸如输出数据一般地HTML数据发给浏览器解释显示的数据.但是如果你不想把脚本结果作为一个数据流形式发回浏览器,而是想把一个存在的页发回,怎么办?如果你只是要脚本做一些事而不让任何结果回答给浏览器,怎么办?不用怕,这里开始解释这些情况.用调用另一个文本作为响应CGI输出不是非得一个数据流,有时可以告诉浏览器是存在服务器上的一个页,为了发出这个信息,看下面的例子:Location:../docs/final.html这个Location行用作通常的输出位置,也就是说,如果你用了Location,你就不必再用象Content-type这样的数据输出(实际上,你也不能).正如Content-type,你也必须在这一行后面跟一个空行.指向这个文件的路径可以是一个URL或相对路径.所有相对路径是指相对于脚本所在的位置.例子中的final.html文本是在当前上一个目录下docs的目录下:echoLocation:../docs/final.htmlecho--------------------------------------------------------------------------------你不能Content-type和Location两个输出同时使用.比如,如果你想输出一个标准页,但是想在这个页尾加上客户的内容,你就得用Content-type自行组建这两个部分.注意:你可以用脚本命令打开一个当地文件作为数据直接将之输出.--------------------------------------------------------------------------------NoResponse有时对于一个CGI脚本也许一点没有输出.有时你只是要从用户那儿收集点信息.你就不用再调用一个新文本,也不用输出结果或打开一个存在的文件.在浏览器上的屏幕还是那个样子.很幸运,这一切很容易.你只要输出下面这个命令即可(后面跟一个空行):echoStatus:204NoResponseecho这个Status头部提供状态码给服务器(并且也给浏览器).特别的204将传递给浏览器,如果能识别它,它将什么也不做.--------------------------------------------------------------------------------尽管无响应是一个官方HTTP规定的一部分,但也并不是适合所有的浏览器,也许会产生奇怪的结果,那你要多试验试试看啦.--------------------------------------------------------------------------------处理表单的脚本今天,大多数CGI脚本是用来处理表单输入的.这个过程大致象上面说阐述的一样,但还是有些不同,比如CGI脚本只要被调用;数据怎样从服务器被发向浏览器.记住,大多数表单有两个部分:HTML的表单格式;处理表单数据的CGI脚本.这个CGI脚本使用标签<FORM>属性调用的.表单形式和表单脚本正如上面所说,由于表单有两个部分.如下:这个ACTION属性包含着处理表单的脚本:<FORMACTION="http://www.popchina.com/cgi-bin/processorscript">在这个表单中,每个输入区都有一个NAME的属性,用来称呼表单元素.当这个表单数据被递交给你在ACTION中定义的CGI脚本,这样这些name和输入内容被作为一个数字或字符传递给脚本.GET和POST表单从浏览器发给服务器有两种方法.GET和POST.我们上面谈论的方法,实际是GET,它将数据打包放置在环境变量QUERY_STRING中作为URL整体的一部分传递给服务器。POST做很多类似GET同样的事情,不同的地方就是它是分离地传递数据给脚本.你的脚本通过标准输入获取这些数据.(有些Web服务器是存储在临时文件中.)这个QUERY_STRING环境变量将不再设置.那你用那个方法呢?POST是个安全的方法,尤其如果你的表单中有很多数据的话.当你用GET,这个服务器就分配变量QUERY_STRING给所有的表单数据,但是这个变量可存储量是有限的.换句话说,如果你有很多数据但是你又用GET,你会丢失很多数据.如果你用POST,你可以尽可能多地使用数据,因为这些数据从来也不分配到一个变量里.URL编码URL编码是一种浏览器用来打包表单输入的格式.浏览器从表单中获取所有的name和其中的值,将他们作为name/value参数编码,移去那些不能传送的字符,将数据排行等等,这些还取决于你用GET还是POST?作为URL的一部分或者分离地发给服务器.不管哪种情况,在服务器端的表单输入格式样子象这样:theName=Ichabod+Crane&gender=male&status=missing&headless=yesURL编码遵循下列规则:■每对name/value由&符分开.■每对来自表单的name/value由=符分开.如果用户没有输入值给这个name,那么这个name还是出现,只是无值(象这样"name=").■任何特殊的字符(就是那些不是简单的七位ASCII,如汉字)将以百分符%用十六进制编码.当然也包括象=,&,和%这些特殊的字符.■在输入区中的空格将以加号+显示.因为表单输入是用这个URL编码传递给你的脚本的,在你用这些参数之前必须解码,因为解码是个很普遍的工作,可以有很多工具做这个工作.你没有必要自己写这个解码程序.这里介绍一个叫uncgi的解码程序,你可以从http://www.hyperion.com/~koreth/uncgi.html.得到原码,安装在你自己的cgi-bin目录下.robotsCGI变量表2总结那些环境变量.表2.CGI环境变量.环境变量意义SERVER_NAMECGI脚本运行时的主机名和IP地址.SERVER_SOFTWARE你的服务器的类型如:CERN/3.0或NCSA/1.3.GATEWAY_INTERFACE运行的CGI版本.对于UNIX服务器,这是CGI/1.1.SERVER_PROTOCOL服务器运行的HTTP协议.这里当是HTTP/1.0.SERVER_PORT服务器运行的TCP口,通常Web服务器是80.REQUEST_METHODPOST或GET,取决于你的表单是怎样递交的.HTTP_ACCEPT浏览器能直接接收的Content-types,可以有HTTPAcceptheader定义.HTTP_USER_AGENT递交表单的浏览器的名称、版本和其他平台性的附加信息。HTTP_REFERER递交表单的文本的URL,不是所有的浏览器都发出这个信息,不要依赖它PATH_INFO附加的路径信息,由浏览器通过GET方法发出.PATH_TRANSLATED在PATH_INFO中系统规定的路径信息.SCRIPT_NAME指向这个CGI脚本的路径,是在URL中显示的(如,/cgi-bin/thescript).QUERY_STRING脚本参数或者表单输入项(如果是用GET递交).QUERY_STRING包含URL中问号后面的参数.REMOTE_HOST递交脚本的主机名,这个值不能被设置.REMOTE_ADDR递交脚本的主机IP地址.REMOTE_USER递交脚本的用户名.如果服务器的authentication被激活,这个值可以设置。REMOTE_IDENT如果Web服务器是在ident(一种确认用户连接你的协议)运行,递交表单的系统也在运行ident,这个变量就含有ident返回值.CONTENT_TYPE如果表单是用POST递交,这个值将是application/x-www-form-urlencoded.在上载文件的表单中,content-type是个multipart/form-data.CONTENT_LENGTH对于用POST递交的表单,标准输入口的字节数.表单输入的解码程序目前有两个程序:通用目的的uncgi,和cgi-lib.pl,这是个Perl库,用于perl编写的CGI脚本.当然也有表单上载时可以解码的程序,很少。uncgi说明原码可以从http://www.hyperion.com/~koreth/uncgi.html获得。cgi-lib.pl这是由SteveBrenner编写的,帮助你管理输入.他能从GET和POST获取输入并且放置在一个Perl列表或阵列中.更新的版本也能处理来自表单的文件上传.从这儿可以得到信息与原码http://www.bio.cam.ac.uk/cgi-lib.如果你决定用Perl语言处理你的表单输入,cgi-lib是个很好的库.为了使用cgi-lib.pl,你通常要这样写:#!/usr/lib/perlrequire'cgi-lib.pl';cgi-lib中尽管有很多子程序,最重要的是ReadParse子程.ReadParse读取输入方便地将name/value储存在一个Perl阵列中.在你的Perl脚本中通常是这样调用的:&ReadParse(*in);此例中,阵列名是in,可以随便取名的.在表单输入解码后,你能读取和处理这个name/value,方法是象下面这样:print$in{'theName'};这个将显示名字name是theName的值value.如果你有多个用同样名字的name对,cgi-lib.pl用(\0)分隔多个名字.这样可以正常处理你的脚本.解码上传的文件输入基于表单的文件上传需要不同的表单输入,有一些程序可以对其进行解码。cgi-lib.pl后来版本可以很好支持,在http://www.bio.cam.ac.uk/cgi-lib/了解更多的情况.另一个处理用Perl编写的CGI地址是http://valine.ncsa.uiuc.edu/cgi_docs.html.自己做找专门书籍学习吧:ftp://ds.internic.net/rfc/rfc1867.txt.非解剖的脚本头部按照本书阐述,大多数情况可以正常操作,在一些情况下不是这样的,你可以翻阅说明书了解。<ISINDEX>脚本为了在CGI中完成讨论组,我们看看叫<ISINDEX>的搜索.这是早期在浏览器中用来向服务器发出搜索关键字的办法,参看以前的资料。总结CGI脚本,有时叫服务器端脚本或网关脚本。在internet上有很多免费资源,你可以搜索下载读懂他们,当然都是英文的,如果你下决心翻译他们(可能更加强理解).这样一举两得啊.注意:上述程序可以用ultraedit来编辑,注意转换UNIX格式,必须采用UNIX格式存盘,再上载,用telnet登陆,在命令行键入perlsample.pl,看有无bug,再在浏览器中调用。CGI程序包括放置CGI的目录一定要改属性为777,要写入的HTML文件也要改属性为777.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: