Java Tools

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  83 随笔 :: 0 文章 :: 16 评论 :: 0 Trackbacks

#

软件需求说明书
1. 引言
1.1 项目名称
1.2 项目背景和内容概要
(项目的委托单位、开发单位、主管部门、与其它项目的关系,与其他机构的关系等)

1.3 相关资料、缩略语、定义
(相关项目计划、合同及上级机关批文,引用的文件、采用的标准等)
(缩写词和名词定义)
2. 任务概述
2.1 目标
(项目的开发目标和应用目标。如果是其他系统的一部分,则说明其关系)
2.2 范围
(包含的业务,不包含的业务)
2.3 假定条件与约束限制
(尽量列出开展本项目的假定和约束,例如:经费限制,开发期限,设备条件,用户现
场环境准备等)
3.业务流程
4.数据描述
4.1 原始数据描述
a. 静态数据
b. 动态数据
4.2 数据流向图
4.3 数据概念模型和描述
5.功能需求
5.1 功能描述
6.界面要求
6.1报表格式
6.2图形要求
6.3输入输出要求
7.接口要求
(描述与本系统相连的系统的接口的数据格式,数据交换协议,接口功能等)
8.性能需求
8.1数据精确度
(例如,数据内部精度,外部显示精度)
8. 2数据量
8. 3时间特性要求
(根据所开发系统的特点,规定系统对时间的特性的要求。例如:
系统响应时间、界面更新处理时间、数据转换与传输时间)
9. 运行环境需求
9.1网络和硬件设备平台
(网络拓扑图及设备类型描述)
操作系统平台
数据库系统平台
10.1编程工具
10.2其它支撑软件
11. 其它专门需求
11.1安装和操作
11.2安全保密
11.3维护服务
posted @ 2007-07-02 13:13 和田雨 阅读(4618) | 评论 (1)编辑 收藏

法则1:优先使用(对象)组合,而非(类)继承

[ Favor Composition Over Inheritance ]




  • 组合



    1.(对象)组合是一种通过创建一个组合了其它对象的对象,从而获得新功能的复用方法。

    2.将功能委托给所组合的一个对象,从而获得新功能。

    3.有些时候也称之为"聚合"(aggregation)或"包容"(containment),尽管有些作者对这些术语赋予了专门的含义

    4.例如:

    a.聚合:一个对象拥有另一个对象或对另一个对象负责(即一个对象包含另一个对象或是另一个对象的一部分),并且聚合对象和其所有者具有相同的生命周期。(译者注:即所谓的"同生共死"关系,可参见GOF的Design
    Patterns: Elements of Reusable Object-Oriented Software的引言部分。)

    b.包容:一种特殊类型的组合,对于其它对象而言,容器中的被包含对象是不可见的,其它对象仅能通过容器对象来访问被包含对象。(Coad)





    5.包含可以通过以下两种方式实现:

    a.根据引用(By reference)

    b.根据值(By value)

    6.C++允许根据值或引用来实现包含。

    7.但是在Java中,一切皆为对象的引用!




  • 组合的优点和缺点






    1.优点:

    a.容器类仅能通过被包含对象的接口来对其进行访问。

    b."黑盒"复用,因为被包含对象的内部细节对外是不可见。

    c.对装性好。

    d.实现上的相互依赖性比较小。(译者注:被包含对象与容器对象之间的依赖关系比较少)

    e.每一个类只专注于一项任务。

    f.通过获取指向其它的具有相同类型的对象引用,可以在运行期间动态地定义(对象的)组合。




    2.缺点:

    a.从而导致系统中的对象过多。

    b为了能将多个不同的对象作为组合块(composition block)来使用,必须仔细地对接口进行定义。




  • 继承





    1.(类)继承是一种通过扩展一个已有对象的实现,从而获得新功能的复用方法。

    2.泛化类(超类)可以显式地捕获那些公共的属性和方法。

    3.特殊类(子类)则通过附加属性和方法来进行实现的扩展。





  • 继承的优点和缺点





    1.优点:

    a.容易进行新的实现,因为其大多数可继承而来。

    b.易于修改或扩展那些被复用的实现。

    2.缺点:

    a.破坏了封装性,因为这会将父类的实现细节暴露给子类。

    b. "白盒"复用,因为父类的内部细节对于子类而言通常是可见的。

    c.当父类的实现更改时,子类也不得不会随之更改。

    d.从父类继承来的实现将不能在运行期间进行改变。





  • Coad规则





    仅当下列的所有标准被满足时,方可使用继承:

    a.子类表达了"是一个…的特殊类型",而非"是一个由…所扮演的角色"。

    b子类的一个实例永远不需要转化(transmute)为其它类的一个对象。

    c.子类是对其父类的职责(responsibility)进行扩展,而非重写或废除(nullify)。

    d.子类没有对那些仅作为一个工具类(utility class)的功能进行扩展。

    e.对于一个位于实际的问题域(Problem Domain)的类而言,其子类特指一种角色(role),交易(transaction)或设备(device)。





  • 继承/组合示例1







1."是一个…的特殊类型",而非"是一个由…所扮演的角色"

-->失败。乘客是人所扮演的一种角色。代理人亦然。

2.永远不需要转化

-->失败。随着时间的发展,一个Person的子类实例可能会从Passenger转变成Agent,再到Agent Passenger。

3.扩展,而非重写和废除

-->通过。

4.不要扩展一个工具类

-->通过。

5.在问题域内,特指一种角色,交易或设备

-->失败。Person不是一种角色,交易或设备。






继承并非适用于此处!


使用组合进行挽救!





  • 继承/组合示例2







1."是一个…的特殊类型",而非"是一个由…所扮演的角色"

-->通过。乘客和代理人都是特殊类型的人所扮演的角色。

2.永远不需要转化

-->通过。一个Passenger对象将保持不变;Agent对象亦然。

3.扩展,而非重写和废除

-->通过。

4.不要扩展一个工具类

-->通过。

5.在问题域内,特指一种角色,交易或设备

-->通过。PersonRole是一种类型的角色。




继承适用于此处!




  • 继承/组合示例3







1."是一个…的特殊类型",而非"是一个由…所扮演的角色"

-->通过。预订和购买都是一种特殊类型的交易。

2.永远不需要转化

-->通过。一个Reservation对象将保持不变;Purchase对象亦然。

3.扩展,而非重写和废除

-->通过。

4.不要扩展一个工具类

-->通过。

5.在问题域内,特指一种角色,交易或设备

-->通过。是一种交易。




继承适用于此处!




  • 继承/组合示例4







1."是一个…的特殊类型",而非"是一个由…所扮演的角色"

-->失败。预订不是一种特殊类型的observable。

2.永远不需要转化

-->通过。一个Reservation对象将保持不变。

3.扩展,而非重写和废除

-->通过。

4.不要扩展一个工具类

-->失败。Observable就是一个工具类。

5.在问题域内,特指一种角色,交易或设备

-->不适用。Observable是一个工具类,并非一个问题域的类。。




继承并非适用于此处!




  • 继承/组合总结





    1.组合与继承都是重要的重用方法

    2.在OO开发的早期,继承被过度地使用

    3.随着时间的发展,我们发现优先使用组合可以获得重用性与简单性更佳的设计

    4.当然可以通过继承,以扩充(enlarge)可用的组合类集(the set of composable classes)。

    5.因此组合与继承可以一起工作

    6.但是我们的基本法则是:

    优先使用对象组合,而非(类)继承

    [ Favor Composition Over Inheritance ]

    法则2:针对接口编程,而非(接口的)实现

    [ Program To An Interface, Not An Implementation ]





    • 接口



      1.接口是一个对象在对其它的对象进行调用时所知道的方法集合。

      2.一个对象可以有多个接口(实际上,接口是对象所有方法的一个子集)

      3.类型是对象的一个特定的接口。

      4.不同的对象可以具有相同的类型,而且一个对象可以具有多个不同的类型。

      5.一个对象仅能通过其接口才会被其它对象所了解。

      6.某种意义上,接口是以一种非常局限的方式,将"是一种…"表达为"一种支持该接口的…"。

      7.接口是实现插件化(pluggability)的关键





    • 实现继承和接口继承



      1.实现继承(类继承):一个对象的实现是根据另一个对象的实现来定义的。

      2.接口继承(子类型化):描述了一个对象可在什么时候被用来替代另一个对象。

      3.C++的继承机制既指类继承,又指接口继承。

      4.C++通过继承纯虚类来实现接口继承。

      5.Java对接口继承具有单独的语言构造方式-Java接口。

      6.Java接口构造方式更加易于表达和实现那些专注于对象接口的设计。





    • 接口的好处



      1.优点

      a.Client不必知道其使用对象的具体所属类。

      b.一个对象可以很容易地被(实现了相同接口的)的另一个对象所替换。

      c.对象间的连接不必硬绑定(hardwire)到一个具体类的对象上,因此增加了灵活性。

      e.松散藕合(loosens coupling)。

      f.增加了重用的可能性。

      e.提高了(对象)组合的机率,因为被包含对象可以是任何实现了一个指定接口的类。

      2.缺点:

      a.设计的复杂性略有增加

      (译者注:接口表示"…像…"(LikeA)的关系,继承表示"…是…"(IsA)的关系,组合表示"…有…"(HasA)的关系。)





    • 接口实例








    该方法是指其它的一些类可以进行交通工具的驾驶,而不必关心其实际上是(汽车,轮船,潜艇或是其它任何实现了IManeuverabre的对象)。


    法则3:开放-封闭法则(OCP)

    软件组成实体应该是可扩展的,但是不可修改的。

    [ Software Entities Should Be Open For Extension, Yet Closed For Modification
    ]




    • 开放-封闭法则





      1.开放-封闭法则认为我们应该试图去设计出永远也不需要改变的模块。

      2我们可以添加新代码来扩展系统的行为。我们不能对已有的代码进行修改。

      3.符合OCP的模块需满足两个标准:

      4.可扩展,即"对扩展是开放的"(Open For Extension)-模块的行为可以被扩展,以需要满足新的需求。

      5.不可更改,即"对更改是封闭的"(Closed for Modification)-模块的源代码是不允许进行改动的。

      6.我们能如何去做呢?

      a.抽象(Abstraction)

      b.多态(Polymorphism)

      c.继承(Inheritance)

      d.接口(Interface)


      7. 一个软件系统的所有模块不可能都满足OCP,但是我们应该努力最小化这些不满足OCP的模块数量。

      8.开放-封闭法则是OO设计的真正核心。

      9.符合该法则便意味着最高等级的复用性(reusability)和可维护性(maintainability)。





    • OCP示例



      1. 考虑下面某类的方法:





      2.以上函数的工作是在制订的部件数组中计算各个部件价格的总和。

      3.若Part是一个基类或接口且使用了多态,则该类可很容易地来适应新类型的部件,而不必对其进行修改。

      4.其将符合OCP


      5. 但是在计算总价格时,若财务部颁布主板和内存应使用额外费用,则将如何去做。

      6.下列的代码是如何来做的呢?





      7.这符合OCP吗?

      8.当每次财务部提出新的计价策略,我们都不得不要修改totalPrice()方法!这并非"对更改是封闭的"。显然,策略的变更便意味着我们不得不要在一些地方修改代码的,因此我们该如何去做呢?

      9.为了使用我们第一个版本的totalPrice(),我们可以将计价策略合并到Part的getPrice()方法中。


      10.这里是Part和ConcretePart类的示例:



      11. 但是现在每当计价策略发生改变,我们就必须修改Part的每个子类!

      12.一个更好的思路是采用一个PricePolicy类,通过对其进行继承以提供不同的计价策略:




      13.看起来我们所做的就是将问题推迟到另一个类中。但是使用该解决方案,我们可通过改变Part对象,在运行期间动态地来设定计价的策略。

      14.另一个解决方案是使每个ConcretePart从数据库或属性文件中获取其当前的价格。





    • 单选法则



      单选法则(the Single Choice Principle)是OCP的一个推论。

      无论在什么时候,一个软件系统必须支持一组备选项,理想情况下,在系统中只能有一个类能够知道整个的备选项集合。


      法则4:Liskov替换法则(LSP)

      使用指向基类(超类)的引用的函数,必须能够在不知道具体派生类(子类)对象类型的情况下使用它们。

      [ Function Thar Use Referennces To Base(Super) Classes Must Be Able To Use Objects
      Of Derived(Sub) Classes Without Knowing It ]




      • Liskov替换法则





        1.显而易见,Liskov替换法则(LSP)是根据我所熟知的"多态"而得出的。

        2.例如:



        方法drawShape应该可与Sharp超类的任何子类一起工作(或者,若Sharp为Java接口,则该方法可与任何实现了Sharp接口的类一起工作)

        但是当我们在实现子类时必须要谨慎对待,以确保我们不会无意中违背了LSP。





        3.若一个函数未能满足LSP,那么可能是因为它显式地引用了超类的一些或所有子类。这样的函数也违背了OCP,因为当我们创建一个新的子类时,会不得不进行代码的修改。




      • LSP示例



        1. 考虑下面Rectangle类:



        2.现在,Square类会如何呢?显然,一个正方形是一个四边形,因此Square类应该从Rectangle类派生而来,对否?让我们看一看!

        3.观察可得:

        a.正方形不需要将高和宽都作为属性,但是总之它将继承自Rectangle。因此,每一个Square对象会浪费一点内存,但这并不是一个主要问题。

        b.继承而来的setWidth()和setHeight()方法对于Square而言并非真正地适合,因为一个正方形的高和宽是相同。因此我们将需要重写setWidth()和setHeight()方法。不得不重写这些简单的方法有可能是一种不恰当的继承使用方式。


        3.Square类如下:










      4. 看起来都还不错。但是让我们检验一下!








      5. 测试程序输出:







      6.看上去好像我们违背了LSP!


      7.这里的问题出在哪里呢?编写testLsp()方法的程序员做了一个合理的假设,即改变Rectangle的宽而保持它的高不变。

      8.在将一个Square对象传递给这样一个方法时产生了问题,显然是违背了LSP

      9.Square和Rectangle类是相互一致和合法的。尽管程序员对基类作了合理的假设,但其所编写的方法仍然会导致设计模型的失败。

      10.不能孤立地去看待解决方案,必须根据设计用户所做的合理假设来看待它们。


      11. 一个数学意义上的正方形可能是一个四边形,但是一个Square对象不是一个Rectangle对象,因为一个Square对象的行为与一个Rectangle对象的行为是不一致的!

      12.从行为上来说,一个Square不是一个Rectangle!一个Square对象与一个Rectangle对象之间不具有多态的特征。






      • 总结





        1.Liskov替换法则(LSP)清楚地表明了ISA关系全部都是与行为有关的。

        2.为了保持LSP(并与开放-封闭法则一起),所有子类必须符合使用基类的client所期望的行为。

        3.一个子类型不得具有比基类型(base type)更多的限制,可能这对于基类型来说是合法的,但是可能会因为违背子类型的其中一个额外限制,从而违背了LSP!

        4.LSP保证一个子类总是能够被用在其基类可以出现的地方!

posted @ 2007-07-02 13:11 和田雨 阅读(200) | 评论 (0)编辑 收藏

     摘要: 摘要:单点登录(SSO)的技术被越来越广泛地运用到各个领域的软件系统当中。本文从业务的角度分析了单点登录的需求和应用领域;从技术本身的角度分析了单点登录技术的内部机制和实现手段,并且给出Web-SSO和桌面SSO的实现、源代码和详细讲解;还从安全和性能的角度对现有的实现技术进行进一步分析,指出相应的风险和需要改进的方面。本文除了从多个方面和角度给出了对单点登录(SSO)的全面分析,还并且讨论了如何...  阅读全文
posted @ 2007-07-02 13:10 和田雨 阅读(613) | 评论 (0)编辑 收藏

     摘要: JDK 1.4以前,Java的IO操作集中在java.io这个包中,是基于流的阻塞(blocking)API。对于大多数应用来说,这样的API使用很方便,然而,一些对性能要求较高的应用,尤其是服务端应用,往往需要一个更为有效的方式来处理IO。从JDK 1.4起,NIO API作为一个基于缓冲区,并能提供非阻塞(non-blocking)IO操作的API被引入。本文对其进行深入的介绍。  ...  阅读全文
posted @ 2007-07-02 13:07 和田雨 阅读(247) | 评论 (0)编辑 收藏

1 定义头和根元素

部署描述符文件就像所有XML文件一样,必须以一个XML头开始。这个头声明可以使用的XML版本并给出文件的字符编码。
DOCYTPE声明必须立即出现在此头之后。这个声明告诉服务器适用的servlet规范的版本(如2.2或2.3)并指定管理此文件其余部分内容的语法的DTD(Document Type Definition,文档类型定义)。
所有部署描述符文件的顶层(根)元素为web-app。请注意,XML元素不像HTML,他们是大小写敏感的。因此,web-App和WEB-APP都是不合法的,web-app必须用小写。

1 定义头和根元素

XML 元素不仅是大小写敏感的,而且它们还对出现在其他元素中的次序敏感。例如,XML头必须是文件中的第一项,DOCTYPE声明必须是第二项,而web- app元素必须是第三项。在web-app元素内,元素的次序也很重要。服务器不一定强制要求这种次序,但它们允许(实际上有些服务器就是这样做的)完全 拒绝执行含有次序不正确的元素的Web应用。这表示使用非标准元素次序的web.xml文件是不可移植的。
下面的列表给出了所有可直接出现在web-app元素内的合法元素所必需的次序。例如,此列表说明servlet元素必须出现在所有servlet-mapping元素之前。请注意,所有这些元素都是可选的。因此,可以省略掉某一元素,但不能把它放于不正确的位置。
l icon icon元素指出IDE和GUI工具用来表示Web应用的一个和两个图像文件的位置。
l display-name display-name元素提供GUI工具可能会用来标记这个特定的Web应用的一个名称。
l description description元素给出与此有关的说明性文本。
l context-param context-param元素声明应用范围内的初始化参数。
l filter 过滤器元素将一个名字与一个实现javax.servlet.Filter接口的类相关联。
l filter-mapping 一旦命名了一个过滤器,就要利用filter-mapping元素把它与一个或多个servlet或JSP页面相关联。
l listener servlet API的版本2.3增加了对事件监听程序的支持,事件监听程序在建立、修改和删除会话或servlet环境时得到通知。Listener元素指出事件监听程序类。
l servlet 在向servlet或JSP页面制定初始化参数或定制URL时,必须首先命名servlet或JSP页面。Servlet元素就是用来完成此项任务的。
l servlet-mapping 服务器一般为servlet提供一个缺省的URL:http://host/webAppPrefix/servlet/ServletName。但是,常常会更改这个URL,以便servlet可以访问初始化参数或更容易地处理相对URL。在更改缺省URL时,使用servlet-mapping元素。
l session-config 如果某个会话在一定时间内未被访问,服务器可以抛弃它以节省内存。可通过使用HttpSession的setMaxInactiveInterval方法 明确设置单个会话对象的超时值,或者可利用session-config元素制定缺省超时值。
l mime-mapping 如果Web应用具有想到特殊的文件,希望能保证给他们分配特定的MIME类型,则mime-mapping元素提供这种保证。
l welcom-file-list welcome-file-list元素指示服务器在收到引用一个目录名而不是文件名的URL时,使用哪个文件。
l error-page error-page元素使得在返回特定HTTP状态代码时,或者特定类型的异常被抛出时,能够制定将要显示的页面。
l taglib taglib元素对标记库描述符文件(Tag Libraryu Descriptor file)指定别名。此功能使你能够更改TLD文件的位置,而不用编辑使用这些文件的JSP页面。
l resource-env-ref resource-env-ref元素声明与资源相关的一个管理对象。
l resource-ref resource-ref元素声明一个资源工厂使用的外部资源。
l security-constraint security-constraint元素制定应该保护的URL。它与login-config元素联合使用
l login-config 用login-config元素来指定服务器应该怎样给试图访问受保护页面的用户授权。它与sercurity-constraint元素联合使用。
l security-role security-role元素给出安全角色的一个列表,这些角色将出现在servlet元素内的security-role-ref元素的role-name子元素中。分别地声明角色可使高级IDE处理安全信息更为容易。
l env-entry env-entry元素声明Web应用的环境项。
l ejb-ref ejb-ref元素声明一个EJB的主目录的引用。
l ejb-local-ref ejb-local-ref元素声明一个EJB的本地主目录的应用。

3 分配名称和定制的UL

在web.xml中完成的一个最常见的任务是对servlet或JSP页面给出名称和定制的URL。用servlet元素分配名称,使用servlet-mapping元素将定制的URL与刚分配的名称相关联。
3.1 分配名称
为 了提供初始化参数,对servlet或JSP页面定义一个定制URL或分配一个安全角色,必须首先给servlet或JSP页面一个名称。可通过 servlet元素分配一个名称。最常见的格式包括servlet-name和servlet-class子元素(在web-app元素内),如下所示:
<servlet>
<servlet-name>Test</servlet-name>
<servlet-class>moreservlets.TestServlet</servlet-class>
</servlet> 
这 表示位于WEB-INF/classes/moreservlets/TestServlet的servlet已经得到了注册名Test。给 servlet一个名称具有两个主要的含义。首先,初始化参数、定制的URL模式以及其他定制通过此注册名而不是类名引用此servlet。其次,可在 URL而不是类名中使用此名称。因此,利用刚才给出的定义,URL http://host/webAppPrefix/servlet/Test 可用于 http://host/webAppPrefix/servlet/moreservlets.TestServlet 的场所。
请 记住:XML元素不仅是大小写敏感的,而且定义它们的次序也很重要。例如,web-app元素内所有servlet元素必须位于所有servlet- mapping元素(下一小节介绍)之前,而且还要位于5.6节和5.11节讨论的与过滤器或文档相关的元素(如果有的话)之前。类似地,servlet 的servlet-name子元素也必须出现在servlet-class之前。5.2节"部署描述符文件内的元素次序"将详细介绍这种必需的次序。
例 如,程序清单5-1给出了一个名为TestServlet的简单servlet,它驻留在moreservlets程序包中。因为此servlet是扎根 在一个名为deployDemo的目录中的Web应用的组成部分,所以TestServlet.class放在deployDemo/WEB- INF/classes/moreservlets中。程序清单5-2给出将放置在deployDemo/WEB-INF/内的web.xml文件的一部 分。此web.xml文件使用servlet-name和servlet-class元素将名称Test与TestServlet.class相关联。图 5-1和图5-2分别显示利用缺省URL和注册名调用TestServlet时的结果。

程序清单5-1 TestServlet.java
package moreservlets;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

/** Simple servlet used to illustrate servlet naming
* and custom URLs.
* <P>
* Taken from More Servlets and JavaServer Pages
* from Prentice Hall and Sun Microsystems Press,
http://www.moreservlets.com/.
* © 2002 Marty Hall; may be freely used or adapted.
*/

public class TestServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String uri = request.getRequestURI();
out.println(ServletUtilities.headWithTitle("Test Servlet") +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H2>URI: " + uri + "</H2>\n" +
"</BODY></HTML>");
}
}


程序清单5-2 web.xml(说明servlet名称的摘录)
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
<!-- … -->
<servlet>
<servlet-name>Test</servlet-name>
<servlet-class>moreservlets.TestServlet</servlet-class>
</servlet>
<!-- … -->
</web-app>

3.2 定义定制的URL
大多数服务器具有一个缺省的serlvet URL:
http://host/webAppPrefix/servlet/packageName.ServletName。 虽然在开发中使用这个URL很方便,但是我们常常会希望另一个URL用于部署。例如,可能会需要一个出现在Web应用顶层的URL(如,http: //host/webAppPrefix/Anyname),并且在此URL中没有servlet项。位于顶层的URL简化了相对URL的使用。此外,对 许多开发人员来说,顶层URL看上去比更长更麻烦的缺省URL更简短。
事实上,有时需要使用定制的URL。比如,你可能想关闭缺省URL映射,以便更好地强制实施安全限制或防止用户意外地访问无初始化参数的servlet。如果你禁止了缺省的URL,那么你怎样访问servlet呢?这时只有使用定制的URL了。
为 了分配一个定制的URL,可使用servlet-mapping元素及其servlet-name和url-pattern子元素。Servlet- name元素提供了一个任意名称,可利用此名称引用相应的servlet;url-pattern描述了相对于Web应用的根目录的URL。url- pattern元素的值必须以斜杠(/)起始。
下面给出一个简单的web.xml摘录,它允许使用URL http://host/webAppPrefix/UrlTest而不是http://host/webAppPrefix/servlet/Test或
http: //host/webAppPrefix/servlet/moreservlets.TestServlet。请注意,仍然需要XML头、 DOCTYPE声明以及web-app封闭元素。此外,可回忆一下,XML元素出现地次序不是随意的。特别是,需要把所有servlet元素放在所有 servlet-mapping元素之前。
<servlet>
<servlet-name>Test</servlet-name>
<servlet-class>moreservlets.TestServlet</servlet-class>
</servlet>
<!-- ... -->
<servlet-mapping>
<servlet-name>Test</servlet-name>
<url-pattern>/UrlTest</url-pattern>
</servlet-mapping>
URL模式还可以包含通配符。例如,下面的小程序指示服务器发送所有以Web应用的URL前缀开始,以..asp结束的请求到名为BashMS的servlet。
<servlet>
<servlet-name>BashMS</servlet-name>
<servlet-class>msUtils.ASPTranslator</servlet-class>
</servlet>
<!-- ... -->
<servlet-mapping>
<servlet-name>BashMS</servlet-name>
<url-pattern>/*.asp</url-pattern>
</servlet-mapping>
3.3 命名JSP页面
因 为JSP页面要转换成sevlet,自然希望就像命名servlet一样命名JSP页面。毕竟,JSP页面可能会从初始化参数、安全设置或定制的URL中 受益,正如普通的serlvet那样。虽然JSP页面的后台实际上是servlet这句话是正确的,但存在一个关键的猜疑:即,你不知道JSP页面的实际 类名(因为系统自己挑选这个名字)。因此,为了命名JSP页面,可将jsp-file元素替换为servlet-calss元素,如下所示:
<servlet>
<servlet-name>Test</servlet-name>
<jsp-file>/TestPage.jsp</jsp-file>
</servlet>
命 名JSP页面的原因与命名servlet的原因完全相同:即为了提供一个与定制设置(如,初始化参数和安全设置)一起使用的名称,并且,以便能更改激活 JSP页面的URL(比方说,以便多个URL通过相同页面得以处理,或者从URL中去掉.jsp扩展名)。但是,在设置初始化参数时,应该注意,JSP页 面是利用jspInit方法,而不是init方法读取初始化参数的。
例如,程序清单5-3给出一个名为TestPage.jsp的简单JSP页面,它的工作只是打印出用来激活它的URL的本地部分。TestPage.jsp放置在deployDemo应用的顶层。程序清单5-4给出了用来分配一个注册名PageName,然后将此注册名与http://host/webAppPrefix/UrlTest2/anything 形式的URL相关联的web.xml文件(即,deployDemo/WEB-INF/web.xml)的一部分。

程序清单5-3 TestPage.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>
JSP Test Page
</TITLE>
</HEAD>
<BODY BGCOLOR="#FDF5E6">
<H2>URI: <%= request.getRequestURI() %></H2>
</BODY>
</HTML>


程序清单5-4 web.xml(说明JSP页命名的摘录)
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
<!-- ... -->
<servlet>
<servlet-name>PageName</servlet-name>
<jsp-file>/TestPage.jsp</jsp-file>
</servlet>
<!-- ... -->
<servlet-mapping>
<servlet-name> PageName </servlet-name>
<url-pattern>/UrlTest2/*</url-pattern>
</servlet-mapping>
<!-- ... -->
</web-app>


4 禁止激活器servlet

对servlet 或JSP页面建立定制URL的一个原因是,这样做可以注册从 init(servlet)或jspInit(JSP页面)方法中读取得初始化参数。但是,初始化参数只在是利用定制URL模式或注册名访问 servlet或JSP页面时可以使用,用缺省URL http://host/webAppPrefix/servlet/ServletName 访问时不能使用。因此,你可能会希望关闭缺省URL,这样就不会有人意外地调用初始化servlet了。这个过程有时称为禁止激活器servlet,因为 多数服务器具有一个用缺省的servlet URL注册的标准servlet,并激活缺省的URL应用的实际servlet。
有两种禁止此缺省URL的主要方法:
l 在每个Web应用中重新映射/servlet/模式。
l 全局关闭激活器servlet。
重 要的是应该注意到,虽然重新映射每个Web应用中的/servlet/模式比彻底禁止激活servlet所做的工作更多,但重新映射可以用一种完全可移植 的方式来完成。相反,全局禁止激活器servlet完全是针对具体机器的,事实上有的服务器(如ServletExec)没有这样的选择。下面的讨论对每 个Web应用重新映射/servlet/ URL模式的策略。后面提供在Tomcat中全局禁止激活器servlet的详细内容。
4.1 重新映射/servlet/URL模式
在一个特定的Web应用中禁止以http://host/webAppPrefix/servlet/ 开始的URL的处理非常简单。所需做的事情就是建立一个错误消息servlet,并使用前一节讨论的url-pattern元素将所有匹配请求转向该 servlet。只要简单地使用:
<url-pattern>/servlet/*</url-pattern>
作为servlet-mapping元素中的模式即可。
例如,程序清单5-5给出了将SorryServlet servlet(程序清单5-6)与所有以http://host/webAppPrefix/servlet/ 开头的URL相关联的部署描述符文件的一部分。

程序清单5-5 web.xml(说明JSP页命名的摘录)
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
<!-- ... -->
<servlet>
<servlet-name>Sorry</servlet-name>
<servlet-class>moreservlets.SorryServlet</servlet-class>
</servlet>
<!-- ... -->
<servlet-mapping>
<servlet-name> Sorry </servlet-name>
<url-pattern>/servlet/*</url-pattern>
</servlet-mapping>
<!-- ... -->
</web-app>


程序清单5-6 SorryServlet.java
package moreservlets;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

/** Simple servlet used to give error messages to
* users who try to access default servlet URLs
* (i.e., http://host/webAppPrefix/servlet/ServletName)
* in Web applications that have disabled this
* behavior.
* <P>
* Taken from More Servlets and JavaServer Pages
* from Prentice Hall and Sun Microsystems Press,
* http://www.moreservlets.com/.
* © 2002 Marty Hall; may be freely used or adapted.
*/

public class SorryServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "Invoker Servlet Disabled.";
out.println(ServletUtilities.headWithTitle(title) +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H2>" + title + "</H2>\n" +
"Sorry, access to servlets by means of\n" +
"URLs that begin with\n" +
"http://host/webAppPrefix/servlet/\n" +
"has been disabled.\n" + 
"</BODY></HTML>");
}

public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}


4.2 全局禁止激活器:Tomcat
Tomcat 4中用来关闭缺省URL的方法与Tomcat 3中所用的很不相同。下面介绍这两种方法:
1.禁止激活器: Tomcat 4
Tomcat 4用与前面相同的方法关闭激活器servlet,即利用web.xml中的url-mapping元素进行关闭。不同之处在于Tomcat使用了放在 install_dir/conf中的一个服务器专用的全局web.xml文件,而前面使用的是存放在每个Web应用的WEB-INF目录中的标准 web.xml文件。
因此,为了在Tomcat 4中关闭激活器servlet,只需在install_dir/conf/web.xml中简单地注释出/servlet/* URL映射项即可,如下所示:
<!-- 
<servlet-mapping>
<servlet-name>invoker</servlet-name>
<url-pattern>/servlet/*</url-pattern>
</servlet-mapping>
-->
再次提醒,应该注意这个项是位于存放在install_dir/conf的Tomcat专用的web.xml文件中的,此文件不是存放在每个Web应用的WEB-INF目录中的标准web.xml。
2.禁止激活器:Tomcat3
在Apache Tomcat的版本3中,通过在install_dir/conf/server.xml中注释出InvokerInterceptor项全局禁止缺省 servlet URL。例如,下面是禁止使用缺省servlet URL的server.xml文件的一部分。
<!-- 
<RequsetInterceptor 
className="org.apache.tomcat.request.InvokerInterceptor"
debug="0" prefix="/servlet/" />
-->

5 初始化和预装载servlet与JSP页面

这里讨论控制servlet和JSP页面的启动行为的方法。特别是,说明了怎样分配初始化参数以及怎样更改服务器生存期中装载servlet和JSP页面的时刻。
5.1 分配servlet初始化参数
利 用init-param元素向servlet提供初始化参数,init-param元素具有param-name和param-value子元素。例如, 在下面的例子中,如果initServlet servlet是利用它的注册名(InitTest)访问的,它将能够从其方法中调用getServletConfig(). getInitParameter("param1")获得"Value 1",调用getServletConfig().getInitParameter("param2")获得"2"。
<servlet>
<servlet-name>InitTest</servlet-name>
<servlet-class>moreservlets.InitServlet</servlet-class>
<init-param>
<param-name>param1</param-name>
<param-value>value1</param-value>
</init-param>
<init-param>
<param-name>param2</param-name>
<param-value>2</param-value>
</init-param>
</servlet>
在涉及初始化参数时,有几点需要注意:
l 返回值。GetInitParameter的返回值总是一个String。因此,在前一个例子中,可对param2使用Integer.parseInt获得一个int。
l JSP中的初始化。JSP页面使用jspInit而不是init。JSP页面还需要使用jsp-file元素代替servlet-class。
l 缺省URL。初始化参数只在通过它们的注册名或与它们注册名相关的定制URL模式访问Servlet时可以使用。因此,在这个例子中,param1和 param2初始化参数将能够在使用URL http://host/webAppPrefix/servlet/InitTest 时可用,但在使用URL http://host/webAppPrefix/servlet/myPackage.InitServlet 时不能使用。
例如,程序清单5-7给出一个名为InitServlet的简单servlet,它使用init方法设置firstName和emailAddress字段。程序清单5-8给出分配名称InitTest给servlet的web.xml文件。
程序清单5-7 InitServlet.java
package moreservlets;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

/** Simple servlet used to illustrate servlet
* initialization parameters.
* <P>
* Taken from More Servlets and JavaServer Pages
* from Prentice Hall and Sun Microsystems Press,
* http://www.moreservlets.com/.
* © 2002 Marty Hall; may be freely used or adapted.
*/

public class InitServlet extends HttpServlet {
private String firstName, emailAddress;

public void init() {
ServletConfig config = getServletConfig();
firstName = config.getInitParameter("firstName");
emailAddress = config.getInitParameter("emailAddress");
}

public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String uri = request.getRequestURI();
out.println(ServletUtilities.headWithTitle("Init Servlet") +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H2>Init Parameters:</H2>\n" +
"<UL>\n" +
"<LI>First name: " + firstName + "\n" +
"<LI>Email address: " + emailAddress + "\n" +
"</UL>\n" + 
"</BODY></HTML>");
}
}


程序清单5-8 web.xml(说明初始化参数的摘录)
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
<!-- ... -->
<servlet>
<servlet-name>InitTest</servlet-name>
<servlet-class>moreservlets.InitServlet</servlet-class>
<init-param>
<param-name>firstName</param-name>
<param-value>Larry</param-value>
</init-param>
<init-param>
<param-name>emailAddress</param-name>
<param-value>Ellison@Microsoft.com</param-value>
</init-param>
</servlet>
<!-- ... -->
</web-app>

5.2 分配JSP初始化参数
给JSP页面提供初始化参数在三个方面不同于给servlet提供初始化参数。
1)使用jsp-file而不是servlet-class。因此,WEB-INF/web.xml文件的servlet元素如下所示:
<servlet>
<servlet-name>PageName</servlet-name>
<jsp-file>/RealPage.jsp</jsp-file>
<init-param>
<param-name>...</param-name>
<param-value>...</param-value>
</init-param>
...
</servlet>
2) 几乎总是分配一个明确的URL模式。对servlet,一般相应地使用以http://host/webAppPrefix/servlet/ 开始的缺省URL。只需记住,使用注册名而不是原名称即可。这对于JSP页面在技术上也是合法的。例如,在上面给出的例子中,可用URL http://host/webAppPrefix/servlet/PageName 访问RealPage.jsp的对初始化参数具有访问权的版本。但在用于JSP页面时,许多用户似乎不喜欢应用常规的servlet的URL。此外,如果 JSP页面位于服务器为其提供了目录清单的目录中(如,一个既没有index.html也没有index.jsp文件的目录),则用户可能会连接到此 JSP页面,单击它,从而意外地激活未初始化的页面。因此,好的办法是使用url-pattern(5.3节)将JSP页面的原URL与注册的 servlet名相关联。这样,客户机可使用JSP页面的普通名称,但仍然激活定制的版本。例如,给定来自项目1的servlet定义,可使用下面的 servlet-mapping定义:
<servlet-mapping>
<servlet-name>PageName</servlet-name>
<url-pattern>/RealPage.jsp</url-pattern>
</servlet-mapping>
3)JSP页使用jspInit而不是init。自动从JSP页面建立的servlet或许已经使用了inti方法。因此,使用JSP声明提供一个init方法是不合法的,必须制定jspInit方法。
为了说明初始化JSP页面的过程,程序清单5-9给出了一个名为InitPage.jsp的JSP页面,它包含一个jspInit方法且放置于 deployDemo Web应用层次结构的顶层。一般,http://host/deployDemo/InitPage.jsp 形式的URL将激活此页面的不具有初始化参数访问权的版本,从而将对firstName和emailAddress变量显示null。但是, web.xml文件(程序清单5-10)分配了一个注册名,然后将该注册名与URL模式/InitPage.jsp相关联。

程序清单5-9 InitPage.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD><TITLE>JSP Init Test</TITLE></HEAD>
<BODY BGCOLOR="#FDF5E6">
<H2>Init Parameters:</H2>
<UL>
<LI>First name: <%= firstName %>
<LI>Email address: <%= emailAddress %>
</UL>
</BODY></HTML>
<%!
private String firstName, emailAddress;

public void jspInit() {
ServletConfig config = getServletConfig();
firstName = config.getInitParameter("firstName");
emailAddress = config.getInitParameter("emailAddress");
}
%>


程序清单5-10 web.xml(说明JSP页面的init参数的摘录)
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
<!-- ... -->
<servlet>
<servlet-name>InitPage</servlet-name>
<jsp-file>/InitPage.jsp</jsp-file>
<init-param>
<param-name>firstName</param-name>
<param-value>Bill</param-value>
</init-param>
<init-param>
<param-name>emailAddress</param-name>
<param-value>gates@oracle.com</param-value>
</init-param>
</servlet>
<!-- ... --> 
<servlet-mapping>
<servlet-name> InitPage</servlet-name>
<url-pattern>/InitPage.jsp</url-pattern>
</servlet-mapping>
<!-- ... -->
</web-app>


5.3 提供应用范围内的初始化参数
一 般,对单个地servlet或JSP页面分配初始化参数。指定的servlet或JSP页面利用ServletConfig的 getInitParameter方法读取这些参数。但是,在某些情形下,希望提供可由任意servlet或JSP页面借助ServletContext 的getInitParameter方法读取的系统范围内的初始化参数。
可利用context-param元素声明这些系统范围内的初始化值。context-param元素应该包含param-name、param-value以及可选的description子元素,如下所示:
<context-param>
<param-name>support-email</param-name>
<param-value>blackhole@mycompany.com</param-value>
</context-param>
可 回忆一下,为了保证可移植性,web.xml内的元素必须以正确的次序声明。但这里应该注意,context-param元素必须出现任意与文档有关的元 素(icon、display-name或description)之后及filter、filter-mapping、listener或 servlet元素之前。
5.4 在服务器启动时装载servlet
假如servlet或JSP页面有一个要花很长时间执行的init (servlet)或jspInit(JSP)方法。例如,假如init或jspInit方法从某个数据库或ResourceBundle查找产量。这种 情况下,在第一个客户机请求时装载servlet的缺省行为将对第一个客户机产生较长时间的延迟。因此,可利用servlet的load-on- startup元素规定服务器在第一次启动时装载servlet。下面是一个例子。
<servlet>
<servlet-name> … </servlet-name>
<servlet-class> … </servlet-class> <!-- Or jsp-file -->
<load-on-startup/>
</servlet>
可 以为此元素体提供一个整数而不是使用一个空的load-on-startup。想法是服务器应该在装载较大数目的servlet或JSP页面之前装载较少 数目的servlet或JSP页面。例如,下面的servlet项(放置在Web应用的WEB-INF目录下的web.xml文件中的web-app元素 内)将指示服务器首先装载和初始化SearchServlet,然后装载和初始化由位于Web应用的result目录中的index.jsp文件产生的 servlet。
<servlet>
<servlet-name>Search</servlet-name>
<servlet-class>myPackage.SearchServlet</servlet-class> <!-- Or jsp-file -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>Results</servlet-name>
<servlet-class>/results/index.jsp</servlet-class> <!-- Or jsp-file -->
<load-on-startup>2</load-on-startup>
</servlet>

6 声明过滤器

servlet版本2.3引入了过滤器的概念。虽然所有支持servlet API版本2.3的服务器都支持过滤器,但为了使用与过滤器有关的元素,必须在web.xml中使用版本2.3的DTD。
过 滤器可截取和修改进入一个servlet或JSP页面的请求或从一个servlet或JSP页面发出的相应。在执行一个servlet或JSP页面之前, 必须执行第一个相关的过滤器的doFilter方法。在该过滤器对其FilterChain对象调用doFilter时,执行链中的下一个过滤器。如果没 有其他过滤器,servlet或JSP页面被执行。过滤器具有对到来的ServletRequest对象的全部访问权,因此,它们可以查看客户机名、查找 到来的cookie等。为了访问servlet或JSP页面的输出,过滤器可将响应对象包裹在一个替身对象(stand-in object)中,比方说把输出累加到一个缓冲区。在调用FilterChain对象的doFilter方法之后,过滤器可检查缓冲区,如有必要,就对它 进行修改,然后传送到客户机。
例如,程序清单5-11帝国难以了一个简单的过滤器,只要访问相关的servlet或JSP页面,它就截取请求并在标准输出上打印一个报告(开发过程中在桌面系统上运行时,大多数服务器都可以使用这个过滤器)。

程序清单5-11 ReportFilter.java
package moreservlets;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;

/** Simple filter that prints a report on the standard output 
* whenever the associated servlet or JSP page is accessed.
* <P>
* Taken from More Servlets and JavaServer Pages
* from Prentice Hall and Sun Microsystems Press,
* http://www.moreservlets.com/.
* © 2002 Marty Hall; may be freely used or adapted.
*/

public class ReportFilter implements Filter {
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws ServletException, IOException {
HttpServletRequest req = (HttpServletRequest)request;
System.out.println(req.getRemoteHost() +
" tried to access " +
req.getRequestURL() +
" on " + new Date() + ".");
chain.doFilter(request,response);
}

public void init(FilterConfig config)
throws ServletException {
}

public void destroy() {}
}

一 旦建立了一个过滤器,可以在web.xml中利用filter元素以及filter-name(任意名称)、file-class(完全限定的类名)和 (可选的)init-params子元素声明它。请注意,元素在web.xml的web-app元素中出现的次序不是任意的;允许服务器(但不是必需的) 强制所需的次序,并且实际中有些服务器也是这样做的。但这里要注意,所有filter元素必须出现在任意filter-mapping元素之前, filter-mapping元素又必须出现在所有servlet或servlet-mapping元素之前。
例如,给定上述的ReportFilter类,可在web.xml中作出下面的filter声明。它把名称Reporter与实际的类ReportFilter(位于moreservlets程序包中)相关联。
<filter>
<filter-name>Reporter</filter-name>
<filter-class>moresevlets.ReportFilter</filter-class>
</filter>
一旦命名了一个过滤器,可利用filter-mapping元素把它与一个或多个servlet或JSP页面相关联。关于此项工作有两种选择。
首 先,可使用filter-name和servlet-name子元素把此过滤器与一个特定的servlet名(此servlet名必须稍后在相同的 web.xml文件中使用servlet元素声明)关联。例如,下面的程序片断指示系统只要利用一个定制的URL访问名为SomeServletName 的servlet或JSP页面,就运行名为Reporter的过滤器。
<filter-mapping>
<filter-name>Reporter</filter-name>
<servlet-name>SomeServletName</servlet-name>
</filter-mapping>
其次,可利用filter-name和url-pattern子元素将过滤器与一组servlet、JSP页面或静态内容相关联。例如,相面的程序片段指示系统只要访问Web应用中的任意URL,就运行名为Reporter的过滤器。
<filter-mapping>
<filter-name>Reporter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
例 如,程序清单5-12给出了将ReportFilter过滤器与名为PageName的servlet相关联的web.xml文件的一部分。名字 PageName依次又与一个名为TestPage.jsp的JSP页面以及以模式http: //host/webAppPrefix/UrlTest2/ 开头的URL相关联。TestPage.jsp的源代码已经JSP页面命名的谈论在前面的3节"分配名称和定制的URL"中给出。事实上,程序清单5- 12中的servlet和servlet-name项从该节原封不动地拿过来的。给定这些web.xml项,可看到下面的标准输出形式的调试报告(换行是 为了容易阅读)。
audit.irs.gov tried to access 
http://mycompany.com/deployDemo/UrlTest2/business/tax-plan.html
on Tue Dec 25 13:12:29 EDT 2001.

程序清单5-12 Web.xml(说明filter用法的摘录)
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
<filter>
<filter-name>Reporter</filter-name>
<filter-class>moresevlets.ReportFilter</filter-class>
</filter>
<!-- ... -->
<filter-mapping>
<filter-name>Reporter</filter-name>
<servlet-name>PageName</servlet-name>
</filter-mapping>
<!-- ... -->
<servlet>
<servlet-name>PageName</servlet-name>
<jsp-file>/RealPage.jsp</jsp-file>
</servlet>
<!-- ... -->
<servlet-mapping>
<servlet-name> PageName </servlet-name>
<url-pattern>/UrlTest2/*</url-pattern>
</servlet-mapping>
<!-- ... -->
</web-app>


7 指定欢迎页

假 如用户提供了一个像http: //host/webAppPrefix/directoryName/ 这样的包含一个目录名但没有包含文件名的URL,会发生什么事情呢?用户能得到一个目录表?一个错误?还是标准文件的内容?如果得到标准文件内容,是 index.html、index.jsp、default.html、default.htm或别的什么东西呢?
Welcome-file-list 元素及其辅助的welcome-file元素解决了这个模糊的问题。例如,下面的web.xml项指出,如果一个URL给出一个目录名但未给出文件名,服 务器应该首先试用index.jsp,然后再试用index.html。如果两者都没有找到,则结果有赖于所用的服务器(如一个目录列表)。
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
虽然许多服务器缺省遵循这种行为,但不一定必须这样。因此,明确地使用welcom-file-list保证可移植性是一种良好的习惯。

8 指定处理错误的页面

现 在我了解到,你在开发servlet和JSP页面时从不会犯错误,而且你的所有页面是那样的清晰,一般的程序员都不会被它们的搞糊涂。但是,是人总会犯错 误的,用户可能会提供不合规定的参数,使用不正确的URL或者不能提供必需的表单字段值。除此之外,其它开发人员可能不那么细心,他们应该有些工具来克服 自己的不足。
error-page元素就是用来克服这些问题的。它有两个可能的子元素,分别是:error-code和exception- type。第一个子元素error-code指出在给定的HTTP错误代码出现时使用的URL。第二个子元素excpetion-type指出在出现某个 给定的Java异常但未捕捉到时使用的URL。error-code和exception-type都利用location元素指出相应的URL。此 URL必须以/开始。location所指出的位置处的页面可通过查找HttpServletRequest对象的两个专门的属性来访问关于错误的信息, 这两个属性分别是:javax.servlet.error.status_code和javax.servlet.error.message。
可回忆一下,在web.xml内以正确的次序声明web-app的子元素很重要。这里只要记住,error-page出现在web.xml文件的末尾附近,servlet、servlet-name和welcome-file-list之后即可。

8.1 error-code元素
为了更好地了解error-code元素的值,可考虑一下如果不正确地输入文件名,大多数站点会作出什么反映。这样做一般会出现一个404错误信息,它表示不能找到该文件,但几乎没提供更多有用的信息。另一方面,可以试一下在www.microsoft.com、www.ibm.com 处或者特别是在www.bea.com 处输出未知的文件名。这是会得出有用的消息,这些消息提供可选择的位置,以便查找感兴趣的页面。提供这样有用的错误页面对于Web应用来说是很有价值得。 事实上rm-error-page子元素)。由form-login-page给出的HTML表单必须具有一个j_security_check的 ACTION属性、一个名为j_username的用户名文本字段以及一个名为j_password的口令字段。
例如,程序清单5-19指示服务器使用基于表单的验证。Web应用的顶层目录中的一个名为login.jsp的页面将收集用户名和口令,并且失败的登陆将由相同目录中名为login-error.jsp的页面报告。

程序清单5-19 web.xml(说明login-config的摘录)
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
<!-- ... -->
<security-constraint> ... </security-constraint>
<login-config>
<auth-method> FORM </auth-method>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/login-error.jsp</form-error-page>
</form-login-config>
</login-config>
<!-- ... -->
</web-app>


9.2 限制对Web资源的访问
现 在,可以指示服务器使用何种验证方法了。"了不起,"你说道,"除非我能指定一个来收到保护的 URL,否则没有多大用处。"没错。指出这些URL并说明他们应该得到何种保护正是security-constriaint元素的用途。此元素在 web.xml中应该出现在login-config的紧前面。它包含是个可能的子元素,分别是:web-resource-collection、 auth-constraint、user-data-constraint和display-name。下面各小节对它们进行介绍。
l web-resource-collection
此 元素确定应该保护的资源。所有security-constraint元素都必须包含至少一个web-resource-collection项。此元素 由一个给出任意标识名称的web-resource-name元素、一个确定应该保护的URL的url-pattern元素、一个指出此保护所适用的 HTTP命令(GET、POST等,缺省为所有方法)的http-method元素和一个提供资料的可选description元素组成。例如,下面的 Web-resource-collection项(在security-constratint元素内)指出Web应用的proprietary目录中 所有文档应该受到保护。
<security-constraint>
<web-resource-coolection>
<web-resource-name>Proprietary</web-resource-name>
<url-pattern>/propritary/*</url-pattern>
</web-resource-coolection>
<!-- ... -->
</security-constraint>
重 要的是应该注意到,url-pattern仅适用于直接访问这些资源的客户机。特别是,它不适合于通过MVC体系结构利用 RequestDispatcher来访问的页面,或者不适合于利用类似jsp:forward的手段来访问的页面。这种不匀称如果利用得当的话很有好 处。例如,servlet可利用MVC体系结构查找数据,把它放到bean中,发送请求到从bean中提取数据的JSP页面并显示它。我们希望保证决不直 接访问受保护的JSP页面,而只是通过建立该页面将使用的bean的servlet来访问它。url-pattern和auth-contraint元素 可通过声明不允许任何用户直接访问JSP页面来提供这种保证。但是,这种不匀称的行为可能让开发人员放松警惕,使他们偶然对应受保护的资源提供不受限制的 访问。 
l auth-constraint
尽管web-resource-collention元素质出了哪些URL应该受到保护, 但是auth-constraint元素却指出哪些用户应该具有受保护资源的访问权。此元素应该包含一个或多个标识具有访问权限的用户类别role- name元素,以及包含(可选)一个描述角色的description元素。例如,下面web.xml中的security-constraint元素部 门规定只有指定为Administrator或Big Kahuna(或两者)的用户具有指定资源的访问权。
<security-constraint>
<web-resource-coolection> ... </web-resource-coolection>
<auth-constraint>
<role-name>administrator</role-name>
<role-name>kahuna</role-name>
</auth-constraint>
</security-constraint>
重要的是认识到,到此为止,这个过程的可移植部分结束了。服务器怎样确定哪些用户处于任何角色以及它怎样存放用户的口令,完全有赖于具体的系统。
例如,Tomcat使用install_dir/conf/tomcat-users.xml将用户名与角色名和口令相关联,正如下面例子中所示,它指出用户joe(口令bigshot)和jane(口令enaj)属于administrator和kahuna角色。
<tomcat-users>
<user name="joe" password="bigshot" roles="administrator,kahuna" />
<user name="jane" password="enaj" roles="kahuna" />
</tomcat-users>
l user-data-constraint
这 个可选的元素指出在访问相关资源时使用任何传输层保护。它必须包含一个transport-guarantee子元素(合法值为NONE、 INTEGRAL或CONFIDENTIAL),并且可选地包含一个description元素。transport-guarantee为NONE值将 对所用的通讯协议不加限制。INTEGRAL值表示数据必须以一种防止截取它的人阅读它的方式传送。虽然原理上(并且在未来的HTTP版本中),在 INTEGRAL和CONFIDENTIAL之间可能会有差别,但在当前实践中,他们都只是简单地要求用SSL。例如,下面指示服务器只允许对相关资源做 HTTPS连接:
<security-constraint>
<!-- ... -->
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
l display-name
security-constraint的这个很少使用的子元素给予可能由GUI工具使用的安全约束项一个名称。
9.3 分配角色名
迄今为止,讨论已经集中到完全由容器(服务器)处理的安全问题之上了。但servlet以及JSP页面也能够处理它们自己的安全问题。
例 如,容器可能允许用户从bigwig或bigcheese角色访问一个显示主管人员额外紧贴的页面,但只允许bigwig用户修改此页面的参数。完成这种 更细致的控制的一种常见方法是调用HttpServletRequset的isUserInRole方法,并据此修改访问。
Servlet的 security-role-ref子元素提供出现在服务器专用口令文件中的安全角色名的一个别名。例如,假如编写了一个调用 request.isUserInRole("boss")的servlet,但后来该servlet被用在了一个其口令文件调用角色manager而不 是boss的服务器中。下面的程序段使该servlet能够使用这两个名称中的任何一个。
<servlet>
<!-- ... -->
<security-role-ref>
<role-name>boss</role-name> <!-- New alias -->
<role-link>manager</role-link> <!-- Real name -->
</security-role-ref>
</servlet>
也可以在web-app内利用security-role元素提供将出现在role-name元素中的所有安全角色的一个全局列表。分别地生命角色使高级IDE容易处理安全信息。

10 控制会话超时

如 果某个会话在一定的时间内未被访问,服务器可把它扔掉以节约内存。可利用HttpSession的setMaxInactiveInterval方法直接 设置个别会话对象的超时值。如果不采用这种方法,则缺省的超时值由具体的服务器决定。但可利用session-config和session- timeout元素来给出一个适用于所有服务器的明确的超时值。超时值的单位为分钟,因此,下面的例子设置缺省会话超时值为三个小时(180分钟)。
<session-config>
<session-timeout>180</session-timeout>
</session-config>

11 Web应用的文档化

越 来越多的开发环境开始提供servlet和JSP的直接支持。例子有Borland Jbuilder Enterprise Edition、Macromedia UltraDev、Allaire JRun Studio(写此文时,已被Macromedia收购)以及IBM VisuaAge for Java等。
大量的web.xml元素不仅是为服务器设计的,而且还是为可视开发环境设计的。它们包括icon、display-name和discription等。
可回忆一下,在web.xml内以适当地次序声明web-app子元素很重要。不过,这里只要记住icon、display-name和description是web.xml的web-app元素内的前三个合法元素即可。
l icon
icon元素指出GUI工具可用来代表Web应用的一个和两个图像文件。可利用small-icon元素指定一幅16 x 16的GIF或JPEG图像,用large-icon元素指定一幅32 x 32的图像。下面举一个例子: 
<icon>
<small-icon>/images/small-book.gif</small-icon>
<large-icon>/images/tome.jpg</large-icon>
</icon>
l display-name
display-name元素提供GUI工具可能会用来标记此Web应用的一个名称。下面是个例子。
<display-name>Rare Books</display-name>
l description
description元素提供解释性文本,如下所示:
<description>
This Web application represents the store developed for
rare-books.com, an online bookstore specializing in rare
and limited-edition books.
</description>
posted @ 2007-07-02 13:05 和田雨 阅读(198) | 评论 (0)编辑 收藏

1. 如何让选中的一行记录高亮显示?
http://topic.csdn.net/t/20050105/09/3699823.html
2. 如何在下拉列表框里选择一个值后跳出新窗口?
http://topic.csdn.net/t/20050107/15/3707444.html
3. 如何在JSP中启动execl?
http://community.csdn.net/Expert/TopicView1.asp?id=4909154
http://community.csdn.net/Expert/TopicView1.asp?id=4685297
4. 两级联动菜单
http://topic.csdn.net/t/20040730/16/3227437.html
5. java中如何把一个目录下的文件移到另一个指定的目录?
http://topic.csdn.net/t/20050112/13/3719237.html
6. 如何制作表格线?
http://community.csdn.net/Expert/TopicView1.asp?id=5130862
7. jsp如判别一个字符在A到Z之间?
http://topic.csdn.net/t/20050113/08/3721286.html
8. 得到一浮点数小数点后4位,如何写以函数截取为两位
http://topic.csdn.net/t/20050117/14/3731712.html
9. 整型转字符?
http://topic.csdn.net/t/20030526/22/1837632.html
10. 显示数据库的记录,点击哪个标题栏,就按照哪个标题排序
http://topic.csdn.net/t/20041226/15/3677011.html
11. 制作两个按钮
??
12. 用什么sql语句将数据库中的一条记录,复制为两条?
http://topic.csdn.net/t/20050120/17/3741746.html
13. 有兩個按鈕A,B,其中A按下去,A就不可以再按,另外B按下去,A可以再按..請問如何用javascript控制.?
http://topic.csdn.net/t/20050120/17/3741568.html
14. 请问jsp中的数据库的连接方式
http://topic.csdn.net/t/20030107/11/1334377.html
15. 在jsp中,怎么实现按回车就可提交表单?
http://topic.csdn.net/t/20050121/11/3743133.html
16. 在JSP中如何传递数组?
http://topic.csdn.net/t/20030624/17/1952227.html
17. 如何按地址取图片?
http://community.csdn.net/Expert/TopicView1.asp?id=4894525
http://community.csdn.net/Expert/TopicView1.asp?id=4990451
18. JSP中如何上传图片到数据库字段?
http://community.csdn.net/Expert/TopicView1.asp?id=4923127
19. 页面自动刷新?
http://topic.csdn.net/t/20040430/16/3025697.html
20. 表单自动提交?
http://community.csdn.net/Expert/TopicView1.asp?id=4681334
21. 如何从JSP传数据的到JAVABEAN里?
这个不就是参数传递么??
22. weblogic 数据池连接? 数据源 JNDI名字 mysource
http://topic.csdn.net/t/20040915/22/3376617.html
23. 三级联动菜单?
http://blog.csdn.net/overmind/archive/2005/10/27/517856.aspx
24. 在JSP中如何调用浏览器中的"另存为"功能?
http://topic.csdn.net/t/20050509/09/3990931.html
25. 网页全屏显示
http://community.csdn.net/Expert/TopicView1.asp?id=5057245
26. 求两个日期相隔了多少天:输入时间格式为(yyyy-mm-dd)
http://topic.csdn.net/t/20050516/10/4009546.html
27. 上传文件对话框
http://community.csdn.net/Expert/TopicView1.asp?id=4961980
28. 分页测试
http://community.csdn.net/Expert/TopicView1.asp?id=4925123
29. 下载文件
http://community.csdn.net/Expert/TopicView1.asp?id=5019146
30. 简单汉字判断
http://blog.csdn.net/duanxd/archive/2005/05/19/376481.aspx
31. 可否将JSP的变量或者bean传递给JAVASCRIPT使用?
http://topic.csdn.net/t/20050520/14/4022667.html
32. 怎么把一种格式(如yyyy-mm-dd)的日期变量转换成另外一种格式(如dd-mm-yyyy)的日期变量!
http://topic.csdn.net/t/20050602/21/4055209.html
33. 如何实现在页面上添加一行输入对话框
??
34. 如何制作验证码图片?
http://community.csdn.net/Expert/TopicView1.asp?id=4857455
35. 图片缩小放大功能
http://topic.csdn.net/t/20041227/09/3678138.html
36. 如何点击输入框弹出日期选择?
http://community.csdn.net/Expert/TopicView1.asp?id=5020494
http://www.dynarch.com/projects/calendar/
37. 如何在图片上传前查看自己要上传的图片?
http://community.csdn.net/Expert/TopicView1.asp?id=4825282
38. 如何在图片排列的页面上选中一个图片,然后把它删掉?
http://community.csdn.net/Expert/TopicView1.asp?id=5162107
39. 显示某目录下的所有文件
http://community.csdn.net/Expert/TopicView1.asp?id=5056503
40. 如何把复选框中选中的值直接显示在输入文本框中?
http://community.csdn.net/Expert/TopicView1.asp?id=5004830
41. 如何选择路径下的文件直接显示文件内容?
http://community.csdn.net/Expert/TopicView1.asp?id=5194181
http://community.csdn.net/Expert/TopicView1.asp?id=5121413
42. 如何制作进度条?
http://topic.csdn.net/t/20051120/03/4405364.html
43. 如何对较长字符省略显示?
http://community.csdn.net/Expert/TopicView1.asp?id=5124078
44. 如何制作日历?
这个太多了
45. 点击文本弹出一个选择框,选中值后返回并显示
http://community.csdn.net/Expert/TopicView1.asp?id=4979197
http://community.csdn.net/Expert/TopicView1.asp?id=4988006
46. 如何关闭框架页面回到没框架的页面?
http://community.csdn.net/Expert/TopicView1.asp?id=4970057
47. 如何选中多条记录一次性删除?
http://community.csdn.net/Expert/TopicView1.asp?id=4762839
48. 如何自动获取页面文件名?
http://community.csdn.net/Expert/TopicView1.asp?id=4945500
49. 如何在JSP中调用ActiveX控件?
http://community.csdn.net/Expert/TopicView1.asp?id=4919689
50. 如何使用SmartUpload实现文件上传?
http://community.csdn.net/Expert/TopicView1.asp?id=4911791
51. 如何使用iReport和Jasperreport开发报表?
http://community.csdn.net/Expert/TopicView1.asp?id=5038328
52. 如何使用iText生成PDF?
http://www.lowagie.com/iText/tutorial/ch07.html#htmlparsing
http://java.ccidnet.com/art/3565/20050309/480327_1.html
53. 如何制作图片水印?
http://community.csdn.net/Expert/TopicView1.asp?id=5212770
http://community.csdn.net/Expert/TopicView1.asp?id=4885889
54. 如何在页面中屏蔽键盘功能键?
http://community.csdn.net/Expert/TopicView1.asp?id=4356360
55. 如何禁止用户复制网页内容?
http://community.csdn.net/Expert/TopicView1.asp?id=4356360
56. 如何实现不在地址拦中显示当前URL?
http://community.csdn.net/Expert/TopicView1.asp?id=4678351
http://community.csdn.net/Expert/TopicView1.asp?id=4863808
57. 如何获取用户的真实IP地址?
http://community.csdn.net/Expert/TopicView1.asp?id=4718686
58. 如何获取用户浏览器信息?
http://community.csdn.net/Expert/TopicView1.asp?id=4987045
http://community.csdn.net/Expert/TopicView1.asp?id=4898974
59. 如何获取当前绝对路径?
http://community.csdn.net/Expert/TopicView1.asp?id=5157921
http://community.csdn.net/Expert/TopicView1.asp?id=5178848
60. 如何将HTML文件转换成XML文件?
http://community.csdn.net/Expert/TopicView1.asp?id=4542984
61. 如何结合XML和XSL输出HTML页面?
http://community.csdn.net/Expert/TopicView1.asp?id=4355891
62. 如何制作动态树型菜单制作?
http://www.blogjava.net/rickhunter/articles/59742.html
http://community.csdn.net/Expert/TopicView1.asp?id=4966014
63. 如何制作类似QQ的短消息提示?
http://community.csdn.net/Expert/TopicView1.asp?id=4702037
http://community.csdn.net/Expert/TopicView1.asp?id=5087584
64. 如何用jfreechat制作拄、饼、曲线图型?
http://www.inspiresky.com/Article/ShowArticle.asp?ArticleID=731
65. 文本框怎么只容许输入数字?
http://community.csdn.net/Expert/TopicView1.asp?id=4927727
66. 如何打开Word和Execl文件?
http://community.csdn.net/Expert/TopicView1.asp?id=5194181
http://community.csdn.net/Expert/TopicView1.asp?id=4685297
67. 如何生成Word 和 Excel文档?
http://sourceforge.net/project/showfiles.php?group_id=15255&release_id=167948
68. JSP如何读取Word内容?
http://topic.csdn.net/t/20030217/13/1435281.html 
posted @ 2007-07-02 13:01 和田雨 阅读(535) | 评论 (0)编辑 收藏

 1、获取服务器端当前日期:
<%@ page import="java.util.Date"%>
<%
Date myDate = new Date();
%>
2、获取当前年、月、日:

<%@ page import="java.util.Date"%>

<%
Date myDate = new Date();
int thisYear = myDate.getYear() + 1900;//thisYear = 2003
int thisMonth = myDate.getMonth() + 1;//thisMonth = 5
int thisDate = myDate.getDate();//thisDate = 30
%>


3、按本地时区输出当前日期

<%@ page import="java.util.Date"%>
<%
Date myDate = new Date();
out.println(myDate.toLocaleString());
%>


输出结果为:
2003-5-30


4、获取数据库中字段名为"publish_time"、类型为Datetime的值


<%@ page import="java.util.Date"%>
<%
...连接数据库...
ResultSet rs = ...
Date sDate = rs.getDate("publish_time");
%>
[code]


5、按照指定格式打印日期


[code]
<%@ page import="java.util.Date"%>
<%@ page import="java.text.DateFormat"%>
<%
Date dNow = new Date();

SimpleDateFormat formatter = new SimpleDateFormat("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
out.println("It is " + formatter.format(dNow));
%>

 

输出的结果为:
It is 星期五 2003.05.30 at 11:30:46 上午 CST
(更为详尽的格式符号请参看SimpleDateFormat类)


6、将字符串转换为日期

<%@ page import="java.util.Date"%>
<%@ page import="java.text.DateFormat"%>
<%
String input = "1222-11-11";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date t = null;

try{

  t = formatter.parse(input);

  out.println(t);

  }catch(ParseException e){

  out.println("unparseable using" + formatter);

  }

%>

输出结果为:
Fri Nov 11 00:00:00 CST 1222


7、计算日期之间的间隔

 

<%@ page import="java.util.Date"%>
<%@ page import="java.text.DateFormat"%>
<%
String input = "2003-05-01";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date d1 = null;
trycatch(ParseException e)

Date d2 = new Date();

long diff = d2.getTime() - d1.getTime();
out.println("Difference is " + (diff/(1000*60*60*24)) + " days.");
%>


输出结果为:
Difference is 29 days.


8、日期的加减运算
方法:用Calendar类的add()方法


<%@ page import="java.util.*"%>
<%@ page import="java.text.*"%>
<%
Calendar now = Calendar.getInstance();
SimpleDateFormat formatter = new SimpleDateFormat("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
out.println("It is now " + formatter.format(now.getTime()));
now.add(Calendar.DAY_OF_YEAR,-(365*2));
out.println("<br>");
out.println("Two years ago was " + formatter.format(now.getTime()));
%>

 

输出结果为:
It is now 星期五 2003.05.30 at 01:45:32 下午 CST
Two years ago was 星期三 2001.05.30 at 01:45:32 下午 CST


9、比较日期
方法:用equals()、before()、after()方法

 

<%@ page import="java.util.*"%>
<%@ page import="java.text.*"%>
<%
DateFormat df = new SimpleDateFormat("yyy-MM-dd");
Date d1 = df.parse("2000-01-01");
Date d2 = df.parse("1999-12-31");

String relation = null;
if(d1.equals(d2))
relation = "the same date as";
else if(d1.before(d2))
relation = "before";
else
relation = "after";
out.println(d1 +" is " + relation + ' ' + d2);
%>


输出结果为:
Sat Jan 01 00:00:00 CST 2000 is after Fri Dec 31 00:00:00 CST 1999


10、记录一件事所花费的时间
方法:调用两次System.getTimeMillis()方法,求差值

 

<%@ page import="java.text.*"%>
<%
long t0,t1;
t0 = System.currentTimeMillis();
out.println("Cyc starts at " + t0);
int k = 0;
for(int i =0;i<100000;i++)
t1 = System.currentTimeMillis();
out.println("<br>");
out.println("Cyc ends at " + t1);
out.println("<br>");
out.println("This run took " + (t1-t0) + "ms.");
%>


输出结果为:
Cyc starts at 1054275312432
Cyc ends at 1054275312442
This run took 10ms.

其它:如何格式化小数

 

<%@ page import="java.text.*"%>
<%
DecimalFormat df = new DecimalFormat(",###.00");
double aNumber = 33665448856.6568975;
String result = df.format(aNumber);
out.println(result);
%>


输出结果为:
33,665,448,856.66

posted @ 2007-07-02 13:01 和田雨 阅读(205) | 评论 (0)编辑 收藏

计数器是一般网站必备的东东,别小看它了,每当站长看着小小计数器上的数字飞速增长的时候,感觉实在是好极了。以前我们用cgi、asp来写计数器,这方面的文章很多了,在这里,我们将会采用目前比较流行的jsp技术演示如何做一个计数器。 6?P~(MPPm  
mVfGL 3P  
  其中我们用到了两个文件,test.jsp文件用于在浏览器中运行,counter.java是后台的一个小java bean程序,用来读计数器的值和写入计数器的值。而对于计数器的保存,我们采用了一个文本文件lyfcount.txt。
B2cYy,Whi  
6Nz</bHn  
转自:动态网制作指南
www.knowsky.com '$ 6Zv$S  
mgpeMc5R3  
下面是详细的程序代码(test.jsp放到web目录下,counter.java放到class目录):
+33qS}  
//test.jsp文件
@`3-X/Q  
<%@ page contentType="text/html;charset=gb2312"%>
LYL. eK  
<HTML>
 pW0  
<HEAD>
C|F1F &2U  
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
&wk.'0R9E  
<META NAME="GENERATOR" CONTENT="Oracle JDeveloper">
%K&gZIkX  
<TITLE>
87x7Rnj >=  
计数器演示程序
%fU wb  
</TITLE>
"I,z,/5Y  
</HEAD>
lJgBcZ{7  
<BODY>
IrtugFf  
<!--创建并调用bean(counter)-->
KPX)E!"v  
<jsp:useBean id="counter" class="counter" scope="request">
v2LW[I7]  
</jsp:useBean>
-5~k  
<%
~jKx  
//调用counter对象的ReadFile方法来读取文件lyfcount.txt中的计数
j(}8B=c{e6  
String cont=counter.ReadFile("/lyfcount.txt");
s Ki/puJ  
//调用counter对象的ReadFile方法来将计数器加一后写入到文件lyfcount.txt中
b#j^QB9w N  
counter.WriteFile("/lyfcount.txt",cont);%>
W*AWh`yDK  
您是第<font color="red"><%=cont%></font>位访问者
j {i6 TI  
</BODY>
e$]VJ-*Ni  
</HTML>
,x 61Tj6p  
{enOdTJQx  
//counter.java 读写文件的一个bean
}-0Rke6`>Y  
import java.io.*;
pcj}E(\ y  
mc?=kzE  
public class counter extends Object {
NHF1l}*  
private String currentRecord = null;//保存文本的变量
0&dB8+;Ge  
private BufferedReader file; //BufferedReader对象,用于读取文件数据
Pv: H87  
private String path;//文件完整路径名
 B4&% )2  
public counter() {
] RgX{;  
}
h4Hi&30  
//ReadFile方法用来读取文件filePath中的数据,并返回这个数据
ZF%0a,&%  
public String ReadFile(String filePath) throws FileNotFoundException
_v(ojt r=  
{
1HPnp /u  
path = filePath;
YicVk\(1  
//创建新的BufferedReader对象
2~ 0K7~  
file = new BufferedReader(new FileReader(path));
ct3vuSf?  
String returnStr =null;
&vt{]z=  
try
<ymk1tk8@  
{
p|~K$ +R  
//读取一行数据并保存到currentRecord变量中
~-g#'  
currentRecord = file.readLine();
C{s%WW3?  
}
! f/|Lm  
catch (IOException e)
DEC5"S'f#  
{//错误处理
j^ %9ji  
System.out.println("读取数据错误.");
uiro2 Fz8  
}
}H&/l?g'  
if (currentRecord == null)
DgO0/n  
//如果文件为空
Y:d2ra*[&  
returnStr = "没有任何记录";
`Au)H  
else
FN@p~ X  
{//文件不为空
="p{vnN"  
returnStr =currentRecord;
]v GW  
}
QDanl36  
//返回读取文件的数据
AR@urdG  
return returnStr;
V0 @M$op  
}
e i&:Z  
//ReadFile方法用来将数据counter+1后写入到文本文件filePath中
c$h=gQ  
//以实现计数增长的功能
~tnQw}x  
public void WriteFile(String filePath,String counter) throws FileNotFoundException
afTiP0 Qz  
{
dnx4bUW0  
path = filePath;
 *% Ga  
//将counter转换为int类型并加一
! Al9>  
int Writestr = Integer.parseInt(counter)+1;
^$%vQ/F,Z  
try {
C{A%JXV|y  
//创建PrintWriter对象,用于写入数据到文件中
oFhww4mY|  
PrintWriter pw = new PrintWriter(new FileOutputStream(filePath));
QyjT?K{j:  
//用文本格式打印整数Writestr
*R\U6A=J8  
pw.println(Writestr);
S$C5 c .  
//清除PrintWriter对象
>|=}0K  
pw.close();
AsBtn-X>^  
} catch(IOException e) {
(1XAc\Le  
//错误处理
e_Pdm8Lw)  
System.out.println("写入文件错误"+e.getMessage());
5._Wa[@  
}
25A-F<x  
}
BnUr~  
_f A:ynT]{  
}
#i'a`8Y6QT  
U_mAGr[  
  到这里,程序写完了,将counter.java编译为counter.class,同样放在对应的class目录下,在根目录下建立一个lyfcount.txt文件,文件内容就一个数字0,直接在浏览器中敲入地址就可以看到计数器了,刷新浏览器会看到不断变幻的数字。
mCzk^}5  
@(;G`0C  
  (如果运行时候提示找不到文件,请将上面test.jsp中的readfile那一句注释后运行一次则lyfcount.txt文件自动建立,然后就可以正常运行。)

posted @ 2007-07-02 12:59 和田雨 阅读(201) | 评论 (0)编辑 收藏

目前, 国内外信息化建设已经进入基于Web应用为核心的阶段, Java作为应用于网络的最好语言,前景无限看好。然而,就算用Java建造一个不是很烦琐的web应用,也不是件轻松的事情。概括一下,实施Java的WEB项目需要掌握的技术如下:

 
lJava语言
l面向对象分析设计思想
l设计模式和框架结构
lXML语言
l网页脚本语言
l数据库
l应用服务器
l集成开发环境
 
下面我们具体地看每个技术.
1、Java语言

Java
语言体系比较庞大,包括多个模块。从WEB项目应用角度讲有JSP、Servlet、JDBC、JavaBean(Application)四部分技术。
 
(1)、Java Database Connectivity (JDBC)技术
Java Web应用开发中,数据库管理系统(RDBMS)的使用是不可缺少的。JDBC(Java Database Connectivity) 是一种用于执行 SQL 语句的 Java API。它由一组用 Java 编程语言编写的类和接口组成。JDBC 为工具/数据库开发人员提供了一个标准的API,使他们能够用纯Java API 来编写数据库应用程序。
简单地说,JDBC 可做三件事:
l与数据库建立连接,
l发送 SQL 语句,
l处理结果。
 
 (2)、Servlet技术
Servlet是运行在服务器端的程序,可以被认为是服务器端的applet。servlet被Web服务器(例如Tomcat)加载和执行,就如同applet被浏览器加载和执行一样。servlet从客户端(通过Web服务器)接收请求,执行某种操作,然后返回结果。
 
Servlet的主要优点包括
lServlet是持久的。servlet只需Web服务器加载一次,而且可以在不同请求之间保持服务(例如一次数据库连接)。
lServlet是与平台无关的。如前所述,servlet是用Java编写的,它自然也继承了Java的平台无关性。
lServlet是可扩展的。由于servlet是用Java编写的,它就具备了Java所能带来的所有优点。Java是健壮的、面向对象的编程语言,它很容易扩展以适应你的需求。servlet自然也具备了这些特征。
lServlet是安全的。从外界调用一个servlet的惟一方法就是通过Web服务器。这提供了高水平的安全性保障,尤其是在你的Web服务器有防火墙保护的时候。
lServlet可以在多种多样的客户机上使用。由于servlet是用Java编写的,所以你可以很方便地在HTML中使用它们。
 
(3)、JavaServer Pages(JSP) 技术
JSP是从Servlet上分离出来的一小部分,简化了开发,加强了界面设计。JSP定位在交互网页的开发。运用Java语法,但功能较Servlet弱了很多,并且高级开发中只充当用户界面部分。JSP容器收到客户端发出的请求时,首先执行其中的程序片段,然后将执行结果以HTML格式响应给客户端。其中程序片段可以是:操作数据库、重新定向网页以及发送 E-Mail 等等,这些都是建立动态网站所需要的功能。所有程序操作都在服务器端执行,网络上传送给客户端的仅是得到的结果,与客户端的浏览器无关,因此,JSP 称为Server-Side Language。
 
JavaServer Pages的主要优点包括
●一次编写,各处执行(Write o­nce, Run Anywhere)特性
作为Java 平台的一部分,JavaServer Pages 技术拥有Java语言“一次编写,各处执行”的特点。随着越来越多的供货商将JavaServer Pages 技术添加到他们的产品中,您可以针对自己公司的需求,做出审慎评估后,选择符合公司成本及规模的服务器,假若未来的需求有所变更时,更换服务器平台并不影响之前所投下的成本、人力所开发的应用程序。
● 搭配可重复使用的组件
JavaServer Pages技术可依赖于重复使用跨平台的组件(如:JavaBean或Enterprise JavaBean组件)来执行更复杂的运算、数据处理。开发人员能够共享开发完成的组件,或者能够加强这些组件的功能,让更多用户或是客户团体使用。基于善加利用组件的方法,可以加快整体开发过程,也大大降低公司的开发成本和人力。
● 采用标签化页面开发
Web 网页开发人员不一定都是熟悉Java 语言的程序员。因此,JSP 技术能够将许多功能封装起来,成为一个自定义的标签,这些功能是完全根据XML 的标准来制订的,即JSP 技术中的标签库(Tag Library)。因此,Web 页面开发人员可以运用自定义好的标签来达成工作需求,而无须再写复杂的Java 语法,让Web 页面开发人员亦能快速开发出一动态内容网页。
今后,第三方开发人员和其他人员可以为常用功能建立自己的标签库,让Web 网页开发人员能够使用熟悉的开发工具,如同HTML 一样的标签语法来执行特定功能的工作。
N-tier 企业应用架构的支持
有鉴于网际网络的发展,为因应未来服务越来越繁杂的要求,且不再受地域的限制,因此,
必须放弃以往Client-Server的Two-tier 架构,进而转向更具威力、弹性的分散性对象系统。由于JavaServer Page 技术是Java 2 Platform Enterprise Edition (J2EE)集成中的一部分,它主要是负责前端显示经过复杂运算后之结果内容,而分散性的对象系统则是主要依赖EJB ( Enterprise JavaBean )和JNDI ( Java Naming and Directory Interface )构建而成。

(4)、JavaBean(Application)
应用组件技术
Application
是Java应用程序,在WEB项目和一些开发中主要应用JavaBean。它就是Application的一部分,逻辑运算能力很强,能极大的发挥Java语言的优点。JavaBean 被称为是Java 组件技术的核心。JavaBean 的结构必须满足一定的命名约定。JavaBean能提供常用功能并且可以重复使用,这使得开发人员可以把某些关键功能和核心算法提取出来封装成为一个组件对象,这样就增加了代码的重用率和系统的安全性。

高级的WEB项目会应用到以上所有技术,它们之间联合使用和协作开发会提高开发的效率和系统的性能。 

2、面向对象分析设计思想

Java
语言是完全面向对象的语言,所以在项目设计时会有很大的帮助,在设计时应尽量舍弃以往的面向过程的设计方式。

在分析项目业务关系的时候,应用一些UML(Unified Modeling Language)图,例如常用的用例图(use case diagram),类图(class diagram),时序图(sequence diagram)等等,会有很大的帮助,这样能尽快找出业务逻辑主要面对的对象,然后对每个对象进行行为划分,最后再实现对象之间的集成和通信。

3、设计模式和框架结构
Java从语言角度来讲不是很难,但是从整体设计角度来讲我们还需要了解一些高级应用框架。如果要设计一个良好的框架结构,单单只掌握Java语言远远不够。这就涉及到一个设计模式,还有和设计模式相关的一些知识。

设计模式在Java项目实施过程更是重中之重。主要在与两层的设计模式、三层的设计模式和N层的设计模式。它直接决定着项目的应用、部署和实际开发设计。

在普通的WEB项目中很多采用两层的开发结构。JSP+Servlet或JSP+JavaBean。当对开发要求高的项目中使用很多的还是MVC的三层开发结构,也就是JSP+Servlet+JavaBean。它能分有效的分离逻辑开发,使开发人员能专注于各自的开发。同时也能时整个开发结构流程更清晰,但是需要比较高的开发配合度。
在项目中,我们经常使用著名的Model-View-Controller(MVC)架构。
MVC架构是随着smalltalk language语言的发展提出的,它是一个著名的用户界面设计架构。经典的MVC架构把一个组件(可认为是整个应用程序的一个模块)划分成三部分组 Model管理这个模块中所用到的数据和业务逻辑。而View 管理模块如何显示给用户,Controller 决定如何处理用户和该模块交互式时候产生的事件 如用户点击一个按钮等。

4、XML
语言

在服务器和设计模式结构中会应用到自定义文件,而且在应用高级设计时也会定义自用的标签,现在流行的是用XML去定义配置,所以XML语言应该有一定掌握。
当前,Java 2平台企业版(J2EE)架构在厂商市场和开发者社区中倍受推崇。作为一种工具,可扩展标记语言(XML)简化了数据交换、进程间消息交换这一类的事情,因而对开发者逐渐变得有吸引力,并开始流行起来。自然,在J2EE架构中访问或集成XML解决方案的想法也很诱人。因为这将是强大系统架构同高度灵活的数据管理方案的结合。

XML的应用似乎是无穷无尽的,但它们大致上可以分为三大类:
1、简单数据的表示和交换(针对XML的简单API(SAX)和文档对象模型(DOM)语法解析,不同的文档类型定义(DTDs)和概要(schemas))
2、用户界面相关、表示相关的上下文(可扩展样式表语言(XSL),可扩展样式表语言转换(XSLT))
3、面向消息的计算(XML-RPC(远程过程调用),基于SOAP协议的Web 服务(Web Services),电子化业务XML(ebXML))

5、网页脚本语言
 
为了提高WEB项目的整体性能,提高人机交互的友好界面,网页的脚本语言是很有用处的,有的时候可以解决很大的难题或提高程序的性能和应用性。

网页脚本语言的执行都是在客户端执行的,速度很很快,并且大多的操作与服务器没有交互运算,所以在一些应用中非常理想。在设计WEB项目的应用中,网页的脚本语言起着不能忽视的作用,所以如果设计WEB项目的应用中,对JavaScript应有一定的了解。
 
JavaScript是一种基于对象(Object Based)和事件驱动(Event Driven)并具有安全性能(Secure)的脚本语言。使用它的目的是与HTML超文本标记语言、Java 脚本语言(Java小程序)一起实现在一个Web页面中链接多个对象,与Web客户交互作用。从而可以开发客户端的应用程序等。它是通过嵌入或调入在标准的HTML语言中实现的。它具有以下几个基本特点:
1.它是一种脚本编写语言
JavaScript是一种脚本语言,它采用小程序段的方式实现编程。像其它脚本语言一样,JavaScript同样已是一种解释性语言,它提供了一个易的开发过程。
它的基本结构形式与C、C++、VB十分类似。但它不像这些语言一样,需要先编译,而是在程序运行过程中被逐行地解释。它与HTML标识结合在一起,从而方便用户的使用操作。
2. 基于对象的语言。
 JavaScript是一种基于对象的语言,同时以可以看作一种面向对象的。这意味着它能运用自己已经创建的对象。因此,许多功能可以来自于脚本环境中对象的方法与脚本的相互作用。
3.简单性
 JavaScript的简单性主要体现在:首先它是一种基于Java基本语句和控制流之上的简单而紧凑的设计, 从而对于学习Java是一种非常好的过渡。其次它的变量类型是采用弱类型,并未使用严格的数据类型。
4.安全性
 JavaScript是一种安全性语言,它不允许访问本地的硬盘,并不能将数据存入到服务器上,不允许对网络文档进行修改和删除,只能通过浏览器实现信息浏览或动态交互。从而有效地防止数据的丢失。
5. 动态性
 JavaScript是动态的,它可以直接对用户或客户输入做出响应,无须经过Web服务程序。它对用户的响应,是采用以事件驱动的方式进行的。所谓事件驱动,就是指在主页(Home Page)中执行了某种操作所产生的动作,就称为“事件”(Event)。比如按下鼠标、移动窗口、选择菜单等都可以视为事件。当事件发生后,可能会引起相应的事件响应。

6、开发工具
(1)、数据库
在主要的应用中,数据库相关的环节应用很多,所以对数据库应该有一定了解。不能单单只了解一种数据库,因为在很多实际开发中会提出很多数据库解决方案,所以只有在了解多种数据库的情况下才能有一个比较方案。
对于数据库应该了解他的性能和一些基本的操作常识,还有该数据库的特点。而针对与Java语言WEB项目的数据库开发则主要是对JDBC的应用,还有数据库事务处理和连接池等高级概念的应用。

(2)、Web服务器
 
同数据库一样,应该了解该服务器的性能,特点和一些常识。
在应用方面,Web服务器主要是针对于配置和部署,对目录的配置,调试;对配置文件属性的修改;对访问权限和并发性的控制;Java类的部署等。

(3)、集成开发环境(IDE):
公欲善其事, 必先利其器”. 对于Web应用开发人员来讲,好的集成开发环境(IDE:Integrated Development Enviroment)是非常重要的。目前在市场上占主导位置的一个集成开发工具就是Eclipse.
 (转载文章请保留出处:Java家(www.javajia.com))
posted @ 2007-07-02 12:58 和田雨 阅读(294) | 评论 (0)编辑 收藏

一些网站采用了字母和数字的验证码,数字和字母加起来一共30多个,如果有心,还是能够通过方法识别出来。 O8<@d3  
我在网上看到一篇文章"jsp彩色验证码",我进行了加强,生成的验证码内容为汉字,可以方便应用在面向汉语网民的网站认证上。
oxcd:, Vc  
iXV6:&\9"r  
当然,我还看到别人考虑的几种方法:
{i867@H_e  
1.生成计算题,比如20+34*(23-12)=?,用户必须输入正确的答案才能通过验证,这个想法挺好,但是用户必须打开计算器进行计算,增加了用户的难度
dza^8ynu  
2.问一些常见的问题,比如“人”这个字由几笔组成。这也是不错的想法,关键是必须有上万条的题库,而且题库的答案必须是明确的,简单易比较的,这个难度也较大。
|||o<  
ejas+  
下面是彩色汉字验证码的代码。
,"-07[X  
]j&J&.:&,  
dVTACb`  
<%@ page contentType="image/jpeg" import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*" %>
YwpC}G;   
<%!
(.&vEwK  
//create by smallnest
z(S Lcx  
//email:
smallnest@gmail.com <p-Y a_&u  
//website:
www.kuaff.com hpC%no /s  
Du:x%[~]  
99Ztr4E  
Jk)|S2  
: pZ<K"Z-&  
//生成随机颜色
s*# ]mm.MD  
Color getRandColor(Random random,int fc,int bc)
M-C|5ahf8B  
{
!DF}` d  
if(fc>255) fc=255;
{+9C59]sA  
if(bc>255) bc=255;
^k41]4 RD  
int r=fc+random.nextInt(bc-fc);
')/u5Y{fp  
int g=fc+random.nextInt(bc-fc);
F\(TcR(  
int b=fc+random.nextInt(bc-fc);
qQ5> k=3  
return new Color(r,g,b);
2Es&*Kr+"  
}
 '0 )!e!=  
%>
=H NQZD`e  
<%
q=X0lJ<V  
//设置页面不缓存
Qsd{m_y#  
response.setHeader("Pragma","No-cache");
p[brf>x  
response.setHeader("Cache-Control","no-cache");
h-r<TW  
response.setDateHeader("Expires", 0);
hB~(UCtd  
{m@moH 3N  
">^0|,(e  
// 设置图片的长宽
G"KO  
int width=176, height=30;
rl> 1bV?8  
//设置备选汉字,剔除一些不雅的汉字
>22XQgGh  
String base = "\u7684\u4e00\u4e86\u662f\u6211\u4e0d\u5728\u4eba\u4eec\u6709\u6765\u4ed6\u8fd9\u4e0a\u7740\u4e2a\u5730\u5230\u5927\u91cc\u8bf4\u5c31\u53bb\u5b50\u5f97\u4e5f\u548c\u90a3\u8981\u4e0b\u770b\u5929\u65f6\u8fc7\u51fa\u5c0f\u4e48\u8d77\u4f60\u90fd\u628a\u597d\u8fd8\u591a\u6ca1\u4e3a\u53c8\u53ef\u5bb6\u5b66\u53ea\u4ee5\u4e3b\u4f1a\u6837\u5e74\u60f3\u751f\u540c\u8001\u4e2d\u5341\u4ece\u81ea\u9762\u524d\u5934\u9053\u5b83\u540e\u7136\u8d70\u5f88\u50cf\u89c1\u4e24\u7528\u5979\u56fd\u52a8\u8fdb\u6210\u56de\u4ec0\u8fb9\u4f5c\u5bf9\u5f00\u800c\u5df1\u4e9b\u73b0\u5c71\u6c11\u5019\u7ecf\u53d1\u5de5\u5411\u4e8b\u547d\u7ed9\u957f\u6c34\u51e0\u4e49\u4e09\u58f0\u4e8e\u9ad8\u624b\u77e5\u7406\u773c\u5fd7\u70b9\u5fc3\u6218\u4e8c\u95ee\u4f46\u8eab\u65b9\u5b9e\u5403\u505a\u53eb\u5f53\u4f4f\u542c\u9769\u6253\u5462\u771f\u5168\u624d\u56db\u5df2\u6240\u654c\u4e4b\u6700\u5149\u4ea7\u60c5\u8def\u5206\u603b\u6761\u767d\u8bdd\u4e1c\u5e2d\u6b21\u4eb2\u5982\u88ab\u82b1\u53e3\u653e\u513f\u5e38\u6c14\u4e94\u7b2c\u4f7f\u5199\u519b\u5427\u6587\u8fd0\u518d\u679c\u600e\u5b9a\u8bb8\u5feb\u660e\u884c\u56e0\u522b\u98de\u5916\u6811\u7269\u6d3b\u90e8\u95e8\u65e0\u5f80\u8239\u671b\u65b0\u5e26\u961f\u5148\u529b\u5b8c\u5374\u7ad9\u4ee3\u5458\u673a\u66f4\u4e5d\u60a8\u6bcf\u98ce\u7ea7\u8ddf\u7b11\u554a\u5b69\u4e07\u5c11\u76f4\u610f\u591c\u6bd4\u9636\u8fde\u8f66\u91cd\u4fbf\u6597\u9a6c\u54ea\u5316\u592a\u6307\u53d8\u793e\u4f3c\u58eb\u8005\u5e72\u77f3\u6ee1\u65e5\u51b3\u767e\u539f\u62ff\u7fa4\u7a76\u5404\u516d\u672c\u601d\u89e3\u7acb\u6cb3\u6751\u516b\u96be\u65e9\u8bba\u5417\u6839\u5171\u8ba9\u76f8\u7814\u4eca\u5176\u4e66\u5750\u63a5\u5e94\u5173\u4fe1\u89c9\u6b65\u53cd\u5904\u8bb0\u5c06\u5343\u627e\u4e89\u9886\u6216\u5e08\u7ed3\u5757\u8dd1\u8c01\u8349\u8d8a\u5b57\u52a0\u811a\u7d27\u7231\u7b49\u4e60\u9635\u6015\u6708\u9752\u534a\u706b\u6cd5\u9898\u5efa\u8d76\u4f4d\u5531\u6d77\u4e03\u5973\u4efb\u4ef6\u611f\u51c6\u5f20\u56e2\u5c4b\u79bb\u8272\u8138\u7247\u79d1\u5012\u775b\u5229\u4e16\u521a\u4e14\u7531\u9001\u5207\u661f\u5bfc\u665a\u8868\u591f\u6574\u8ba4\u54cd\u96ea\u6d41\u672a\u573a\u8be5\u5e76\u5e95\u6df1\u523b\u5e73\u4f1f\u5fd9\u63d0\u786e\u8fd1\u4eae\u8f7b\u8bb2\u519c\u53e4\u9ed1\u544a\u754c\u62c9\u540d\u5440\u571f\u6e05\u9633\u7167\u529e\u53f2\u6539\u5386\u8f6c\u753b\u9020\u5634\u6b64\u6cbb\u5317\u5fc5\u670d\u96e8\u7a7f\u5185\u8bc6\u9a8c\u4f20\u4e1a\u83dc\u722c\u7761\u5174\u5f62\u91cf\u54b1\u89c2\u82e6\u4f53\u4f17\u901a\u51b2\u5408\u7834\u53cb\u5ea6\u672f\u996d\u516c\u65c1\u623f\u6781\u5357\u67aa\u8bfb\u6c99\u5c81\u7ebf\u91ce\u575a\u7a7a\u6536\u7b97\u81f3\u653f\u57ce\u52b3\u843d\u94b1\u7279\u56f4\u5f1f\u80dc\u6559\u70ed\u5c55\u5305\u6b4c\u7c7b\u6e10\u5f3a\u6570\u4e61\u547c\u6027\u97f3\u7b54\u54e5\u9645\u65e7\u795e\u5ea7\u7ae0\u5e2e\u5566\u53d7\u7cfb\u4ee4\u8df3\u975e\u4f55\u725b\u53d6\u5165\u5cb8\u6562\u6389\u5ffd\u79cd\u88c5\u9876\u6025\u6797\u505c\u606f\u53e5\u533a\u8863\u822c\u62a5\u53f6\u538b\u6162\u53d4\u80cc\u7ec6";
=-/!18  
//备选汉字的长度
k63GRbd?  
int length = base.length();
n\+47N*ze  
,"jx!  
2b8~3d[L  
//创建内存图像
e/6VUo@>%  
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
X/$V%6)  
// 获取图形上下文
"g&Xk0  
Graphics g = image.getGraphics();
NEE4{?Q?  
k >@l  
Q{AR6CRAt  
//创建随机类的实例
ch6) "2  
Random random = new Random();
>>#>"<CMT  
K#]~p^Z}  
aF@:;!cVu  
// 设定图像背景色(因为是做背景,所以偏淡)
NAL2w3  
g.setColor(getRandColor(random,200,250));
{<=!bYh  
g.fillRect(0, 0, width, height);
7@mFmb] -#  
+.S``"'  
Eg^${%,d  
//备选字体
RE]p3t|O  
String[] fontTypes = {"\u5b8b\u4f53","\u65b0\u5b8b\u4f53","\u9ed1\u4f53","\u6977\u4f53","\u96b6\u4e66"};
b<psU?/% _  
int fontTypesLength = fontTypes.length;
YZ?KfO=r  
6< 1B;  
<;G d~(  
//在图片背景上增加噪点
Q`6 A{@5Y  
g.setColor(getRandColor(random,160,200));
8M`w  
g.setFont(new Font("Times New Roman",Font.PLAIN,14));
S h (%oy<+  
for (int i=0;i<6;i++)
[NFmqEEanb  
{
_R6 Lr9q  
g.drawString("*********************************************",0,5*(i+2));
goQ2Va+  
}
}):f;M*  
9L+)0)(  
+4vsFa6*  
Fj%N4$?(m  
+Sv2qb  
//取随机产生的认证码(6个汉字)
%[B|3.e  
=e?R(E^Y"  
XSp~5|I  
//保存生成的汉字字符串
p^ >Q(g  
String sRand="";
/0A5(P&q/  
for (int i=0;i<6;i++)
ypeul27H8  
{
h570L^  
int start = random.nextInt(length);
L[4Aolk:M  
String rand=base.substring(start,start+1);
&hA0:^  
sRand+=rand;
D/ ^Kl  
$N^odf(2   
//设置字体的颜色
2A<BW~3FPt  
g.setColor(getRandColor(random,10,150));
C hhWE@!  
//设置字体
6<\w'-  
g.setFont(new Font(fontTypes[random.nextInt(fontTypesLength)],Font.BOLD,18 + random.nextInt(6)));
ftVk!3e  
//将此汉字画到图片上
dMjL#H}  
g.drawString(rand,24*i+ 10 + random.nextInt(8),24);
I_i 7 %  
}
! [ $qI1  
X8H6Fki  
eP{42 C0=  
//将认证码存入session
kCl -?N{og  
session.setAttribute("rand",sRand);
<uT}CUy  
lfKXsvP  
+M'E6E%w  
g.dispose();
*$4SR?  
OIFYpaBXb  
<~[q5tC+  
//输出图象到页面
/z <4A^+  
ImageIO.write(image, "JPEG", response.getOutputStream());
L$ "5TP<  
%>
&+ Q :0Y  
~ oNku2,  
 |D6AG!J  
4f$X#:  
===========================
qozOA`,l  
/j|Au)P  
注:此方法没有在本站JSP虚拟主机测试过,不知道性能如何,如果要用验证请看:
~J|X4>.Vm  
posted @ 2007-07-02 12:57 和田雨 阅读(672) | 评论 (0)编辑 收藏

仅列出标题
共9页: 上一页 1 2 3 4 5 6 7 8 9 下一页