SSH-Struts-Spring-Hibernate

欢迎来到SSH-Struts-Spring-Hibernate>>   | 首页 资源中心 | 一般分类 | Hibernate | Struts | Spring | java | Security | ITPUB论坛

Debian下安装拼音输入法Fcitx

发表人:xuniji123 | 发表时间: 2008年八月29日, 10:01

http://packages.debian.org/zh-tw/lenny/i386/fcitx/download

下载fcitx_3.4.3-1_i386.deb

拷贝到某一目录,如/usr

安装

执行dpkg -i fcitx_3.4.3-1_i386.deb

debiangary:/usr# dpkg -i fcitx_3.4.3-1_i386.deb

Selecting previously deselected package fcitx.

(Reading database ... 61873 files and directories currently installed.)

Unpacking fcitx (from fcitx_3.4.3-1_i386.deb) ...

Setting up fcitx (3.4.3-1) ...

debiangary:/usr# ls

X11R6 fcitx_3.4.3-1_i386.deb include local share src

bin games lib sbin soft

debiangary:/usr#

/etc/X11/Xsession.d/目录下创建一个名为25xchinput的文件,其内容如下:

export LAGN=zh_CN.utf8

export LC_CTYPE=zh_CN.utf8

export LC_ALL=

export XMODIFIERS=@im=fcitx

fcitx &

开机后将自动启动fcitx输入法。使用Ctrl+Space切换输入法

 查看全文

Debian下安装Myeclipse

发表人:xuniji123 | 发表时间: 2008年八月26日, 20:27

eclipse-SDK-3.2-linux-gtk.tar.gzMyEclipse_5_5_1GA_E3_2_2_Installer.bin整合

http://myeclipseide.com

下载MyEclipse_5_5_1GA_E3_2_2_Installer.bin

拷贝到/ypu

/ypu下执行

chmod 777 MyEclipse_5_5_1GA_E3_2_2_Installer.bin

执行./ MyEclipse_5_5_1GA_E3_2_2_Installer.bin

开始安装

找到已经安装好的eclipse3.2的位置。


Debian下安装Oracle10g

发表人:xuniji123 | 发表时间: 2008年八月26日, 17:18

source.list中加入deb http://oss.oracle.com/debian/ unstable main non-free

执行

aptitude update

aptitude oracle-xe-client oracle-xe-universal 包有点大260多兆

开始下载oracle-xe-client oracle-xe-universal,大概需要三十多分钟。

下载完后就开始安装,但是系统会提示交换分区不够,所以要增大交换分区。

分别执行

dd if=/dev/zero of=/mnt/swapfile bs=1024 count=1048576

mkswap /mnt/swapfile

swapon /mnt/swapfile

之后。

现在开始安装oracle 10g express

执行

aptitude install oracle-xe-client oracle-xe-universal

安装完成后将提示进行参数配置

执行/etc/init.d/oracle-xe configure

将设置HTTP 端口,默认是8080,此处设置为8081,为了不和tomcat冲突

设置Oracle服务端口使用默认的1521

最后是设置syssystem的密码

系统提示是否开机自动运行oracle,选择yes

最后重启debian

通过http://127.0.0.1:8081/apex/http://localhost:8081/apex进行管理


Debian下安装Tomcat

发表人:xuniji123 | 发表时间: 2008年八月26日, 17:17

http://tomcat.apache.org/download-60.cgi

下载apache-tomcat-6.0.18.tar.gz

拷贝到/usr/soft/tomcat

并在目录/usr/soft/tomcat

执行tar –xzvf apache-tomcat-6.0.18.tar.gz

将解压生成apache-tomcat-6.0.18文件夹,为了简单,将其更名为tomcat6

mv apache-tomcat-6.0.18 tomcat6

如果已经设置好JRE_HOME环境变量,则可在目录/usr/soft/tomcat/tomcat6/bin下执行

./startup.sh驱动tomcat

./shutdown.sh关闭tomcat

设置环境变量TOMCAT_HOMECATALINA_HOME,修改/etc/profile文件如下:

# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))

# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).

if [ "`id -u`" -eq 0 ]; then

PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

else

PATH="/usr/local/bin:/usr/bin:/bin:/usr/games"

fi

if [ "$PS1" ]; then

if [ "$BASH" ]; then

PS1='u@h:w$ '

else

if [ "`id -u`" -eq 0 ]; then

PS1='# '

else

PS1='$ '

fi

fi

fi

PATH=$PATH:/usr/soft/java/jdk/bin:/usr/soft/java/jdk/jre/bin

JAVA_HOME=/usr/soft/java/jdk

JRE_HOME=/usr/soft/java/jdk/jre

CLASSPATH=.:/usr/soft/java/jdk/lib/tools.jar:/usr/soft/java/jdk/lib/dt.jar

TOMCAT_HOME=/usr/soft/tomcat/tomcat6

CATALINA_HOME=/usr/soft/tomcat/tomcat6

export PATH

export JAVA_HOME

export JRE_HOME

export CLASSPATH

export TOMCAT_HOME

export CATALINA_HOME

umask 022


Debian下安装Eclipse

发表人:xuniji123 | 发表时间: 2008年八月26日, 17:17

www.eclipse.org

下载eclipse-jee-ganymede-linux-gtk.tar.gz

安装:

在拷贝eclipse-jee-ganymede-linux-gtk.tar.gz/usr/soft/eclipse目录下,cd到该目录,执行:

tar -zvxf eclipse-jee-ganymede-linux-gtk.tar.gz

/usr/soft/eclipse下生成eclipse包,进入eclipse下,即/usr/soft/eclipse/eclipse下,执行./eclipse,将运行eclipse出错,提示:“no java virtual machine was found after searching the following locations:”

解决办法:

原因是没找到jre,解决办法是,进入/usr/soft/eclipse/eclipse目录,建立软连接,连接到jre

ln -s /usr/soft/java/jdk/jre jre

debiangary:/usr/soft/eclipse/eclipse# ln -s /usr/soft/java/jdk/jre jre


Debian下安装Java

发表人:xuniji123 | 发表时间: 2008年八月26日, 17:16

http://java.sun.com/javase/downloads/ea/6u10/6u10rcDownload.jsp#6u10JREs

下载jdk-6u10-rc-bin-b28-linux-i586-21_jul_2008.bin

拷贝到/usr/soft/java

并在目录/usr/soft/java

执行./ jdk-6u10-rc-bin-b28-linux-i586-21_jul_2008.bin将开始安装

安装完成后,在目录/usr/soft/java下下生成jdk1.6.0_10文件夹

为了方便,将其重命名为jdk

mv jdk1.6.0_10 jdk

设置环境变量PATHJAVA_HOMEJRE_HOMECLASSPATH,修改/etc/profile文件如下:

# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))

# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).

if [ "`id -u`" -eq 0 ]; then

PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

else

PATH="/usr/local/bin:/usr/bin:/bin:/usr/games"

fi

if [ "$PS1" ]; then

if [ "$BASH" ]; then

PS1='u@h:w$ '

else

if [ "`id -u`" -eq 0 ]; then

PS1='# '

else

PS1='$ '

fi

fi

fi

PATH=$PATH:/usr/soft/java/jdk/bin:/usr/soft/java/jdk/jre/bin

JAVA_HOME=/usr/soft/java/jdk

JRE_HOME=/usr/soft/java/jdk/jre

CLASSPATH=.:/usr/soft/java/jdk/lib/tools.jar:/usr/soft/java/jdk/lib/dt.jar

TOMCAT_HOME=/usr/soft/tomcat/tomcat6

CATALINA_HOME=/usr/soft/tomcat/tomcat6

export PATH

export JAVA_HOME

export JRE_HOME

export CLASSPATH

export TOMCAT_HOME

export CATALINA_HOME

umask 022


Debian下建立SSH

发表人:xuniji123 | 发表时间: 2008年八月26日, 17:15

笔者先完成Debian的安装后(在Windows XP下的VMWare中安装),首先考虑到是怎么让WindowsDebian之间的资源实现共享。

没用Samba,直接想到了安装SSH

即可用在windows下远程控制Debian,又可以将windows下的文件等直接拷贝到debian下。

安装DebianSSH

执行apt-get install openssh-server

cd1iso文件引入到VMWare中。

虚拟机à设置

点击CD-ROM(IDE 1:0),设置如下:

另:

运行安装命令:apt-get install openssh-server 提示有错误,请教了高人,修改/etc/apt/source.list 把源修改为国内的debian.cn99.com就可以正常运行了

apt-get update apt-get install openssh-server

具体的etc/apt/source.list 的配置文件请见附件。(将此文件,不带txt后缀的覆盖掉原来的source.list

启动/停止服务:/etc/init.d/ssh start|stop|restart


Debian安装

发表人:xuniji123 | 发表时间: 2008年八月26日, 17:14

http://cdimage.debian.org/debian-cd/4.0_r4a/i386/iso-cd/

下载debian-40r4a-i386-DVD-1.iso

放到Windows的目录下:

E:XunleiDebian_DVD_CDdebian-40r4a-i386-DVD-1.iso

安装VMware_ha_vmware.exe后,运行

创建虚拟机

 查看全文

在debian下安装eclipse,运行时出错"no java virtual machine was found after searching the following locations"

发表人:xuniji123 | 发表时间: 2008年八月26日, 15:45

下载eclipse-jee-ganymede-linux-gtk.tar.gz
安装:
在拷贝eclipse-jee-ganymede-linux-gtk.tar.gz到/usr/soft/eclipse目录下,cd到该目录,执行:
tar -zvxf eclipse-jee-ganymede-linux-gtk.tar.gz
在/usr/soft/eclipse下生成eclipse包,进入eclipse下,即/usr/soft/eclipse/eclipse下,执行./eclipse,将运行eclipse出错,提示:“no java virtual machine was found after searching the following locations:”

解决办法:

在debian中安装eclipse:
解压到某位置,此处为/usr/soft/eclipse/,运行eclipse时提示“no java virtual machine was found after searching the following locations:”。
原因是没找到jre,解决办法是,进入/usr/soft/eclipse/eclipse目录,建立软连接,连接到jre,
ln -s /usr/soft/java/jdk/jre jre

debiangary:/usr/soft/eclipse/eclipse# ln -s /usr/soft/java/jdk/jre jre


Windows下Subversion和TortoiseSVN构建SVN版本控制

发表人:xuniji123 | 发表时间: 2008年八月13日, 17:57

WindowsSubversionTortoiseSVN构建SVN版本控制

2008-8-13 杨普

1.下载Subversionwindow安装版本svn-1.4.6-setup.exe

http://subversion.tigris.org/

http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=8100

2.下载TortoiseSVNTortoiseSVN-1.5.2.13595-win32-svn-1.5.1.msi版本

http://tortoisesvn.net/

http://tortoisesvn.net/downloads

3.安装subversion

双击svn-1.4.6-setup.exe,一路next完成安装。

设置环境变量,将subversionbin设置到path中。如:D:Program FilesSubversionbin

4.安装TortoiseSVN

双击TortoiseSVN-1.5.2.13595-win32-svn-1.5.1.msi,一路next完成安装。

5.创建svn容器Repository

在硬盘上任意位置创建一文件夹,如D:svnRepository,在文件夹上右键

TortoiseSVN->Create repository here

创建成功后将在D:svnRepository下生成一系列文件。

6.配置容器的访问权限

在容器的目录下D:svnRepositoryconf中,用记事本打开svnserve.conf文件,找到

# anon-access = read

# auth-access = write

# password-db = passwd

并去掉注释#

注意,去掉注释后,不要留下空格,保持每行顶格,切记!!!

效果如下:

### This file controls the configuration of the svnserve daemon, if you

### use it to allow access to this repository. (If you only allow

### access through http: and/or file: URLs, then this file is

### irrelevant.)

### Visit http://subversion.tigris.org/ for more information.

[general]

### These options control access to the repository for unauthenticated

### and authenticated users. Valid values are "write", "read",

### and "none". The sample settings below are the defaults.

anon-access = read

auth-access = write

### The password-db option controls the location of the password

### database file. Unless you specify a path starting with a /,

### the file's location is relative to the directory containing

### this configuration file.

### If SASL is enabled (see below), this file will NOT be used.

### Uncomment the line below to use the default password file.

password-db = passwd

### The authz-db option controls the location of the authorization

### rules for path-based access control. Unless you specify a path

### starting with a /, the file's location is relative to the the

### directory containing this file. If you don't specify an

### authz-db, no path-based access control is done.

### Uncomment the line below to use the default authorization file.

# authz-db = authz

### This option specifies the authentication realm of the repository.

### If two repositories have the same authentication realm, they should

### have the same password database, and vice versa. The default realm

### is repository's uuid.

# realm = My First Repository

[sasl]

### This option specifies whether you want to use the Cyrus SASL

### library for authentication. Default is false.

### This section will be ignored if svnserve is not built with Cyrus

### SASL support; to check, run 'svnserve --version' and look for a line

### reading 'Cyrus SASL authentication is available.'

# use-sasl = true

### These options specify the desired strength of the security layer

### that you want SASL to provide. 0 means no encryption, 1 means

### integrity-checking only, values larger than 1 are correlated

### to the effective key length for encryption (e.g. 128 means 128-bit

### encryption). The values below are the defaults.

# min-encryption = 0

# max-encryption = 256

配置访问用户列表,用户名加密码

记事本打开该目录下的文件passwd

去掉

# harry = harryssecret

# sally = sallyssecret

的注释#,同意注意每行要顶格,开头也不能有空格。

说明harry = harryssecret表示:用户名=密码

当然也可以自己增加,如gary=gary

最好效果如下:

### This file is an example password file for svnserve.

### Its format is similar to that of svnserve.conf. As shown in the

### example below it contains one section labelled [users].

### The name and password for each user follow, one account per line.

[users]

harry=harryssecret

sally=sallyssecret

gary=gary

7.启动Subversion

因为之前设置了环境变量path= D:Program FilesSubversionbin;因此打开cmd,直接运行命令:svnserve -d -r D:svnRepository

这样Subversion服务器就假设好了。

8.向容器添加需版本控制的文件(也可以远程,只需urlip就行)

在硬盘上任意位置,右键需要上传的文件的上级文件夹,TortoiseSVN->Import…

此处为了测试,创建文件夹D:importFiles,里面放一doc文件test.doc,即要将test.doc上传到svn中去。右键importFilesTortoiseSVN->Import…,输入容器的url

svn://localhost/svnRepository

输入用户名和密码:

就将test.doc文件上传到svn容器了

9.从容器获得test.doc文件(也可以远程,只需urlip就行)

在任意位置,某文件上右键D:checkOutFiles,点击SVN Checkout…

输入url即可

10.完成

这样就完成的部署和存取,修改相应的文件,提交即可,注意始终保持Subversion的运行。

注意,在第8步中会报错“期望文件系统格式“2”;发现格式“3””

原因是TortoisSVN的版本过高,或与Subversion不匹配。

应该换成低版本的TortoisSVN TortoiseSVN-1.4.8.12137-win32-svn-1.4.6.msi

即应该为svn-1.4.6-setup.exeTortoiseSVN-1.4.8.12137-win32-svn-1.4.6.msi的组合才行,步骤和之前的一样,只是在第6步中的svnserve.conf文件中没有后面的内容

[sasl]

### This option specifies whether you want to use the Cyrus SASL

### library for authentication. Default is false.

### This section will be ignored if svnserve is not built with Cyrus

### SASL support; to check, run 'svnserve --version' and look for a line

### reading 'Cyrus SASL authentication is available.'

# use-sasl = true

### These options specify the desired strength of the security layer

### that you want SASL to provide. 0 means no encryption, 1 means

### integrity-checking only, values larger than 1 are correlated

### to the effective key length for encryption (e.g. 128 means 128-bit

### encryption). The values below are the defaults.

# min-encryption = 0

# max-encryption = 256


开源项目buffalo2.0最终版正式发布

发表人:xuniji123 | 发表时间: 2007年五月10日, 15:12

Buffalo在经历了两年之久的考验后,近日正式发布2.0版本。Buffalo是一个J2EE轻量级AJAX框架,也是国内著名的开源项目。它与DWR 和JSON-RPC一样,着眼于Web远程调用(Web Remoting),其简洁而实用的特性一直以来深受开发者喜爱。 Buffalo2.0最大的特点在于其性能的提升,还有完全自行实现的Java到JavaScript协议转换。得益于新的协议实现以及为大规模AJAX 调用而进行的优化,2.0版本比前一阶段版性能有进一步的提高。

  在国内,对JavaScript技术深入研究的人可谓凤毛麟角,Buffalo的作者陈金洲 (Michael Chen) 就是其中之一。关于这次Buffalo 2.0版本的新特性,陈金洲这样解释:

  最令人振奋的特性应当是为大规模、频繁远程调用而进行优化的显著性能提升。在2.0-alpha1版本的性能测试中,性能最高提升达到了30%。即便不借助于高级的测试工具,从1.2升级到2.0的用户,应该能显著感受到速度的提升。

  另外,Buffalo 1.x版本的用户都知道,之前的版本都基于Burlap协议,而Burlap协议的维护者Caucho公司已经很久没有更新这个库了。很多在Resin上使用Buffalo的用户发现这样或者那样基于Burlap的各种问题。种种考虑之后,2.0版本正式使用了完全自行编写的协议解析和转换。
  当问到Buffalo希望在众多AJAX框架中扮演一个什么样的角色时,他回答:

  最早的时候希望Buffalo成为一个全功能、全新的、Web 2.0时代的Web框架。异步传输只是其中最基础的一部分。后来发现凭借自己现有的资源(时间,、能力等)不太可能在能够预见的时间内完成这一目标。目前想达到的目标是:最简单最容易使用的AJAX框架。从使用者的反馈看来,这一目标完成的比较不错,大多数用户都能在很短的时间内配置Buffalo并开始使用。

  那么和Web Remoting框架DWR 和JSON-RPC相比较,在JS-Java之间对象转换功能和协议上,Buffalo有何优势所在?

  从整体产品上来说,最大的优势在于简单。核心API只有一个方法。在JS-Java对象转换上,谈不上优势吧,各有千秋:buffalo采用自我描述,完整的XML协议,DWR采用自定义文本协议,JSON对JavaScript更友好。

  社区力量推动Buffalo成长!

  在一年多前的一次BEA活动上,就曾经听到满江红开源组织的负责人曹晓刚讲述“利用元数据和RIA简化企业应用程序的开发”的主题时推荐了Buffalo。时间过去了这么久,Buffalo并没有像许多的开源项目那样销声匿迹,而是还在不断完善,陈金洲解释了Buffalo的开发路线图和背后的支持动力:

  2004年11月的时候我提出了AMOWA的概念——即面向消息的Web应用,第二年春即发布了1.0测试版本。具体的日程可以在Buffalo变更历史里看到。从Buffalo产生至今,整整两年了。新的开发计划,还有很多特性没有完成,例如跟Spring更紧密的集成;文件上载支持,以及更好的OPOA支持等。开发计划完全取决于社区的反馈,以及功能纯粹单一的综合衡量。我不希望Buffalo成为庞然大物。

  其中的动力,我想最大程度上来自于Buffalo社区。在1.2版本发布的时候我写过一篇博客“写在Buffalo1.2发布之后”。我现在的想法虽然稍有不同,但归根结底就是:开源作者提出一个想法,需要得到社区的反馈;同时作者对反馈进行响应。这是一个长期的过程。对此我一直对处在社区中,对Buffalo进行贡献的用户心存感激。Buffalo方便了他们的工作,也满足了我作为一个软件作者某种程度上的虚荣心:),这种感觉,应该是最大的动力吧。

  从2.0-alpha升级到Buffalo 2.0正式版!

  当Buffalo的用户遇到问题时,可以联系Buffalo邮件列表,绝大多数问题都可以找到答案,其他的开发者也会帮助你解决问题。

  从2.0-alpha1发布至今,经过长达半年多的测试阶段,buffalo 2.0正式版本发布。2.0最大的关注点在于性能的提升和完全自行实现的java到javascript协议转换。根据评测,2.0版本要比前一阶段版本最高提升30%性能。这得益于新的协议实现以及为大规模AJAX调用而进行的优化。

  对于一直使用alpha版本的用户,此次升级很简单,只需要将相应的jar和js进行替换即可。从1.2.x版本升级的用户,升级也很简单:

* 删除所有burlap*.jar, buffalo*.jar, 替换为buffalo.jar
* 替换新的buffalo.js
* 将继承自BuffaloService的类,对session等信息的使用替换为对RequestContext.getContext().getXXX的使用。(注意,目前有开发者报告在resin 2.1服务器上偶尔会出现丢session的现象)

  Buffalo2.0正式版本的发布意味着完全自我独立的协议实现,为后续特性的开发打下了基础。

  马上访问Buffalo并download最新2。0版!

  初学者可以到Buffalo的中文wiki look一下,这里有详尽的tutorials!

  当然,在线demo也会生动地展现Buffalo2.0的最新特性!


BEA交付业界首个混合开发环境BEA Workshop 10.1

发表人:xuniji123 | 发表时间: 2007年五月10日, 15:10

全球领先的企业基础架构软件公司BEA系统有限公司日前宣布,推出业界第一个统一的混合开发环境——BEAWorkshop10.1。该产品成功地把最佳的开源和商用软件融入到综合开发环境中,是BEA实现Workspace 360°愿景的重要里程碑。它的推出,不仅表明BEA在执行其混合软件战略方面所取得的持续发展,同时进一步增强了BEA在开发工具市场的领先地位。

BEAWorkshop10.1结合了BEAWorkshop for WebLogic和BEA Workshop Studio,旨在提供功能丰富的综合开发环境,有助于让开发人员能把最佳的开源软件和商用软件结合起来,构建具有服务使能的下一代应用——这是BEA混合战略及开发模式的精髓所在。如今,BEA正在履行之前宣布的计划,把现有的开发工具功能和基于Eclipse的NitroX技术(现已改名为Workshop Studio)合并起来。后者是BEA在2005年秋季收购M7公司而获得的技术,它在2006年获得了Eclipse基金会授予的“基于Eclipse的最佳商用工具”奖。

BEA公司负责工具事业部的副总裁BillRoth说:“BEAWorkshop10.1的推出,表明BEA的混合模式愿景已经开花结果。它可以帮助开发人员按自己所需要的方式、采用开源产品和商用产品来构建应用。混合模式已是许多企业的主导开发模式,而BEA是最先认可这种模式的公司。BEA Workshop 10.1的重要性还在于,它再次证明了BEA能够成功地执行计划、优化收购对象的资产,使他们成为BEA产品组合中不可或缺的部分。”

BEAWorkshop10.1旨在支持JavaEE(Java企业版)5,能够有助于加快并从根本上简化应用开发的过程。它提供了一种集成的对象/关系映射Studio,能够提供面向Eclipse的一流的EJB3/JPA、BEA Kodo™、OpenJPA和Hibernate等工具;该产品还包括了独特的AppXRay™技术和所见即所得(WYSIWYG)的开发功能,它们为众多开源和行业标准框架而设计,包括Java Server Faces(JSF)、Struts/Tiles、Spring、JSP/JSTL、EJB3/Hibernate、Apache Beehive及其他框架,有助于进一步简化开发过程、提高整体生产力。Workshop 10.1的新特性还包括全面的拖放式集成开发环境(IDE)和单一管理点功能,前者用于在BEA WebLogic Server上构建企业级服务,后者用于开源maven编译系统的编译、编译报告及编译文档的编制。BEA Workshop不仅支持Apache Tomcat等开源服务器,同时还支持其他应用服务器,比如IBM和JBoss/Redhat的应用服务器。

BEAWorkshop10.1旨在帮助开发人员与架构师进行协作,并通过全面、可扩展的开发环境实现架构的需求。它在BEAWorkSpace 360°愿景中扮演着重要角色。BEA WorkSpace 360°将在2007年陆续上市,旨在从根本上改变业务和IT专业人员在整个扩展型企业中相互协作与独立工作的方式。


评估用户输入密码的强度(用Javascript)

发表人:xuniji123 | 发表时间: 2007年四月13日, 21:14

密码已经是我们生活工作中必不可少的工具,但一个不安全的密码有又有可能会给我们造成不必要的损失。作为网站设计者,如果我们在网页中能对用户输入的密码进行安全评估,并显示出相应的提示信息,那么对用户设置一个安全的密码将有很大帮助。同时也使得网站更具人性化,更有吸引力.

  什么是一个安全的密码呢?本程序按以下的方式进行评估.

  1.如果密码少于5位,那么就认为这是一个弱密码.

  2.如果密码只由数字、小写字母、大写字母或其它特殊符号当中的一种组成,则认为这是一个弱密码.

  3.如果密码由数字、小写字母、大写字母或其它特殊符号当中的两种组成,则认为这是一个中度安全的密码.

  4.如果密码由数字、小写字母、大写字母或其它特殊符号当中的三种以上组成,则认为这是一个比较安全的密码.

  本程序将根据用户输入的密码分别显示不同的颜色表示密码的强度,具体程序如下:
以下是引用片段:<script language=javascript>



//CharMode函数
//测试某个字符是属于哪一类.
function CharMode(iN){
if (iN>=48 && iN <=57) //数字
return 1;
if (iN>=65 && iN <=90) //大写字母
return 2;
if (iN>=97 && iN <=122) //小写
return 4;
else
return 8; //特殊字符
}

//bitTotal函数
//计算出当前密码当中一共有多少种模式
function bitTotal(num){
modes=0;
for (i=0;i<4;i++){
if (num & 1) modes++;
num>>>=1;
}
return modes;
}

//checkStrong函数
//返回密码的强度级别

function checkStrong(sPW){
if (sPW.length<=4)
return 0; //密码太短
Modes=0;
for (i=0;i<sPW.length;i++){
//测试每一个字符的类别并统计一共有多少种模式.
Modes|=CharMode(sPW.charCodeAt(i));
}

return bitTotal(Modes);

}

//pwStrength函数
//当用户放开键盘或密码输入框失去焦点时,根据不同的级别显示不同的颜色

function pwStrength(pwd){
O_color="#eeeeee";
L_color="#FF0000";
M_color="#FF9900";
H_color="#33CC00";
if (pwd==null||pwd==''){
Lcolor=Mcolor=Hcolor=O_color;
}
else{
S_level=checkStrong(pwd);
switch(S_level) {
case 0:
Lcolor=Mcolor=Hcolor=O_color;
case 1:
Lcolor=L_color;
Mcolor=Hcolor=O_color;
break;
case 2:
Lcolor=Mcolor=M_color;
Hcolor=O_color;
break;
default:
Lcolor=Mcolor=Hcolor=H_color;
}
}

document.getElementById("strength_L").style.background=Lcolor;
document.getElementById("strength_M").style.background=Mcolor;
document.getElementById("strength_H").style.background=Hcolor;
return;
}

</script>

<form name=form1 action="" >
输入密码:<input type=password size=10 onKeyUp=pwStrength(this.value) onBlur=pwStrength(this.value)>
<br>密码强度:
<table width="217" border="1" cellspacing="0" cellpadding="1" bordercolor="#cccccc" height="23" style='display:inline'>
<tr align="center" bgcolor="#eeeeee">

<td width="33%" id="strength_L">弱</td>

<td width="33%" id="strength_M">中</td>

<td width="33%" id="strength_H">强</td>
</tr>
</table>

</form>


详解JAVA数据库基本操作

发表人:xuniji123 | 发表时间: 2007年四月13日, 21:12

java 数据库基本操作
1、java数据库操作基本流程
2、几个常用的重要技巧:
可滚动、更新的记录集
批量更新
事务处理

java数据库操作基本流程:取得数据库连接 - 执行sql语句 - 处理执行结果 - 释放数据库连接
1、取得数据库连接
1)用DriverManager取数据库连接
例子
String className,url,uid,pwd;
className = "oracle.jdbc.driver.OracleDriver";
url = "jdbc:oracle:thin:@127.0.0.1:1521:orasvr;
uid = "system";
pwd = "manager";
Class.forName(className);
Connection cn = DriverManager.getConnection(url,uid,pwd);
2)用jndi(java的命名和目录服务)方式
例子
String jndi = "jdbc/db";
Context ctx = (Context) new InitialContext().lookup("java:comp/env");
DataSource ds = (DataSource) ctx.lookup(jndi);
Connection cn = ds.getConnection();
多用于jsp中

2、执行sql语句
1)用Statement来执行sql语句
String sql;
Statement sm = cn.createStatement();
sm.executeQuery(sql); // 执行数据查询语句(select)
sm.executeUpdate(sql); // 执行数据更新语句(delete、update、insert、drop等)statement.close();
2)用PreparedStatement来执行sql语句
String sql;
sql = "insert into user (id,name) values (?,?)";
PreparedStatement ps = cn.prepareStatement(sql);
ps.setInt(1,xxx);
ps.setString(2,xxx);
...
ResultSet rs = ps.executeQuery(); // 查询
int c = ps.executeUpdate(); // 更新

3、处理执行结果
查询语句,返回记录集ResultSet
更新语句,返回数字,表示该更新影响的记录数
ResultSet的方法
1、next(),将游标往后移动一行,如果成功返回true;否则返回false
2、getInt("id")或getSting("name"),返回当前游标下某个字段的值

4、释放连接
cn.close();
一般,先关闭ResultSet,然后关闭Statement(或者PreparedStatement);最后关闭Connection


可滚动、更新的记录集
1、创建可滚动、更新的Statement
Statement sm = cn.createStatement(ResultSet.TYPE_SCROLL_ENSITIVE,ResultSet.CONCUR_READ_ONLY);
该Statement取得的ResultSet就是可滚动的
2、创建PreparedStatement时指定参数
PreparedStatemet ps = cn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);

ResultSet.absolute(9000);
批量更新
1、Statement
Statement sm = cn.createStatement();
sm.addBatch(sql1);
sm.addBatch(sql2);
...
sm.executeBatch()
一个Statement对象,可以执行多个sql语句以后,批量更新。这多个语句可以是delete、update、insert等或兼有
2、PreparedStatement
PreparedStatement ps = cn.preparedStatement(sql);
{
ps.setXXX(1,xxx);
...
ps.addBatch();
}
ps.executeBatch();
一个PreparedStatement,可以把一个sql语句,变换参数多次执行,一次更新。


事务的处理
1、关闭Connection的自动提交
cn.setAutoCommit(false);
2、执行一系列sql语句
要点:执行每一个新的sql语句前,上一次执行sql语句的Statement(或者PreparedStatemet)必须先close
Statement sm ;
sm = cn.createStatement(insert into user...);
sm.executeUpdate();
sm.close();

sm = cn.createStatement("insert into corp...);
sm.executeUpdate();
sm.close();

3、提交
cn.commit();
4、如果发生异常,那么回滚
cn.rollback();


Java开源软件测试工具大汇总

发表人:xuniji123 | 发表时间: 2007年四月08日, 18:15

JUnit

  JUnit是由Erich Gamma 和Kent Beck 编写的一个回归测试框架(regression testing framework)。Junit测试是程序员测试,即所谓白盒测试,因为程序员知道被测试的软件如何(How)完成功能和完成什么样(What)的功能。Junit是一套框架,继承TestCase类,就可以用Junit进行自动测试了。

  http://www.junit.org/

  Cactus

  Cactus是一个基于JUnit框架的简单测试框架,用来单元测试服务端Java代码。Cactus框架的主要目标是能够单元测试服务端的使用Servlet对象的Java方法如HttpServletRequest,HttpServletResponse,HttpSession等

  http://jakarta.apache.org/cactus/

  Abbot

  Abbot是一个用来测试Java GUIs的框架。用简单的基于XML的脚本或者Java代码,你就可以开始一个GUI。

  http://abbot.sourceforge.net/

  JUnitPerf

  Junitperf实际是junit的一个decorator,通过编写用于junitperf的单元测试,我们也可使测试过程自动化。

  http://www.clarkware.com/software/JUnitPerf.html

  DbUnit

  DbUnit是为数据库驱动的项目提供的一个对JUnit 的扩展,除了提供一些常用功能,它可以将你的数据库置于一个测试轮回之间的状态。

  http://dbunit.sourceforge.net/

  Mockrunner

  Mockrunner用在J2EE环境中进行应用程序的单元测试。它不仅支持Struts actions, servlets,过滤器和标签类还包括一个JDBC和一个JMS测试框架,可以用于测试基于EJB的应用程序。

  http://mockrunner.sourceforge.net/index.html

  DBMonster

  DBMonster是一个用生成随机数据来测试SQL数据库的压力测试工具。

  http://dbmonster.kernelpanic.pl/

  MockEJB

  MockEJB是一个不需要EJB容器就能运行EJB并进行测试的轻量级框架。

  http://mockejb.sourceforge.net/

  StrutsTestCase

  StrutsTestCase 是Junit TestCase类的扩展,提供基于Struts框架的代码测试。StrutsTestCase同时提供Mock 对象方法和Cactus方法用来实际运行Struts ActionServlet,你可以通过运行servlet引擎来测试。因为StrutsTestCase使用ActionServlet控制器来测试你的代码,因此你不仅可以测试Action对象的实现,而且可以测试mappings,from beans以及forwards声明。StrutsTestCase不启动servlet容器来测试struts应用程序(容器外测试)也属于Mock对象测试,但是与EasyMock不同的是,EasyMock是提供了创建Mock对象的API,而StrutsTest则是专门负责测试Struts应用程序的Mock对象测试框架。

  http://strutstestcase.sourceforge.net/

JFCUnit

  JFCUnit使得你能够为Java偏移应用程序编写测试例子。它为从用代码打开的窗口上获得句柄提供了支持;为在一个部件层次定位部件提供支持;为在部件中发起事件(例如按一个按钮)以及以线程安全方式处理部件测试提供支持。

  http://jfcunit.sourceforge.net/

  JTestCase

  JTestCase 使用XML文件来组织多测试案例数据,声明条件(操作和期望的结果),提供了一套易于使用的方法来检索XML中的测试案例,按照数据文件的定义来声明结果。

  http://jtestcase.sourceforge.net/

  SQLUnit

  SQLUnit是一个单元测试框架,用于对数据库存储过程进行回归测试。用Java/JUnit/XML开发。

  http://sqlunit.sourceforge.net

  JTR

  JTR (Java Test Runner)是一个开源的基于反转控制(IOC)的J2EE测试框架。它允许你构建复杂的J2EE测试套件(Test Suites)并连到应用服务器执行测试,可以包括多个测试实例。JTR的licensed是GPL协议。

  http://jtrunner.sourceforge.net/

  Marathon

  Marathon是一个针对使用Java/Swing开发GUI应用程序的测试框架,它由recorder, runner 和editor组成,测试脚本是python代码。Marathon的焦点是放在最终用户的测试上。

  http://marathonman.sourceforge.net

  TestNG

  TestNG是根据JUnit 和NUnit思想而构建的一个测试框架,但是TestNG增加了许多新的功能使得它变得更加强大与容易使用比如:

  *支持JSR 175注释(JDK 1.4利用JavaDoc注释同样也支持)

  *灵活的Test配置

  *支持默认的runtime和logging JDK功能

  *强大的执行模型(不再TestSuite)

  *支持独立的测试方法。

  http://testng.org/

  Surrogate Test framework

  Surrogate Test framework是一个值得称赞单元测试框架,特别适合于大型,复杂Java系统的单元测试。这个框架能与JUnit,MockEJB和各种支持模拟对象(mock object )的测试工具无缝给合。这个框架基于AspectJ技术。

  http://surrogate.sourceforge.net

  MockCreator

  MockCreator可以为给定的interface或class生成模拟对象(Mock object)的源码。

  http://mockcreator.sourceforge.net/

jMock

  jMock利用mock objects思想来对Java code进行测试。jMock具有以下特点:容易扩展,让你快速简单地定义mock objects,因此不必打破程序间的关联,让你定义灵活的超越对象之间交互作用而带来测试局限,减少你测试地脆弱性。

  http://www.jmock.org/

  EasyMock

  EasyMock为Mock Objects提供接口并在JUnit测试中利用Java的proxy设计模式生成它们的实例。EasyMock最适合于测试驱动开发。

  http://www.easymock.org/

  The Grinder

  The Grinder是一个负载测试框架。在BSD开源协议下免费使用。

  http://grinder.sourceforge.net/

  XMLUnit

  XMLUnit不仅有Java版本的还有.Net版本的。Java开发的XMLUnit提供了两个JUnit 扩展类XMLAssert和XMLTestCase,和一组支持的类。这些类可以用来比较两张XML之间的不同之处,展示XML利用XSLT来,校验XML,求得XPath表达式在XML中的值,遍历XML中的某一节点利DOM展开,

  http://xmlunit.sourceforge.net/

  Jameleon

  Jameleon一个自动化测试工具。它被用来测试各种各样的应用程序,所以它被设计成插件模式。为了使整个测试过程变得简单Jameleon提供了一个GUI,因此Jameleon实现了一个Swing 插件。

  http://jameleon.sourceforge.net/index.html

  J2MEUnit

  J2MEUnit是应用在J2ME应用程序的一个单元测试框架。它基于JUnit.

  http://j2meunit.sourceforge.net/

  Jetif

  Jetif是一个用纯Java实现的回归测试框架。它为Java程序单元测试以及功能测试提供了一个简单而且可伸缩的架构,可以用于个人开发或企业级开发的测试。它容易使用,功能强大,而且拥有一些企业级测试的重要功能。Jetif来源于JUnit, JTestCase以及TestNG的启发,有几个基本的概念直接来自于JUnit,比如说断言机制,Test Listener的概念,因此从JUnit转到Jetif是非常容易的。

  http://jetif.sourceforge.net/

  GroboUtils

  GroboUtils使得扩展Java测试变得可能。它包括用在Java不同方面测试的多个子项目。在GroboUtils中最常被到的工具是:多线程测试(multi-threaded tests),整体单元测试(hierarchial unit tests),代码覆盖工具(code coverage tool)。

  http://groboutils.sourceforge.net/

  Testare

  TESTARE是用来简化分布式应用程序(比如:在SERVLETS,JMS listeners, CORBA ORBs或RMI环境下)测试开发过程的一个测试框架.

  https://testare.dev.java.net/


JSP和JSF双剑合并 打造完美Web应用

发表人:xuniji123 | 发表时间: 2007年一月23日, 19:38

Java在最近几年逐渐升温,随着Java SE 5和Java SE 6的推出,Java的未来更显得无比辉煌。但以Java为基础的JSP在Java SE 5推出之前却一直抬不起头来,这最重要的原因就是JSP虽然功能十分强大,但最大的优点也是它的最大缺点,功能强大就意味着复杂,尤其是设计前端界面的可视化工具不多,也不够强大。因此,设计JSP页面就变得十分复杂和繁琐。不过,在Java SE 5推出的同时,Sun为了简化JSP的开发难度,推出了新的JavaServer Faces(简称JSF)规范。从而使JSP走上了康庄大道。

  一、什么是JSF

  JSF和JSP是一对新的搭档。JSP是用于后台的逻辑处理的技术,而JSF恰恰相反,是使开发人员能够快速的开发基于 Java 的 Web 应用程序的技术,是一种表现层技术。目前,JSF1.2已经正式作为一个标准加入了Java EE 5中。

  作为一种高度组件化的技术,开发人员可以在一些开发工具的支持下,实现拖拉式编辑操作,用户只需要简单的将 JSF 组件拖到页面上,就可以很容易的进行 Web 开发了。这是其作为一种组件化的技术所具有的最大好处,我们能用的组件不光是一些比较简单的输入框之类,还有更多复杂的组件可以使用的,比如 DataTable 这样的表格组件, Tree 这样的树形组件等等。

  作为一种标准的技术,JSF还得到了相当多工具提供商的支持。同时我们也会有很多很好的免费开发工具可以使用,前不久 Sun Java Studio Creator 2 和 Oracle JDeveloper 10g 作为免费的支持 JSF 的开发工具发布,给 JSF 带来了不小的生气。另外我们也有一些很优秀的商业开发工具可共选择,BEA Workshop (原 M7 NitroX),Exadel,MyEclipse 这样的基于 Eclipse 的插件开发工具,为现在广大的 Eclipse 用户带来了不小的便利,IBM 的 Rational Application Developer 和 Borland 的 JBuilder 也是很不错的支持 JSF 可视化开发的商业开发工具。

  JSF和传统的Web技术有着本质上的差别,在传统的Web技术需要用户自己对浏览器请求进行捕捉,保存客户端状态,并且手工控制着页面的转向,等等。而JSF的出现,无疑给我们带来了巨大的便利,JSF 提供了事件驱动的页面导航模型,该模型使应用程序开发人员能够设计应用程序的页面流。与 Struts 的方式向类似的是,所有的页面流信息都定义在 JSF 配置 XML 文件 (faces-config.xml) 中,而非硬编码在应用程序中。这很大程度简化了开发人员开发难度,简化了应用程序的开发。

  同时JSF也是一种遵循模型-视图-控制器 (MVC) 模式的框架。实现了视图代码(View)与应用逻辑(Model)的完全分离,使得使用 JSF 技术的应用程序能够很好的实现页面与代码的分离。所有对 JSF 页面的请求都会通过一个前端控制器 (FacesServlet) 处理,系统自动处理用户的请求,并将结果返回给用户。这和传统的 MVC 框架并没有太大的区别。

  在JSF中不仅使用了 POJO 技术,而且还使用了类似 Spring 的控制反转(IoC) (或称为依赖注入-DI) 技术,在 JSF 的 Backing Bean 中,我们可以把视图所需要的数据和操作放进一个 Backing Bean 中。同时得益于 JSF 使用的 DI 技术,我们可以在配置文件中初始化 Managed Bean,同时我们也可以通过这样的技术很方便的和使用类似技术的 Spring 进行整合。

二、如何在JSP中使用JSF
  JSF只有通过和JSP相结合,才能充分发挥它的功效。JSF是通过标签库和JSP进行集成的。标签库就相当于ASP.NET的服务端组件。JSF提供了非常丰富的标签库,通过这些标签库,可以生成各种客户端模型,如HTML、WML、XML以及JavaScript等。通过这些标签,你可以很容易建立大规模的客户端模型,并由这些标签自动处理客户端请求。

  接下来让我们来看一个如何使JSF和JSP在一起工作的例子。在JSF中有两个库。第一个叫做内核库,在这个库中包含了各种主要的标签,如配置组件、管理事件、验证输入信息等。第二个库的主要功能是将HTML和JSF的各种标签相对应。每一个JSF标签都会对应一个HTML组件。如UIInput标签对应了HTML中的文本框或密码框。

  在JSF标签中文本输入框叫做inputText,而密码输入库叫inputSecret。下面是一个简单的JSF和JSP结合的用户接口程序。

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=GB2312">
<title>第一个JSF程序</title>
</head>
<body>
 <f:view>
 <h:form id="simpleForm">
 <h:outputText id="favoriteLabel" value="请输入一个数字:"/>
 <h:inputText id="favoriteValue" value="#{simple.longValue}">
  <f:validateLongrange maximum="30" minimum="0"/>
 </h:inputText>
 <p/>
 <h:commandButton id="submit" value="提交" action="#{simple.simpleActionMethod}"/>
 </h:form>
 </f:view>
</body>
</html>


  在上面的代码中,我们可以了解到JSF是如何同JSP集成的。我们首先可以看到一个内核标签:view。然后是几个JSF组件。如form、outputText、inputText以及commandButton。这几个组件被放到form中从而开成了form中的一部分。在程序的最开始,必须使用import导入两个标签库。代码如下。

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>


  上面2行代码声明了JSP中要使用哪一个JSF标签库。内核库使用前缀(prefix)f声明,而HTML库使用前缀(prefix)h声明。这两个前缀并不是必须要使用,而只是一个建议。在程序中,内核库必须要使用,因为view在所有的JSF页中必须使用。而HTML标签在运行时将JSF标签转化为HTML组件,这个h前缀并不是必须的,而是JSF规范推荐使用的,这样,我们使我们的JSF程序更易读。

  在声明后是几行标准的HTML语句,本文不再详述。从<f:view>开始,是一段JSF语句。这段代码如下所示:

<f:view>
<h:form id="simpleForm">
<h:outputText id="favoriteLabel" value="请输入一个数字:"/>
<h:inputText id="favoriteValue" value="#{simple.longValue}">
<f:validateLongrange maximum="30" minimum="0"/>
</h:inputText>
<p/>
<h:commandButton id="submit" value="提交"
action="#{simple.simpleActionMethod}"/>
</h:form>
</f:view>


  </f:view>标签预示着JSF的开始,而它的下一个标签form将建立一个HTML Form。而outputText标签相当于HTML中的label组件。inputText标签相当于HTML中的textField组件。而commandButton标签相当于HTML中的submit按钮。

三、JSP如何响应JSF的请求
  从上面的例子我们已经知道如何在JSP中使用JSF了,在这一部分让我们来看看在JSF是如何处理请求的。

  首先让我们来看一个例子,这个例子是将华氏度转换为摄氏度。当用户点击提交按钮时程序将进行转换。

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<html>
<head>
 <meta HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=GB2312">
<title>温度转换程序</title>
</head>
<body>
 <f:view>
 <h:form>
 <div>
  <h:outputText id="fahrenheitLabel" value="请输入华氏温度:"/>
  <span>
   <h:inputText id="temperature" value="#{tc.fahrenheitTemp}">
   <f:validateDoublerange minimum="-100.0" maximum="100.0"/>
   <f:valuechangeListener type="tempconv.page.TCChangedListener"/>
  </h:inputText>
  </span>
 </div>
 <div>
  <h:outputText id="celsiusLabel" value="摄氏温度:"/>
  <span>
   <h:outputText id="celsiusValue" value="#{tc.celsiusTemp}">
   <f:convertNumber maxFractionDigits="3" type="number"/>
  </h:outputText>
  </span>
 </div>
 <div>
  <h:commandButton value="转换" action="#{tc.convert}">
  </h:commandButton>
 </div>
 </h:form>
 </f:view>
</body>
</html>

  在程序的前两行是导入JSF核心库和HTML库,这个在前面已经讨论过,在这里不再详述。

  下面让我们来看看JSF标签是如何同后端进行交互的。由于我们是在JSP中使用JSF,因此,这个和正常的JSP没有什么区别;JSP实际上就是Servlet,在JSP第一次运行时由JSP编译器将.JSP文件编译成Servlet后再由Servlet调用,然后由Servlet来接收客户端传过来的数据流。但和一般的JSP程序不同的是,JSF标签是由JSF API负责调用的(这样可以做到逻辑层和表现层分离),除此之外,它们和一般的JSP标签没有任何区别。

  当UIComponent标签收到doStartTag方法时,JSF将使用这些属性来设置标签的值。如本例中的inputText标签将按它的属性值来设置。下面是JSF的代码片段。

<h:inputText id="temperature" value="#{tc.fahrenheitTemp}">
 <f:validateDoublerange minimum="-100.0" maximum="100.0"/>
 <f:valuechangeListener type="tempconv.page.TCChangedListener"/>
</h:inputText>

  inputText标签根据相应的值设置了id和value的属性。在JSF中是通过setAttribute(String name, Object value)设置每一个属性值的。但我们需要注意的是JSF标签可以指定相应的默认值。这有些类似java中的系统属性,如果你给了一个属性名子,那系统将返回这个属性的值,如果指定它的默认值,并且这个属性不存在的话,将返回这个默认值。

  接下来让我们来看看上面程序的最重要的部分,也就是UIInput组件的事件处理。

<f:valuechangeListener type="tempconv.page.TCChangedListener"/>

  在JSF中事件处理是由valuechangeListener标签完成的。这个标签所表示的事件在文本框的值发生变化时引发事件。但有意思的是这个事件并不马上提交,而是要等到用户点击"提交"按钮后这个事件连同相应的数据才提交给后端。因此,这个事件请求也叫做预提交。最后,让我们看看UICommand的代码实现。

<div>
 <h:commandButton value="转换" action="#{tc.convert}">
 </h:commandButton>
</div>

  上面的代码将convert()方法和UICommand连接了起来,也就是说,点击"提交"按钮后,将执行convert()方法。在遇到view标签后,JSF程序结果,JSFAPI最后调用doEnd方法来结束JSF程序。JSF引擎在解析这段程序后,将相应的JSF标签转换为HTML组件。

  最后,让我们来看看JSP是如何响应JSF事件的。下面是一段响应JSF事件的Java代码。

public class TCChangedListener implements ValueChangeListener
{
 public TCChangedListener()
 {
  super();
 }
 // 事件处理
 public void processValueChange(ValueChangeEvent event)
throws AbortProcessingException
 {
  UIComponent comp = event.getComponent();
  Object value = event.getNewValue();
  if (null != value)
  {
   float curVal = ((Number) value).floatValue();
   Map values = comp.getAttributes();
   if (curVal < 0)
   {
    values.put("styleClass", "red");
   }
   else
   {
    values.put("styleClass", "black");
   }
  }
}

  要想响应JSF事件,必须要实现JSF库中的ValueChangeListener接口。上面的程序要注意的是最后根据输入的值来设置相应的颜色。这些值并不依赖JSP。当然,你也可以将它们设置成null,而由JSP 标签来设置它们的颜色。


Java的30个基本概念

发表人:xuniji123 | 发表时间: 2007年一月23日, 19:34

在我们学习Java的过程中,掌握其中的基本概念对我们的学习无论是J2SE,J2EE,J2ME都是很重要的,J2SE是Java的基础,所以有必要对其中的基本概念做以归纳,以便大家在以后的学习过程中更好的理解java的精髓,在此我总结了30条基本的概念.

  Java概述:
   目前Java主要应用于中间件的开发(middleware)---处理客户机于服务器之间的通信技术,早期的实践证明,Java不适合pc应用程序的 开发,其发展逐渐变成在开发手持设备,互联网信息站,及车载计算机的开发.Java于其他语言所不同的是程序运行时提供了平台的独立性,称许可以在 windows,solaris,linux其他操作系统上使用完全相同的代码.Java的语法与C++语法类似,C++/C程序员很容易掌握,而且 Java是完全的彻底的面向对象的,其中提出了很好的GC(Garbage Collector)垃圾处理机制,防止内存溢出.
  Java的白皮书为我们提出了Java语言的11个关键特性.
  (1)Easy:Java的语法比C++的相对简单,另一个方面就是Java能使软件在很小的机器上运行,基础解释其和类库的支持的大小约为40kb,增加基本的标准库和线程支持的内存需要增加125kb.
  (2)分布式:Java带有很强大的TCP/IP协议族的例程库,Java应用程序能够通过URL来穿过网络来访问远程对象,由于servlet机制的出现,使Java编程非常的高效,现在许多的大的web server都支持servlet.
  (3)OO:面向对象设计是把重点放在对象及对象的接口上的一个编程技术.其面向对象和C++有很多不同,在与多重继承的处理及Java的原类模型.
  (4)健壮特性:Java采取了一个安全指针模型,能减小重写内存和数据崩溃的可能性。
  (5)安全:Java用来设计网路和分布系统,这带来了新的安全问题,Java可以用来构建防病毒和防攻击的System.事实证明Java在防毒这一方面做的比较好.
(6)中立体系结构:Java编译其生成体系结构中立的目标文件格式可以在很多处理器上执行,编译器产生的指令字节码(Javabytecode)实现此特性,此字节码可以在任何机器上解释执行.
  (7)可移植性:Java中对基本数据结构类型的大小和算法都有严格的规定所以可移植性很好.
  (8)多线程:Java处理多线程的过程很简单,Java把多线程实现交给底下操作系统或线程程序完成.所以多线程是Java作为服务器端开发语言的流行原因之一
  (9)Applet和servlet:能够在网页上执行的程序叫Applet,需要支持Java的浏览器很多,而applet支持动态的网页,这是很多其他语言所不能做到的.
  基本概念:
   1.OOP中唯一关系的是对象的接口是什么,就像计算机的销售商她不管电源内部结构是怎样的,他只关系能否给你提供电就行了,也就是只要知道can or not而不是how and why.所有的程序是由一定的属性和行为对象组成的,不同的对象的访问通过函数调用来完成,对象间所有的交流都是通过方法调用,通过对封装对象数据,很大 限度上提高复用率.
  2.OOP中最重要的思想是类,类是模板是蓝图,从类中构造一个对象,即创建了这个类的一个实例(instance)
  3.封装:就是把数据和行为结合起在一个包中)并对对象使用者隐藏数据的实现过程,一个对象中的数据叫他的实例字段(instance field)
  4.通过扩展一个类来获得一个新类叫继承(inheritance),而所有的类都是由Object根超类扩展而得,根超类下文会做介绍.
  5.对象的3个主要特性
  behavior---说明这个对象能做什么.
  state---当对象施加方法时对象的反映.
  identity---与其他相似行为对象的区分标志.
  每个对象有唯一的indentity 而这3者之间相互影响.
6.类之间的关系:
  use-a :依赖关系
  has-a :聚合关系
  is-a :继承关系--例:A类继承了B类,此时A类不仅有了B类的方法,还有其自己的方法.(个性存在于共性中)
  7.构造对象使用构造器:构造器的提出,构造器是一种特殊的方法,构造对象并对其初始化.
  例:Data类的构造器叫Data
  new Data()---构造一个新对象,且初始化当前时间.
  Data happyday=new
  Data()---把一个对象赋值给一个变量happyday,从而使该对象能够多次使用,此处要声明的使变量与对象变量二者是不同的.new返回的值是一个引用.
  构造器特点:构造器可以有0个,一个或多个参数
  构造器和类有相同的名字
  一个类可以有多个构造器
  构造器没有返回值
  构造器总是和new运算符一起使用.
  8.重载:当多个方法具有相同的名字而含有不同的参数时,便发生重载.编译器必须挑选出调用哪个方法.
  9.包(package)Java允许把一个或多个类收集在一起成为一组,称作包,以便于组织任务,标准Java库分为许多包.java.lang java.util java,net等,包是分层次的所有的java包都在java和javax包层次内.
  10.继承思想:允许在已经存在的类的基础上构建新的类,当你继承一个已经存在的类时,那么你就复用了这个类的方法和字段,同时你可以在新类中添加新的方法和字段.
  11.扩展类:扩展类充分体现了is-a的继承关系. 形式为:class (子类) extends (基类).
  12.多态:在java中,对象变量是多态的.而java中不支持多重继承.
13.动态绑定:调用对象方法的机制.
  (1)编译器检查对象声明的类型和方法名.
  (2)编译器检查方法调用的参数类型.
  (3)静态绑定:若方法类型为priavte static final 编译器会准确知道该调用哪个方法.
  (4)当程序运行并且使用动态绑定来调用一个方法时,那么虚拟机必须调用x所指向的对象的实际类型相匹配的方法版本.
  (5)动态绑定:是很重要的特性,它能使程序变得可扩展而不需要重编译已存代码.
  14.final类:为防止他人从你的类上派生新类,此类是不可扩展的.
  15.动态调用比静态调用花费的时间要长,
  16.抽象类:规定一个或多个抽象方法的类本身必须定义为abstract例: public abstract string getDescripition
  17.Java中的每一个类都是从Object类扩展而来的.
  18.object类中的equal和toString方法.equal用于测试一个对象是否同另一个对象相等.toString返回一个代表该对象的字符串,几乎每一个类都会重载该方法,以便返回当前状态的正确表示.(toString 方法是一个很重要的方法)
  19.通用编程:任何类类型的所有值都可以同object类性的变量来代替.
  20.数组列表:ArrayList动态数组列表,是一个类库,定义在java.uitl包中,可自动调节数组的大小.
  21.class类 object类中的getclass方法返回ckass类型的一个实例,程序启动时包含在main方法的类会被加载,虚拟机要加载他需要的所有类,每一个加载的类都要加载它需要的类.
   22.class类为编写可动态操纵java代码的程序提供了强大的功能反射,这项功能为JavaBeans特别有用,使用反射Java能支持VB程序 员习惯使用的工具.能够分析类能力的程序叫反射器,Java中提供此功能的包叫Java.lang.reflect反射机制十分强大.
  1.在运行时分析类的能力.
  2.在运行时探察类的对象.
  3.实现通用数组操纵代码.
  4.提供方法对象.
  而此机制主要针对是工具者而不是应用及程序.
  反射机制中的最重要的部分是允许你检查类的结构.用到的API有:
  java.lang.reflect.Field 返回字段.
  java.reflect.Method 返回方法.
  java.lang.reflect.Constructor 返回参数.
  方法指针:java没有方法指针,把一个方法的地址传给另一个方法,可以在后面调用它,而接口是更好的解决方案.
23.接口(Interface)说明类该做什么而不指定如何去做,一个类可以实现一个或多个interface.
  24.接口不是一个类,而是对符合接口要求的类的一套规范.若实现一个接口需要2个步骤:
  1.声明类需要实现的指定接口.
  2.提供接口中的所有方法的定义.
  声明一个类实现一个接口需要使用implements 关键字class actionB implements Comparable 其actionb需要提供CompareTo方法,接口不是类,不能用new实例化一个接口.
  25.一个类只有一个超类,但一个类能实现多个接口.Java中的一个重要接口Cloneable
  26.接口和回调.编程一个常用的模式是回调模式,在这种模式中你可以指定当一个特定时间发生时回调对象上的方法.例:ActionListener 接口监听.
  类似的API有:java.swing.JOptionPane
        java.swing.Timer
        java.awt.Tookit
  27.对象clone:clone方法是object一个保护方法,这意味着你的代码不能简单的调用它.

如何才算掌握Java(J2SE篇)

发表人:xuniji123 | 发表时间: 2007年一月07日, 13:49

时常看到一些人说掌握了Java,但是让他们用Java做一个实际的项目可能又困难重重,在这里,笔者根据自己的一点理解斗胆提出自己的一些对掌握Java这个说法的标准,当然对于新手,也可以提供一个需要学习哪些内容的参考。另外这个标准仅限于J2SE部分,J2EE部分的内容有时间再另说。
1、语法:必须比较熟悉,在写代码的时候IDE的编辑器对某一行报错应该能够根据报错信息知道是什么样的语法错误并且知道任何修正。
2、命令:必须熟悉JDK带的一些常用命令及其常用选项,命令至少需要熟悉:appletviewer、HtmlConverter、jar、java、javac、javadoc、javap、javaw、native2ascii、serialver,如果这些命令你没有全部使用过,那么你对java实际上还很不了解。
3、工具:必须至少熟练使用一种IDE的开发工具,例如Eclipse、Netbeans、JBuilder、Jdeveloper、IDEA、JCreator或者Workshop,包括进行工程管理、常用选项的设置、插件的安装配置以及进行调试。
4、API:Java的核心API是非常庞大的,但是有一些内容笔者认为是必须熟悉的,否则不可能熟练的运用Java,包括:
1)、java.lang包下的80%以上的类的功能的灵活运用。
2)、java.util包下的80%以上的类的灵活运用,特别是集合类体系、规则表达式、zip、以及时间、随机数、属性、资源和Timer。
3)、java.io包下的60%以上的类的使用,理解IO体系的基于管道模型的设计思路以及常用IO类的特性和使用场合。
4)、java.math包下的100%的内容。
5)、java.net包下的60%以上的内容,对各个类的功能比较熟悉。
6)、java.text包下的60%以上的内容,特别是各种格式化类。
7)、熟练运用JDBC。
8)、java.security包下40%以上的内容,如果对于安全没有接触的话根本就不可能掌握java。
9)、AWT的基本内容,包括各种组件事件、监听器、布局管理器、常用组件、打印。
10)、Swing的基本内容,和AWT的要求类似。
11)、XML处理,熟悉SAX、DOM以及JDOM的优缺点并且能够使用其中的一种完成XML的解析及内容处理。
5、测试:必须熟悉使用junit编写测试用例完成代码的自动测试。
6、管理:必须熟悉使用ant完成工程管理的常用任务,例如工程编译、生成javadoc、生成jar、版本控制、自动测试。
7、排错:应该可以根据异常信息比较快速的定位问题的原因和大致位置。
8、思想:必须掌握OOP的主要要求,这样使用Java开发的系统才能是真正的Java系统。
9、规范:编写的代码必须符合流行的编码规范,例如类名首字母大写,成员和方法名首字母小写,方法名的第一个单词一般是动词,包名全部小写等,这样程序的可读性才比较好。
 查看全文

JDK6.0的新特性:使用Compiler API

发表人:xuniji123 | 发表时间: 2007年一月02日, 20:29

现在我们可以用JDK6 的Compiler API(JSR 199)去动态编译Java源文件,Compiler API结合反射功能就可以实现动态的产生Java代码并编译执行这些代码,有点动态语言的特征。这个特性对于某些需要用到动态编译的应用程序相当有用, 比如JSP Web Server,当我们手动修改JSP后,是不希望需要重启Web Server才可以看到效果的,这时候我们就可以用Compiler API来实现动态编译JSP文件,当然,现在的JSP Web Server也是支持JSP热部署的,现在的JSP Web Server通过在运行期间通过Runtime.exec或ProcessBuilder来调用javac来编译代码,这种方式需要我们产生另一个进程去做编译工作,不够优雅而且容易使代码依赖与特定的操作系统;Compiler API通过一套易用的标准的API提供了更加丰富的方式去做动态编译,而且是跨平台的。 下面代码演示了Compiler API的使用:

public class CompilerAPITester {
 private static String JAVA_SOURCE_FILE = "DynamicObject.java";
 private static String JAVA_CLASS_FILE = "DynamicObject.class";
 private static String JAVA_CLASS_NAME = "DynamicObject";
 public static void main(String[] args) {
  JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
  StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
  generateJavaClass();
  try {
   //将产生的类文件拷贝到程序的ClassPath下面,下面这一行代码是特定于Windows+IntelliJ IDEA 6.0项目,不具有移植性
   Runtime.getRuntime().exec("cmd /c copy "+JAVA_CLASS_FILE+" classesproductionJDK6Features");
   Iterable<? extends JavaFileObject> sourcefiles = fileManager.getJavaFileObjects(JAVA_SOURCE_FILE);
   compiler.getTask(null, fileManager, null, null, null, sourcefiles).call();
   fileManager.close();
   Class.forName(JAVA_CLASS_NAME).newInstance();//创建动态编译得到的DynamicObject类的实例
  } catch (Exception ex) {
   ex.printStackTrace();
  }
 }

 public static void generateJavaClass(){
  try {
   FileWriter fw = new FileWriter(JAVA_SOURCE_FILE);
   BufferedWriter bw = new BufferedWriter(fw);
   bw.write("public class "+JAVA_CLASS_NAME+"{");
   bw.newLine();
   bw.write("public "+JAVA_CLASS_NAME+"(){System.out.println("In the constructor of DynamicObject");}}");
   bw.flush();
   bw.close();
  } catch (IOException ex) {
   ex.printStackTrace();
  }
 }
}

  程序运行后,会产生DynamicObject.java和DynamicObject.class两个文件,并在控制台输出:

  In the constructor of DynamicObject

JSP 9个内置对象方法使用

发表人:xuniji123 | 发表时间: 2007年一月01日, 23:25

1.request对象
客户端的请求信息被封装在request对象中,通过它才能了解到客户的需求,然后做出响应。它是HttpServletRequest类的实例。


1 object getAttribute(String name) 返回指定属性的属性值
[/color]2 Enumeration getAttributeNames() 返回所有可用属性名的枚举
3 String getCharacterEncoding() 返回字符编码方式
4 int getContentLength() 返回请求体的长度(以字节数)
5 String getContentType() 得到请求体的MIME类型
6 ServletInputStream getInputStream() 得到请求体中一行的二进制流
7 String getParameter(String name) 返回name指定参数的参数值
8 Enumeration getParameterNames() 返回可用参数名的枚举
9 String[] getParameterValues(String name) 返回包含参数name的所有值的数组
10 String getProtocol() 返回请求用的协议类型及版本号
11 String getScheme() 返回请求用的计划名,如:http.https及ftp等
12 String getServerName() 返回接受请求的服务器主机名
13 int getServerPort() 返回服务器接受此请求所用的端口号
14 BufferedReader getReader() 返回解码过了的请求体
15 String getRemoteAddr() 返回发送此请求的客户端IP地址
16 String getRemoteHost() 返回发送此请求的客户端主机名
17 void setAttribute(String key,Object obj) 设置属性的属性值
18 String getRealPath(String path) 返回一虚拟路径的真实路径

[color=crimson]
2.response对象
response对象包含了响应客户请求的有关信息,但在JSP中很少直接用到它。它是HttpServletResponse类的实例。


1 String getCharacterEncoding() 返回响应用的是何种字符编码
2 ServletOutputStream getOutputStream() 返回响应的一个二进制输出流
3 PrintWriter getWriter() 返回可以向客户端输出字符的一个对象
4 void setContentLength(int len) 设置响应头长度
5 void setContentType(String type) 设置响应的MIME类型
6 sendRedirect(java.lang.String location) 重新定向客户端的请求


3.session对象
session对象指的是客户端与服务器的一次会话,从客户连到服务器的一个WebApplication开始,直到客户端与服务器断开连接为止。它是HttpSession类的实例.


1 long getCreationTime() 返回SESSION创建时间
2 public String getId() 返回SESSION创建时JSP引擎为它设的惟一ID号
3 long getLastAccessedTime() 返回此SESSION里客户端最近一次请求时间
4 int getMaxInactiveInterval() 返回两次请求间隔多长时间此SESSION被取消(ms)
5 String[] getValueNames() 返回一个包含此SESSION中所有可用属性的数组
6 void invalidate() 取消SESSION,使SESSION不可用
7 boolean isNew() 返回服务器创建的一个SESSION,客户端是否已经加入
8 void removeValue(String name) 删除SESSION中指定的属性
9 void setMaxInactiveInterval() 设置两次请求间隔多长时间此SESSION被取消(ms)


4.out对象
out对象是JspWriter类的实例,是向客户端输出内容常用的对象


1 void clear() 清除缓冲区的内容
2 void clearBuffer() 清除缓冲区的当前内容
3 void flush() 清空流
4 int getBufferSize() 返回缓冲区以字节数的大小,如不设缓冲区则为0
5 int getRemaining() 返回缓冲区还剩余多少可用
6 boolean isAutoFlush() 返回缓冲区满时,是自动清空还是抛出异常
7 void close() 关闭输出流


5.page对象
page对象就是指向当前JSP页面本身,有点象类中的this指针,它是java.lang.Object类的实例



1 class getClass 返回此Object的类
2 int hashCode() 返回此Object的hash码
3 boolean equals(Object obj) 判断此Object是否与指定的Object对象相等
4 void copy(Object obj) 把此Object拷贝到指定的Object对象中
5 Object clone() 克隆此Object对象
6 String toString() 把此Object对象转换成String类的对象
7 void notify() 唤醒一个等待的线程
8 void notifyAll() 唤醒所有等待的线程
9 void wait(int timeout) 使一个线程处于等待直到timeout结束或被唤醒
10 void wait() 使一个线程处于等待直到被唤醒
11 void enterMonitor() 对Object加锁
12 void exitMonitor() 对Object开锁


6.application对象
application对象实现了用户间数据的共享,可存放全局变量。它开始于服务器的启动,直到服务器的关闭,在此期间,此对象将一直存在;这样在用户的前后连接或不同用户之间的连接中,可以对此对象的同一属性进行操作;在任何地方对此对象属性的操作,都将影响到其他用户对此的访问。服务器的启动和关闭决定了application对象的生命。它是ServletContext类的实例。



1 Object getAttribute(String name) 返回给定名的属性值
2 Enumeration getAttributeNames() 返回所有可用属性名的枚举
3 void setAttribute(String name,Object obj) 设定属性的属性值
4 void removeAttribute(String name) 删除一属性及其属性值
5 String getServerInfo() 返回JSP(SERVLET)引擎名及版本号
6 String getRealPath(String path) 返回一虚拟路径的真实路径
7 ServletContext getContext(String uripath) 返回指定WebApplication的application对象
8 int getMajorVersion() 返回服务器支持的Servlet API的最大版本号
9 int getMinorVersion() 返回服务器支持的Servlet API的最大版本号
10 String getMimeType(String file) 返回指定文件的MIME类型
11 URL getResource(String path) 返回指定资源(文件及目录)的URL路径
12 InputStream getResourceAsStream(String path) 返回指定资源的输入流
13 RequestDispatcher getRequestDispatcher(String uripath) 返回指定资源的RequestDispatcher对象
14 Servlet getServlet(String name) 返回指定名的Servlet
15 Enumeration getServlets() 返回所有Servlet的枚举
16 Enumeration getServletNames() 返回所有Servlet名的枚举
17 void log(String msg) 把指定消息写入Servlet的日志文件
18 void log(Exception exception,String msg) 把指定异常的栈轨迹及错误消息写入Servlet的日志文件
19 void log(String msg,Throwable throwable) 把栈轨迹及给出的Throwable异常的说明信息 写入Servlet的日志文件


7.exception对象
exception对象是一个例外对象,当一个页面在运行过程中发生了例外,就产生这个对象。如果一个JSP页面要应用此对象,就必须把isErrorPage设为true,否则无法编译。他实际上是java.lang.Throwable的对象



1 String getMessage() 返回描述异常的消息
2 String toString() 返回关于异常的简短描述消息
3 void printStackTrace() 显示异常及其栈轨迹
4 Throwable FillInStackTrace() 重写异常的执行栈轨迹
5

 
8.pageContext对象
pageContext对象提供了对JSP页面内所有的对象及名字空间的访问,也就是说他可以访问到本页所在的SESSION,也可以取本页面所在的application的某一属性值,他相当于页面中所有功能的集大成者,它的本 类名也叫pageContext。



1 JspWriter getOut() 返回当前客户端响应被使用的JspWriter流(out)
2 HttpSession getSession() 返回当前页中的HttpSession对象(session)
3 Object getPage() 返回当前页的Object对象(page)
4 ServletRequest getRequest() 返回当前页的ServletRequest对象(request)
5 ServletResponse getResponse() 返回当前页的ServletResponse对象(response)
6 Exception getException() 返回当前页的Exception对象(exception)
7 ServletConfig getServletConfig() 返回当前页的ServletConfig对象(config)
8 ServletContext getServletContext() 返回当前页的ServletContext对象(application)
9 void setAttribute(String name,Object attribute) 设置属性及属性值
10 void setAttribute(String name,Object obj,int scope) 在指定范围内设置属性及属性值
11 public Object getAttribute(String name) 取属性的值
12 Object getAttribute(String name,int scope) 在指定范围内取属性的值
13 public Object findAttribute(String name) 寻找一属性,返回起属性值或NULL
14 void removeAttribute(String name) 删除某属性
15 void removeAttribute(String name,int scope) 在指定范围删除某属性
16 int getAttributeScope(String name) 返回某属性的作用范围
17 Enumeration getAttributeNamesInScope(int scope) 返回指定范围内可用的属性名枚举
18 void release() 释放pageContext所占用的资源
19 void forward(String relativeUrlPath) 使当前页面重导到另一页面
20 void include(String relativeUrlPath) 在当前位置包含另一文件
 
 
9.config对象
config对象是在一个Servlet初始化时,JSP引擎向它传递信息用的,此信息包括Servlet初始化时所要用到的参数(通过属性名和属性值构成)以及服务器的有关信息(通过传递一个ServletContext对象)



1 ServletContext getServletContext() 返回含有服务器相关信息的ServletContext对象
2 String getInitParameter(String name) 返回初始化参数的值
3 Enumeration getInitParameterNames() 返回Servlet初始化所需所有参数的枚举

Servlet 详细说明

发表人:xuniji123 | 发表时间: 2007年一月01日, 23:21

有关Java Servlets
JavaTM servlets是一个不受平台约束的Java小程序,它可以被用来通过多种方法扩充一个Web服务器的功能。你可以把Servlet理解成Server上的applets,它被编译成字节码,这样它就可以被动态地载入并用效地扩展主机的处理能力。
Servlet与applets不同的地方是,它不运行在Web浏览器或其他图形化的用户界面上。Servlet通过servlet引擎运行在Web服务器中,以执行请求和响应,请求、响应的典型范例是HTTP协议。
一个客户端程序,可以是一个Web浏览器,或者是非其他的可以连接上Internet的程序,它会访问Web服务器并发出请求。这个请求被运行在Web服务器上的Servlet引擎处理,并返回响应到Servlet。Servlet通过HTTP将这个响应转发到客户端。
在功能上,Servlet与CGI、NSAPI有点类似,但是,与他们不同的是:Servlet具有平台无关性。

Java Servlet概论
Servlet与其他普通的server扩展机制有以下进步:
因为它采用了不同的进程处理模式,所以它比CGI更快。
它使用了许多Web服务器都支持的标准的API。
它继承了Java的所有优势,包括易升级以及平台无关性。
它可以调用Java所提供的大量的API的功能模块。
这份文档说明了Java Servlet API的类和接口的方法。有关更多的信息,请参看下面的API说明。

Servlet的生命周期
一个Java servlet具有一个生命周期,这个生命周期定义了一个Servlet如何被载入并被初始化,如何接收请求并作出对请求的响应,如何被从服务中清除。Servlet的生命周期被javax.servlet.Servlet这个接口所定义。
所有的Java Servlet都会直接地或间接地执行javax.servlet.Servlet接口,这样它才能在一个Servlet引擎中运行。Servlet引擎是Web 服务器按照Java Servlet API定制的扩展。Servlet引擎提供网络服务,能够理解MIME请求,并提供一个运行Servlet的容器。
javax.servlet.Servlet接口定义了在Servlet的生命周期中特定时间以及特定顺序被调用的方法。

Servlet的解析和载入
Servlet引擎解析并载入一个Servlet,这个过程可以发生在引擎启动时,需要一个Servlet去响应请求时,以及在此之间的任何时候。
Servlet引擎利用Java类载入工具载入一个Servlet,Servlet引擎可以从一个本地的文件系统、一个远程的文件系统以及网络载入Servlet。

Servlet的初始化
Servlet引擎载入Servlet后,Servlet引擎必须对Servlet进行初始化,在这一过程中,你可以读取一些固定存储的数据、初始化JDBC的连接以及建立与其他资源的连接。
在初始化过程中,javax.servlet.Servlet接口的init()方法提供了Servlet的初始化信息。这样,Servlet可以对自己进行配置。
init()方法获得了一个Servlet配置对象(ServletConfig)。这个对象在Servlet引擎中执行,并允许Servlet通过它获处相关参数。这个对象使得Servlet能够访问ServletContext对象。

Servlet处理请求
Servlet被初始化之后,它已经可以处理来自客户端的请求,每一个来自客户端的请求都被描述成一个ServletRequest对象,Servlet的响应被描述成一个ServletResponse对象。
当客户端发出请求时,Servlet引擎传递给Servlet一个ServletRequest对象和一个ServletResponse对象,这两个对象作为参数传递到service()方法中。
Servlet也可以执行ServletRequest接口和ServletResponse接口。ServletRequest接口使得Servlet有权使用客户端发出的请求。Servlet可以通过ServletInputStream对象读取请求信息。
ServletResponse接口允许Servlet建立响应头和状态代码。通过执行这个接口,Servlet有权使用ServletOutputStream类来向客户端返回数据。

多线程和映射
在多线程的环境下,Servlet必须能处理许多同时发生的请求。例外的情况是这个Servlet执行了SingleThreadModel接口,如果是那样的话,Servlet只能同时处理一个请求。
Servlet依照Servlet引擎的映射来响应客户端的请求。一个映射对包括一个Servlet实例以及一个Servlet返回数据的URL,例如:HelloServlet with /hello/index.html。
然而,一个映射可能是由一个URL和许多Servlet实例组成,例如:一个分布式的Servlet引擎可能运行在不止一个的服务器中,这样的话,每一个服务器中都可能有一个Servlet实例,以平衡进程的载入。作为一个Servlet的开发者,你不能假定一个Servlet只有一个实例。

Servlet的卸载
Servlet引擎并不必需保证一个Servlet在任何时候或在服务开启的任何时候都被载入。Servlet引擎可以自由的在任何时候使用或清除一个Servlet。因此,我们不能依赖一个类或实例来存储重要的信息。
当Servlet引擎决定卸载一个Servlet时(例如,如果这个引擎被关闭或者需要让资源),这个引擎必须允许Servlet释放正在使用的资源并存储有关资料。为了完成以上工作,引擎会调用Servlet的destroy()方法。
在卸载一个Servlet之前,Servlet引擎必须等待所有的service()方法完成或超时结束(Servlet引擎会对超时作出定义)。当一个Servlet被卸载时,引擎将不能给Servlet发送任何请求。引擎必须释放Servlet并完成无用存储单元的收集

Servlet映射技术
作为一个Servlet引擎的开发者,你必须对于如何映射客户端的请求到Servlet有大量的适应性。这份说明文档不规定映射如何发生。但是,你必须能够自由地运用下面的所有技术:

映射一个Servlet到一个URL
例如,你可以指定一个特殊的Servlet它仅被来自/feedback/index.html的请求调用。

映射一个Servlet到以一个指定的目录名开始的所有URL
例如,你可以映射一个Servlet到/catalog,这样来自/catalog/、 /catalog/garden和/catalog/housewares/index.html的请求都会被映射到这个Servlet。但是来自/catalogtwo 或/catalog.html的请求没被映射。

映射一个Servlet到所有以一个特定的字段结尾的所有URL
例如,你可以映射一个来自于所有以in.thtml结尾的请求到一个特定的Servlet。

映射一个Servlet到一个特殊的URL /servlet/servlet_name。
例如,如果你建立了一个名叫listattributes的Servlet,你可以通过使用/servlet/listattributes来访问这个Servlet。

通过类名调用Servlet
例如,如果Servlet引擎接收了来自/servlet/com.foo.servlet.MailServlet的请求,Servlet引擎会载入这个com.foo.servlet.MailServlet类,建立实例,并通过这个Servlet来处理请求。

Servlet环境
ServletContext接口定义了一个Servlet环境对象,这个对象定义了一个在Servlet引擎上的Servlet的视图。通过使用这个对象,Servlet可以记录事件、得到资源并得到来自Servlet引擎的类(例如RequestDispatcher对象)。一个Servlet只能运行在一个Servlet环境中,但是不同的Servlet可以在Servlet引擎上有不同的视图。
如果Servlet引擎支持虚拟主机,每个虚拟主机有一个Servlet环境。一个Servlet环境不能在虚拟主机之间共享。
Servlet引擎能够允许一个Servlet环境有它自己的活动范围。
例如,一个Servlet环境是属于bank应用的,它将被映射到/bank目录下。在这种情况下,一个对getContext方法的调用会返回/bank的Servlet环境。

HTTP会话
HTTP是一个没有状态的协议。要建立一个有效的Web服务应用,你必须能够识别一个连续的来自远端的客户机的唯一的请求。随着时间的过去,发展了许多会话跟踪的技术,但是使用起来都比较麻烦。
Java Servlet API提供了一个简单的接口,通过这个接口,Servlet引擎可以有效地跟踪用户的会话。

建立Session
因为HTTP是一个请求-响应协议,一个会话在客户机加入之前会被认为是一个新的会话。加入的意思是返回会话跟踪信息到服务器中,指出会话已被建立。在客户端加入之前,我们不能判断下一个客户端请求是目前会话的一部分。
在下面的情况下,Session会被认为是新的Session。
客户端的Session在此之前还不知道
客户端选择不加入Session,例如,如果客户端拒绝接收来自服务器的cookie
作为一个Servlet的开发者,你必须决定你的Web应用是否处理客户机不加入或不能加入Session。服务器会在Web服务器或Servlet规定的时间内维持一个Session对象。当Session终止时,服务器会释放Session对象以及所有绑定在Session上的对象。
绑定对象到Session中
如果有助于你处理应用的数据需求,你也许需要绑定对象到Session中,你可以通过一个唯一的名字绑定任何的对象到Session中,这时,你需要使用HttpSession对象。任何绑定到Session上的对象都可以被处理同一会话的Servlet调用。
有些对象可能需要你知道什么时候会被放置到Session中或从Session中移开。你可以通过使用HttpSessionBindingListener接口获得这些信息。当你的应用存储数据到Session中,或从Session中清除数据,Servlet都会通过HttpSessionBindingListener检杳什么类被绑定或被取消绑定。这个接口的方法会通报被绑定或被取消绑定的对象。

API对象的说明
这一部分包含了对Java Servlet API的全部类和接口的详细说明。这个说明与Javadoc API差不多,但是这份文档提供了更多的信息。
API包含了两个软件包,十二个接口和九个类。
软件包:javax.servlet
所包含的接口:RequestDispatcher;Servlet;ServletConfig;ServletContext;ServletRequest;ServletResponse;SingleThreadModel。
所包含的类:GenericServlet;ServletInputStream;ServletOutputStream;ServletException;UnavailableException。

一、RequestDispatcher接口:
定义:
public interface RequestDispatcher;
定义一个对象,从客户端接收请求,然后将它发给服务器的可用资源(例如Servlet、CGI、HTML文件、JSP文件)。Servlet引擎创建request dispatcher对象,用于封装由一个特定的URL定义的服务器资源。
这个接口是专用于封装Servlet的,但是一个Servlet引擎可以创建request dispatcher对象用于封装任何类型的资源。
request dispatcher对象是由Servlet引擎建立的,而不是由Servlet开发者建立的。
方法
1、forward
public void forward(ServletRequest request, ServletReponse response)
throws ServletException, IOException;
被用来从这个Servlet向其它服务器资源传递请求。当一个Servlet对响应作了初步的处理,并要求其它的对象对此作出响应时,可以使用这个方法。
当request对象被传递到目标对象时,请求的URL路径和其他路径参数会被调整为反映目标对象的目标URL路径。
如果已经通过响应返回了一个ServletOutputStream对象或PrintWriter对象,这个方法将不能使用,否则,这个方法会抛出一个IllegalStateException。
2、include
public void include(ServletRequest request, ServletResponse response)
throws ServletException, IOException
用来包括发送给其他服务器资源的响应的内容。本质上来说,这个方法反映了服务器端的内容。
请求对象传到目标对象后会反映调用请求的请求URL路径和路径信息。这个响应对象只能调用这个Servlet的ServletOutputStream对象和PrintWriter对象。
一个调用include的Servlet不能设置头域,如果这个Servlet调用了必须设置头域的方法(例如cookie),这个方法将不能保证正常使用。作为一个Servlet开发者,你必须妥善地解决那些可能直接存储头域的方法。例如,即使你使用会话跟踪,为了保证session的正常工作,你必须在一个调用include的Servlet之外开始你的session

二、Servlet接口。
定义
public interface Servlet
这个接口定义了一个Servlet:一个在Web服务器上继承了这个功能的Java类。
方法
1、init
public void init(ServletConfig config) throws ServletException;
Servlet引擎会在Servlet实例化之后,置入服务之前精确地调用init方法。在调用service方法之前,init方法必须成功退出。
如果init方法抛出一个ServletException,你不能将这个Servlet置入服务中,如果init方法在超时范围内没完成,我们也可以假定这个Servlet是不具备功能的,也不能置入服务中。
2、service
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException;
Servlet引擎调用这个方法以允许Servlet响应请求。这个方法在Servlet未成功初始化之前无法调用。在Servlet被初始化之前,Servlet引擎能够封锁未决的请求。
在一个Servlet对象被卸载后,直到一个新的Servelt被初始化,Servlet引擎不能调用这个方法
3、destroy
public void destroy();
当一个Servlet被从服务中去除时,Servlet引擎调用这个方法。在这个对象的service方法所有线程未全部退出或者没被引擎认为发生超时操作时,destroy方法不能被调用。
4、getServletConfig
public ServletConfig getServletConfig();
返回一个ServletConfig对象,作为一个Servlet的开发者,你应该通过init方法存储ServletConfig对象以便这个方法能返回这个对象。为了你的便利,GenericServlet在执行这个接口时,已经这样做了。
5、getServletInfo
public String getServletInfo();
允许Servlet向主机的Servlet运行者提供有关它本身的信息。返回的字符串应该是纯文本格式而不应有任何标志(例如HTML,XML等)。

三、ServletConfig接口
定义
public interface ServletConfig
这个接口定义了一个对象,通过这个对象,Servlet引擎配置一个Servlet并且允许Servlet获得一个有关它的ServletContext接口的说明。每一个ServletConfig对象对应着一个唯一的Servlet。
方法
1、getInitParameter
public String getInitParameter(String name);
这个方法返回一个包含Servlet指定的初始化参数的String。如果这个参数不存在,返加空值。
2、getInitParameterNames
public Enumeration getInitParameterNames();
这个方法返回一个列表String对象,该对象包括Servlet的所有初始化参数名。如果Servlet没有初始化参数,getInitParameterNames返回一个空的列表。
3、getServletContext
public ServletContext getServletContext();
返回这个Servlet的ServletContext对象。

四、ServletContext接口
定义
public interface ServletContext
定义了一个Servlet的环境对象,通过这个对象,Servlet引擎向Servlet提供环境信息。
一个Servlet的环境对象必须至少与它所驻留的主机是一一对应的。在一个处理多个虚拟主机的Servlet引擎中(例如,使用了HTTP1.1的主机头域),每一个虚拟主机必须被视为一个单独的环境。此外,Servlet引擎还可以创建对应于一组Servlet的环境对象。
方法
1、getAttribute
public Object getAttribute(String name);
返回Servlet环境对象中指定的属性对象。如果该属性对象不存在,返回空值。这个方法允许访问有关这个Servlet引擎的在该接口的其他方法中尚未提供的附加信息。
2、getAttributeNames
public Enumeration getAttributeNames();
返回一个Servlet环境对象中可用的属性名的列表。
3、getContext
public ServletContext getContext(String uripath);
返回一个Servlet环境对象,这个对象包括了特定URI路径的Servlets和资源,如果该路径不存在,则返回一个空值。URI路径格式是/dir/dir/filename.ext。
为了安全,如果通过这个方法访问一个受限制的Servlet的环境对象,会返回一个空值。
4、getMajorVersion
public int getMajorVersion();
返回Servlet引擎支持的Servlet API的主版本号。例如对于2.1版,这个方法会返回一个整数2。
5、getMinorVersion
public int getMinorVersion();
返回Servlet引擎支持的Servlet API的次版本号。例如对于2.1版,这个方法会返回一个整数2。
6、getMimeType
public String getMimeType(String file);
返回指定文件的MIME类型,如果这种MIME类型未知,则返回一个空值。MIME类型是由Servlet引擎的配置决定的。
7、getRealPath
public String getRealPath(String path);
一个符合URL路径格式的指定的虚拟路径的格式是:/dir/dir/filename.ext。用这个方法,可以返回与一个符合该格式的虚拟路径相对应的真实路径的String。这个真实路径的格式应该适合于运行这个Servlet引擎的计算机(包括其相应的路径解析器)。
不管是什么原因,如果这一从虚拟路径转换成实际路径的过程不能执行,该方法将会返回一个空值。
8、getResource
public URL getResource(String uripath);
返回一个URL对象,该对象反映位于给定的URL地址(格式:/dir/dir/filename.ext)的Servlet环境对象已知的资源。无论URLStreamHandlers对于访问给定的环境是不是必须的,Servlet引擎都必须执行。如果给定的路径的Servlet环境没有已知的资源,该方法会返回一个空值。
这个方法和java.lang.Class的getResource方法不完全相同。java.lang.Class的getResource方法通过装载类来寻找资源。而这个方法允许服务器产生环境变量给任何资源的任何Servlet,而不必依赖于装载类、特定区域等等。
9、getResourceAsStream
public InputStream getResourceAsStream(String uripath);
返回一个InputStream对象,该对象引用指定的URL的Servlet环境对象的内容。如果没找到Servlet环境变量,就会返回空值,URL路径应该具有这种格式:/dir/dir/filename.ext。
这个方法是一个通过getResource方法获得URL对象的方便的途径。请注意,当你使用这个方法时,meta-information(例如内容长度、内容类型)会丢失。
10、getRequestDispatcher
public RequestDispatcher getRequestDispatcher(String uripath);
如果这个指定的路径下能够找到活动的资源(例如一个Servlet,JSP页面,CGI等等)就返回一个特定URL的RequestDispatcher对象,否则,就返回一个空值,Servlet引擎负责用一个request dispatcher对象封装目标路径。这个request dispatcher对象可以用来完全请求的传送。
11、getServerInfo
public String getServerInfo();
返回一个String对象,该对象至少包括Servlet引擎的名字和版本号。
12、log
public void log(String msg);
public void log(String msg, Throwable t);
public void log(Exception exception, String msg); // 这种用法将被取消
写指定的信息到一个Servlet环境对象的log文件中。被写入的log文件由Servlet引擎指定,但是通常这是一个事件log。当这个方法被一个异常调用时,log中将包括堆栈跟踪。
13、setAttribute
public void setAttribute(String name, Object o);
给予Servlet环境对象中你所指定的对象一个名称。
14、removeAttribute
public void removeAttribute(String name);
从指定的Servlet环境对象中删除一个属性。
注:以下几个方法将被取消
15、getServlet
public Servlet getServlet(String name) throws ServletException;
最初用来返回一个指定名称的Servlet,如果没找到就返回一个空值。如果这个Servlet能够返回,这就意味着它已经被初始化,而且已经可以接受service请求。这是一个危险的方法。当调用这个方法时,可能并不知道Servlet的状态,这就可能导致有关服务器状态的问题。而允许一个Servlet访问其他Servlet的这个方法也同样的危险。
现在这个方法返回一个空值,为了保持和以前版本的兼容性,现在这个方法还没有被取消。在以后的API版本中,该方法将被取消。
16、getServletNames
public Enumeration getServletNames();
最初用来返回一个String对象的列表,该列表表示了在这个Servlet环境下所有已知的Servlet对象名。这个列表总是包含这个Servlet自身。
基于与上一个方法同样的理由,这也是一个危险的方法。
现在这个方法返回一个空的列表。为了保持和以前版本的兼容性,现在这个方法还没有被取消。在以后的API版本中,该方法将被取消。
17、getServlets
public Enumeration getServlets();
最初用来返回在这个Servelet环境下所有已知的Servlet对象的列表。这个列表总是包含这个Servlet自身。
基于与getServlet方法同样的理由,这也是一个危险的方法。
现在这个方法返回一个空的列表。为了保持和以前版本的兼容性,现在这个方法还没有被取消。在以后的API版本中,该方法将被取消。

五、ServletRequest接口
定义
public interface ServletRequest
定义一个Servlet引擎产生的对象,通过这个对象,Servlet可以获得客户端请求的数据。这个对象通过读取请求体的数据提供包括参数的名称、值和属性以及输入流的所有数据。
方法
1、getAttribute
public Object getAttribute(String name);
返回请求中指定属性的值,如果这个属性不存在,就返回一个空值。这个方法允许访问一些不提供给这个接口中其他方法的请求信息以及其他Servlet放置在这个请求对象内的数据。
2、getAttributeNames
public Enumeration getAttributeNames();
返回包含在这个请求中的所有属性名的列表。
3、getCharacterEncoding
public String getCharacterEncoding();
返回请求中输入内容的字符编码类型,如果没有定义字符编码类型就返回空值。
4、getContentLength
public int getContentLength();
请求内容的长度,如果长度未知就返回-1。
5、getContentType
public String getContentType();
返回请求数据体的MIME类型,如果类型未知返回空值。
6、getInputStream
public ServletInputStream getInputStream() throws IOException;
返回一个输入流用来从请求体读取二进制数据。如果在此之前已经通过getReader方法获得了要读取的结果,这个方法会抛出一个IllegalStateException。
7、getParameter
public String getParameter(String name);
以一个String返回指定的参数的值,如果这个参数不存在返回空值。例如,在一个HTTP Servlet中,这个方法会返回一个指定的查询语句产生的参数的值或一个被提交的表单中的参数值。如果一个参数名对应着几个参数值,这个方法只能返回通过getParameterValues方法返回的数组中的第一个值。因此,如果这个参数有(或者可能有)多个值,你只能使用getParameterValues方法。
8、getParameterNames
public Enumeration getParameterNames();
返回所有参数名的String对象列表,如果没有输入参数,该方法返回一个空值。
9、getParameterValues
public String[] getParameterValues(String name);
通过一个String对象的数组返回指定参数的值,如果这个参数不存在,该方法返回一个空值。
10、getProtocol
public String getProtocol();
返回这个请求所用的协议,其形式是协议/主版本号.次版本号。例如对于一个HTTP1.0的请求,该方法返回HTTP/1.0。
11、getReader
public BufferedReader getReader() throws IOException;
这个方法返回一个buffered reader用来读取请求体的实体,其编码方式依照请求数据的编码方式。如果这个请求的输入流已经被getInputStream调用获得,这个方法会抛出一个IllegalStateException。
12、getRemoteAddr
public String getRemoteAddr();
返回发送请求者的IP地址。
13、getRemoteHost
public String getRemoteHost();
返回发送请求者的主机名称。如果引擎不能或者选择不解析主机名(为了改善性能),这个方法会直接返回IP地址。
14、getScheme
public String getScheme();
返回请求所使用的URL的模式。例如,对于一个HTTP请求,这个模式就是http。
15、getServerName
public String getServerName();
返回接收请求的服务器的主机名。
16、getServerPort
public int getServerPort();
返回接收请求的端口号。
17、setAttribute
public void setAttribute(String name, Object object);
这个方法在请求中添加一个属性,这个属性可以被其他可以访问这个请求对象的对象(例如一个嵌套的Servlet)使用。
注:以下方法将被取消
getRealPath
public String getRealPath(String path);
返回与虚拟路径相对应的真实路径,如果因为某种原因,这一过程不能进行,该方法将返回一个空值。
这个方法和ServletContext接口中的getRealPath方法重复。在2.1版中,ServletContext接口将阐明一个Servlet所能用的所有的路径的映射。该方法执行的结果将会与ServletContext中getRealPath方法的结果完全一样。

六、ServletResponse接口
定义
public interface ServletResponse
定义一个Servlet引擎产生的对象,通过这个对象,Servlet对客户端的请求作出响应。这个响应应该是一个MIME实体,可能是一个HTML页、图象数据或其他MIME的格式。
方法
1、getCharacterEncoding
public String getCharacterEncoding();
返回MIME实体的字符编码。这个字符编码可以是指定的类型,也可以是与请求头域所反映的客户端所能接受的字符编码最匹配的类型。在HTTP协议中,这个信息被通过Accept-Charset传送到Servlet引擎。
有关字符编码和MIME的更多信息请参看RFC 2047。
2、getOutputStream
public ServletOutputStream getOutputStream() throws IOException;
返回一个记录二进制的响应数据的输出流。
如果这个响应对象已经调用getWriter,将会抛出IllegalStateException。
3、getWriter
public PrintWriter getWriter throws IOException;
这个方法返回一个PringWriter对象用来记录格式化的响应实体。如果要反映使用的字符编码,必须修改响应的MIME类型。在调用这个方法之前,必须设定响应的content类型。
如果没有提供这样的编码类型,会抛出一个UnsupportedEncodingException,如果这个响应对象已调用getOutputStream,会抛出一个getOutputStream。
4、setContentLength
public void setContentLength(int length);
设置响应的内容的长度,这个方法会覆盖以前对内容长度的设定。
为了保证成功地设定响应头的内容长度,在响应被提交到输出流之前必须调用这个方法。
5、setContentType
public void setContentType(String type);
这个方法用来设定响应的content类型。这个类型以后可能会在另外的一些情况下被隐式地修改,这里所说的另外的情况可能当服务器发现有必要的情况下对MIME的字符设置。
为了保证成功地设定响应头的content类型,在响应被提交到输出流之前必须调用这个方法。

七、SingleThreadModel接口
定义
public interface SingleThreadModel;
这是一个空接口,它指定了系统如何处理对同一个Servlet的调用。如果一个Servlet被这个接口指定,那么在这个Servlet中的service方法中将不会有两个线程被同时执行。
Servlet可以通过维持一个各自独立的Servlet实例池,或者通过只让Servlet的service中只有一个线程的方法来实现这个保证。

八、GenericServlet类
public abstract class GenericServlet implements Servlet,
ServletConfig, Serializable;
这个类的存在使得编写Servlet更加方便。它提供了一个简单的方案,这个方案用来执行有关Servlet生命周期的方法以及在初始化时对ServletConfig对象和ServletContext对象进行说明。
方法
1、destroy
public void destroy();
在这里destroy方法不做任何其他的工作。
2、getInitParameter
public String getInitParameter(String name);
这是一个简便的途径,它将会调用ServletConfig对象的同名的方法。
3、getInitParameterNames
public Enumeration getInitParameterNames();
这是一个简便的途径,它将会调用ServletConfig对象的同名的方法。
4、getServletConfig
public ServletConfig getServletConfig();
返回一个通过这个类的init方法产生的ServletConfig对象的说明。
5、getServletContext
public ServletContext getServletContext();
这是一个简便的途径,它将会调用ServletConfig对象的同名的方法。
6、getServletInfo
public String getServletInfo();
返回一个反映Servlet版本的String。
7、init
public void init() throws ServletException;
public void init(ServletConfig config) throws ServletException;
init(ServletConfig config)方法是一个对这个Servlet的生命周期进行初始化的简便的途径。
init()方法是用来让你对GenericServlet类进行扩充的,使用这个方法时,你不需要存储config对象,也不需要调用super.init(config)。
init(ServletConfig config)方法会存储config对象然后调用init()。如果你重载了这个方法,你必须调用super.init(config),这样GenericServlet类的其他方法才能正常工作。
8、log
public void log(String msg);
public void log(String msg, Throwable cause);
通过Servlet content对象将Servlet的类名和给定的信息写入log文件中。
9、service
public abstract void service(ServletRequest request, ServletResponse
response) throws ServletException, IOException;
这是一个抽象的方法,当你扩展这个类时,为了执行网络请求,你必须执行它。

九、ServletInputStream类
定义
public abstract class ServletInputStream extends InputStream
这个类定义了一个用来读取客户端的请求信息的输入流。这是一个Servlet引擎提供的抽象类。一个Servlet通过使用ServletRequest接口获得了对一个ServletInputStream对象的说明。
这个类的子类必须提供一个从InputStream接口读取有关信息的方法。
方法
1、readLine
public int readLine(byte[] b, int off, int len) throws IOException;
从输入流的指定的偏移量开始将指定长度的字节读入到指定的数组中。如果该行所有请求的内容都已被读取,这个读取的过程将结束。如果是遇到了新的一行,新的一行的首个字符也将被读入到数组中。

十、ServletOutputStream类
定义
public abstract class ServletOutputStream extends OutputStream
这是一个由Servlet引擎使用的抽象类。Servlet通过使用ServletResponse接口的使用获得了对一个这种类型的对象的说明。利用这个输出流可以将数据返回到客户端。
这个类的子类必须提供一个向OutputStream接口写入有关信息的方法。
在这个接口中,当一个刷新或关闭的方法被调用时。所有数据缓冲区的信息将会被发送到客户端,也就是说响应被提交了。请注意,关闭这种类型的对象时不一定要关闭隐含的socket流。
方法
1、print
public void print(String s) throws IOException;
public void print(boolean b) throws IOException;
public void print(char c) throws IOException;
public void print(int i) throws IOException;
public void print(long l) throws IOException;
public void print(float f) throws IOException;
public void print(double d) throws IOException;
输出变量到输出流中
2、println
public void println() throws IOException;
public void println(String s) throws IOException;
public void println(boolean b) throws IOException;
public void println(char c) throws IOException;
public void println(int i) throws IOException;
public void println(long l) throws IOException;
public void println(float f) throws IOException;
public void println(double d) throws IOException;
输出变量到输出流中,并增加一个回车换行符

十一、ServletException类
定义
public class ServletException extends Exception
当Servlet遇到问题时抛出的一个异常。
构造函数
public ServletException();
public ServletException(String message);
public ServletException(String message, Throwable cause);
public ServletException(Throwable cause);
构造一个新的ServletException,如果这个构造函数包括一个Throwable参数,这个Throwable对象将被作为可能抛出这个异常的原因。
方法
1、getRootCause
public Throwable getRootCause();
如果配置了抛出这个异常的原因,这个方法将返回这个原因,否则返回一个空值。

十二、UnavailableException类
定义
public class UnavailableException extends ServletException
不论一个Servlet是永久地还是临时地无效,都会抛出这个异常。Servlet会记录这个异常以及Servlet引擎所要采取的相应措施。
临时的无效是指Servlet在某一时间由于一个临时的问题而不能处理请求。例如,在另一个不同的应用层的服务(可能是数据库)无法使用。这个问题可能会自行纠正或者需要采取其他的纠正措施。
永久的无效是指除非管理员采取措施,这个Servlet将不能处理客户端的请求。例如,这个Servlet配置信息丢失或Servlet的状态被破坏。
Servlet引擎可以安全地处理包括永久无效在内的这两种异常,但是对临时无效的正常处理可以使得Servlet引擎更健壮。特别的,这时对Servlet的请求只是被阻止(或者是被延期)一段时间,这显然要比在service自己重新启动前完全拒绝请求更为科学。
构造函数
public UnavailableException(Servlet servlet, String message);
public UnavailableException(int seconds, Servlet servlet,
String message);
构造一个包含指定的描述信息的新的异常。如果这个构造函数有一个关于秒数的参数,这将给出Servlet发生临时无效后,能够重新处理请求的估计时间。如果不包含这个参数,这意味着这个Servlet永久无效。
方法
1、getServlet
public Servlet getServlet();
返回报告无效的Servlet。这被Servlet引擎用来识别受到影响的Servlet。
2、getUnavailableSeconds
public int getUnavailableSeconds();
返回Servlet预期的无效时间,如果这个Servlet是永久无效,返回-1。
3、isPermanent
public boolean isPermanent();
如果这个Servlet永久无效,返回布尔值true,指示必须采取一些管理行动以使得这个Servlet可用。

 查看全文

2006年Java开发技术回顾与展望

发表人:xuniji123 | 发表时间: 2007年一月01日, 23:15

又是一年终岁尾,伴随着技术行业的烟雨风云,我们即将迎来2007年,那么在过去的一年中,我们Java技术开发行业发生了什么呢?

  Java开源终于在人们的千呼万唤中开源,Hibernate发布3.0版本似乎要在2007年大展拳脚一番,Spring发布了2.0在2006年火热过后,Spring也开始被人讨论,Struts方面有了Webwork的加盟,期待新版本继续扬威,EJB在05年就早早结案年初发布了3.0但是新版本似乎没有改变被动挨打的命运,Ajax在06年没有杰作,相对它的弱点和缺陷被披露无疑,JSP没有人在愿意提及它,好像被放在了一个被人遗忘的角落里,JSF刚刚纳入Java规范以来,Sun对JSF寄予了厚望,2006年Java界成绩频丰,2007才是彼此肉博血战的开始。

Struts、Hibernate、EJB、Spring、Ajax等继续成为我们关注的焦点,那么我们接着就从2006年Java这个热血江湖中,来看看都蕴涵着多少风云故事。

  关键字1:Strust、JSF、Webwork-----MVC框架

  Java技术2006年在表示层方面可谓创新不少,,Struts在2006年没有继续问世时候的辉煌,随着Web框架的兴起,Struts的优势逐步在退却,烦琐的配置让它背上了重型框架的枷锁,但是Struts并没有因为繁重而离开人们的视野,Struts庞大的开发队伍,是它赖以生存的强大生命力,今年Ted(Apache软件基金会的成员)已经与Patrick(WebWork 2的高级开发者)和Jason(Webwork核心架构师)探讨Struts与WebWork合并的构想,在未来Struts 2中我们将会看到一个两者完美结合的框架结构这是Struts2的初衷,Struts2构想是我们2006年对表示层方面产生更多的想象,相对于Struts的不断完善与更新,JSP从2.0之后就开始止步,在Struts这些开源框架面前稍显底气和信心不足,开源框架慢慢在吞食着JSP的领地,

  Sun公司也不会让自已亲手打下来的江山就此灰飞烟灭,全力打造JSF收复失地, JSF的优点在于丰富可定制的UI组件,良好的事件响应机制,表达性语言,表单数据自动转换和验证等,如果在配有良好的开发工具支持的话,也许这将成为众多开源表示层框架的末日。开发人员都清楚开源框架带来的无限惊喜,提高了开发效率,降低了复杂程度,但面对满天的框架时,恐怕心中只有暗暗叫苦的份了。大量知名的不知名的框架,布满了Java Web世界,也渐渐的迷失了众人的双眼,誓必要有一种集众家所长的框架出现,来改变技术频多,但都营养不良的框架技术,今年Sun公司把JSF纳入JavaEE规范,JSF终于从幕后走向前台。

  关键字2: Spring、EJB -----轻重级企业开发框架

  业务组件层前期基本是EJB的天下,但是EJB功能实在太强大,它考虑了世界顶级大型系统需求,因此免不了显得很复杂,当初,基本上所有的大型企业高端都是选用J2EE,选用J2EE实际是选用EJB。EJB强调的高可伸缩性为大型企业日益发展提供最大的发展空间,不再因为企业快速发展导致整个企业系统结构都要发生根本变化,这是使用EJB的现实优势。然而,这个曾经风靡一时的技术, 现在确成了Java领域里中最受争议的技术,它的繁琐复杂把很多人拒之门外,它深奥的理论让一些人如痴如醉大唱赞歌,可是它的博学几人又能读懂?2005年底Ejb草草结案,在2006年推出EJB3.0,EJB3.0的宗旨是从某种程度上减轻了开发人员进行底层开发的工作量,取消或最小化了很多(以前这些是必须实现)回调方法的实现,并且降低了实体Bean及O/R映射模型的复杂性。

  EJB3.0虽然在简化开发上做足了功课,但是已错过最好的发展良机,EJB未来的尴尬处境还不会在短时间内改变。

  与重量级相比的是轻量级,业务组件层轻量级解决方案有Spring/HiveMidn等,轻量一词曾经因为EJB的出现而变得时髦,给人造成的感觉是:EJB花了大力气打造的那些功能,使用轻量级解决方案可以轻而易举完成,虽然这可能是一种错误的观点,但是,Spring的推出着实吸引了不少人的眼光.

  面对EJB3.0的挑战,Spring也不敢示弱,在今年10月份发布2.0版本,来抵制Ejb的围攻,新版本在原基础上强调了三个理念:简洁、强大、健壮。较之前版本做了以下增强:

  1、IOC的增强,可以自定义Beans的应用范围

  2、XML增强,支持namespace

  3、AOP的增强,采用了AspectJ的优点更加高效地识别程序中需要应用的切点

  4、JMS的增强,优化JMS消息的conusme以及本地事务处理

  5、支持多种web开发语言,ruby,groovy以及beanshell

  6、MVC的增强,增强了Form表单校验功能

  7、增加了对门户的支持

  8、引入了Java5的metadata功能间接增强了对OR工具的增强

  这些新功能带着浓浓的火药味,坚决要把EJB逐出这个阵营,凡事要从两个方面来看,有一得就有一失,Spring虽然在功能继续加强攻势,但是繁烦和复杂的配置也伴随着它一起来到人们面前,Spring切记EJB的教训,不要步EJB的后尘。

  关键字3:Hibernate、JDO-----数据持久层框架

  如果说在Web世界的表现层和业务逻辑层的竞争还略显温和的话,那么在数据持久层的竞争可谓军阀割据、血流成河。

  2006年我们不得不提的一项技术就是Hibernate框架,带着对数据库操作灵活易用的优点在对象持久层框架中迅速的占领一席之地,同时Hibernate剑峰指向EJB的实体 Bean。由于EJB的持久化技术一直是EJB致命的硬伤,成为EJB挥之不去的阴影,并最终促成了Hibernate的辉煌。

  在业务层方面Spring一支独大,似乎Spring并不满足目前现状,发布的2.0版本增强了对持久化层方面的设计,Spring的突然搅局,不得不让Hibernate绑紧了神经,Spring新版本发布不到一周Hibernate就匆匆推出3.2版本,来回应Spring和Ejb,Spring想在持久层方面有所建树,Ejb想用新版本抢占自已失地,但是Hibernate的老大地位依然无人憾动。

  前不久我在网上看到一篇文章为Hibernate列举了五大罪证:

  一、Hibernate可以设计很多解决方案,究竟哪个更适合我们无法判断?光是主键生成,就有七八种方案供你选择,你为难不为难?

  二、集合属性可以用Set,也可以用List,还可以用Bag,到底哪个效率高,你为难不为难?

  三、查询可以用Iterator,可以用List,哪个好,有什么区别?你为难不为难?

  四、复合主键你可以直接在hbm里面配置,也可以自定义CustomerType,哪种比较好些?你为难不为难?

  五、对于一个表,你可以选择单一映射一个对象,也可以映射成父子对象,还可以映射成两个1:1的对象,在什么情况下用哪种方案比较好,你为难不为难?”

  Hibernate掳获太多人的心,这五大罪证,不会影响Hibernate前进的脚步,也不会阻止学习Hibernate的热情,连软件富豪微软也不得不对其敬畏三分,NHibernate杀入.NET开发领域,足以证明Hibernate的未来不容质疑,2007年还将继续走红。

  JDO可以算是Hibernate时代的一个”悲情人物”,JDO和Hibernate的O/R映射类似,所不同的是,JDO使用了不同类型的查询API,也就是JDKQL,而不是Hibernate的HQL。JDO可以通过被管制的持久化对象很灵活地感知每个字段值的变化。单从JDO本身来说,这种技术是很好的,但一种技术的兴衰不仅仅取决于技术本身,而更大程度上取决于是否有更多的厂商支持这种技术。由于JDO最初是由Sun提出来的,Sun本来打算使JDO成为数据持久化的规范,但由于JDO没有得到大多数厂商的支持,因此,JDO技术虽然现在有一定的应用,但它并不是标准的Java规范,JDO在2006年没有太大动作来看,不排除将会从这个市场上出局的命运。

  2007年我们有哪些技术值得期待呢?

  Java开源:对业界和开发人员以后产生哪些影响,就目前还没显现,在2007年这些影响将会体现出来。

  2007年的重头戏将是JSF,由于Sun对JSF寄予厚望,因此,近来关于JSF的争论也开始多了起来,各大厂商也开对JSF投入更多的关注度,Orcale,IBM,和国内的金蝶等软件巨头已经把目标锁定在JSF身上,看来2007年称为JSF年不是美丽的慌言。而AJAX虽然可以实现丰富的Web前端界面,但由于编写AJAX程序的工作量非常大,因此,单纯的AJAX应用也许不会大面积铺开,但自从微软推出Atlas(一种包装AJAX技术的可视化组件)后,AJAX好象又开始升温了,也许在未来,JSF和Atlas会上演一场龙争虎斗的好戏。

  Struts将重新回到焦点的位置了。在即将推出的Struts2.0中增加了很多的新功能,而且Struts又和Webwork进行结盟,Webwork加入Struts会展现一个什么的框架结构,我们还不得而知,也许它们的结合会再次带动Struts社区的狂热。

  2006年说最烂的一个词就是SOA了,SOA是一个框架,还是一种思想,我们一直没有看到它庐山真面目,到底SOA是什么,大家都在说业界都在关注,IBM、BEA、ORCALE连Sun公司的Netbean也发布自已的SOA解决方案,宣称产品支持SOA,这么热的一个名词在2007会掀起什么样的波澜,在Java界会对谁发起冲击我们还要在2007年揭晓。

  在持久化层方面,在2007年在这一层当之无愧的焦点当数Hibernate和EJB3.0了,从EJB3.0的规范中可以看出,EJB3.0的实体Bean采用了和Hibernate类似的模式,在EJB3.0中也可以选择使用传统的模式和Hibernate模式。这就意味着EJB3.0和Hibernate有可能走向融合。最终在数据持久层中统一采用类似于Hibnerate模式的轻量级框架形式。

  这是一种想法,也是我们所有开发人员一种期待。

  在业务层方面,2007不会有太多闪光的地方,Spring还将稳定发展下去,EJB不会搅乱现有的固定格局, Spring在10月份发布新版本足以稳定07年的战略地位。

  在这些层面之外,还有很多诱人的非Java技术会吸引大量的眼球。在2005年有人就预言Ruby将消失灭迹,但是这种现象,没有在2006年出现,反而越活越精神,年初发布Rails1.1版本,年底发布推出rails1.2RC版本,Ruby的热头不容小看,有人把它比做新兵挑战老将的神秘武器,敏捷的Web开发让很多的框架暗然失色,脚本语言在2007年还是充满想象的。

  2006年是Java界备受关注的一年,也成绩频丰的一年,Hibernate继续领跑,Spring动力不足,Struts期待新版改变现状,JSP已青春不在,JSF被寄予厚望,2007年谁能独领风骚?我们在预测,业界也在观望,这些未知的答案让我们在2006年细细的品味,新的一年也许会有新惊喜。


论J2EE程序员的武功修为

发表人:xuniji123 | 发表时间: 2006年十二月22日, 20:29

作者:EasyJF开源团队(www.easyjf.com) 大峡

经常会跟一些朋友讨论怎么样才能学好Java,学到什么程度才算撑握了Java的问题。其中有一个J2EE程序员层次及武功修为的问题,有点意思。这里就把讨论的内容大致整理一下发出来,大家继续讨论。

  纵观国内的软件行业,靠Java吃饭的程序员还真不是少,而且Java程序员是有很大优越感的,毕竟对于很多用b/s搞开发的业内朋友来说,Java技术意味着难度大、门槛高,因此相对来说Java程序员比其它的程序员(如php、.net)收入高就理所当然。然而J2EE所涉及到的范畴是很广的,不能一个Java程序员就概括了事,而应该具有层次及水平之分,很多时候经常需要进行分类或评级,有时他评、有时自评。

  谈到国内J2EE领域的程序员层次水平,当前流行的称谓及评级不外乎就下面几种:

  第一种是精通掌握记事本、Dreamweaver等工具来写JSP+JavaBean数据库应用的是J2EE程序员;
  第二种是用JBuilder、Eclipse等专用Java开发工具写着一堆一堆过程式Java Bean,而且还能精通Struts+Spring+Hibernate等应用框架的高级J2EE程序员;
  第三种是用Together建模,然后生成一堆Java接口或代码,开口闭口都是设计模式的资深Java程序同及高级系统分析、构架师;
  最后还有一种是整天在BlogJava或JavaEye上谈经论道的大师们,这些大师技术水平难以触摸,武功门派也各具特色,不好归类,有时不好称为程序员(因为有的时候他们甚至不写或者写不出程序),但又做着与J2EE程序员密切相关的事情,我们暂且就归为“牛牛”或“大师”。

  称谓毕竟只是称谓,带有点主观或者功利色彩,有时很难鉴定一个人应该属于什么,因此,我们再从纯技术的角度,也即武功修为的角度,作了一个简单的分析及归类,把2EE领域程序员大致分成以下几个层次,可以作为大家自评的一个参考标准:

  第一个层次:精通掌握Java语法、能调试基本的程序错误,精通掌握JSP+Java Bean写一些N年前ASP、PHP翻版的Java Web应用程序(如论坛、网站新闻发布系统、OA、网上商城等),精通JDBC使用、精通SQL语句、精通XML等。

  第二个层次:掌握设计模式原理及应用,掌握基于OO的分析及设计方法,并能精通熟练使用几种Java专业设计及开发工具,精通掌握流行的J2EE框架如Hibernate、EJB、Webwork、Spring的原理及应用,精通J2EE中一两个组成部分(如Servlet、EJB等)的工作原理及细节。

  第三个层次:少林的高僧有两种,禅僧及武僧。J2EE程序员的第三个层次也同样有禅、武两个分支,这里我们重点分析一下:

  第一个分支属于走的禅僧线路。在练完第二个层次中的各种武功基础上,结合实际项目中的千奇百怪的用户需求,游刃有余的选择适合的技术方案为客户解决问题,并形成自己的一套解决方案。达到这一个层次的J2EE程序员已经不在乎使用任何工具、任何框架了,而是根据不同的对手,使用不同的武器或招式来应对。好比小李飞刀一样,只有达到了“手中无刀、心中有刀”的境界,才能达到“出手一刀,例不虚发”的效果。这一层次的武功属于一个熟练度问题,刀练得多了、遇到的对手多了,再加上前面的武功修为,就算做不到例不虚发,也可达到十发九中。

  第二个分支属于走的武僧线路,在撑握熟悉第一二个层次中涉及到的内容后,进一步专研并撑握J2EE底层开发,J2EE规范制订、规范实现、Java虚拟机的工作原理、各种常见的J2EE服务器内核工作机制、内存管理、进程机制、源代码等。因为涉及的很多东西都比较抽象,代码也很多,练这一层的武功需要有很好的资质及耐性、并具还得有一定的环境及条件。好比神雕大侠杨过拿起“玄铁剑”,并练成“暗然销魂掌”的成长过程,需要前面的武功修为作基础,更需那只威力神武神雕的帮助指点及他处处为民、惩奸除恶的侠之心态。
  
  胡侃了这么多,现在来根据自己情况测算一下自己的份量,结果如下:

  第一层 练到8成;
  第二层 练到5成;
  第三层 准备走禅僧线路,当前算是练到1成;
  
  唉,后面的武功提升越来越难,真不知道要到何年何月才能达到10成啊。你的武功练到哪一个层次了,不防亮出来大家切磋切磋。嘿嘿,要是有一天,咱们中国的Java程序员人手一把“玄铁剑”、人人会使“暗然销魂掌”,那还了得!汗...,写着写着居然做起白日梦了,不好意思,就此打住。
  
  手中鸡蛋先别扔,还要打个广告:本人刚开始涉足Java开源,目前在EasyJF开源团队中负责EasyJWeb(官网www.easyjf.com)项目,欢迎大家前来指导。

CSDN声明:CSDN登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述


AJAX和Web开发新技术:Dynamic Faces

发表人:xuniji123 | 发表时间: 2006年十二月20日, 19:33

Project Dynamic Faces是数个扩展JavaServer Faces技术的的项目之一。Project Dynamic Faces是一个创新型的项目,提供了向基于JavaServer Faces技术的应用软件增添Ajax功能的方法。它使我们能够让应用软件已经在使用的任何JavaServer Faces组件支持Ajax功能。我们无需对组件进行修改就能够使它们支持Ajax,我们也无需对应用软件进行任何修改就可以使它具有Ajax的魔力。

  要使应用软件具有Ajax魔力,我们必须首先确定应用中希望Ajax功能更新的网页部分。象基于JavaServer Faces技术的开发人员了解的那样,JavaServer Faces网页是由组件树表示的。利用Dynamic Faces,我们能够确定组件树中的哪个组件会受益于异步更新。就象使用Ajax更新代表网页的HTML DOM树的一部分那样,我们使用Dynamic Faces更新代表JavaServer Faces网页的组件树的一部分。因此,Dynamic Faces机制对于Ajax和JavaServer Faces开发人员而言是熟悉的。

  更重要的是,Dynamic Faces使用JavaServer Faces组件模式,使我们能够以一种更有效的方式利用Ajax功能。由于组件模式的协作特性,一些网页组件上的JavaScript事件能够触发该网页上任何数量的其它组件的异步更新。Dynamic Faces使得这些异步更新只是向服务器发送的一次Ajax请求的结果,而不是导致每次异步更新的Ajax请求的结果。

  Dynamic Faces还利用JavaServer Faces组件模式有效地管理客户机端和服务器端的状态。当Dynamic Faces更新客户机端上的组件状态时,它更新的只是已经改变的组件而不是整个树的状态。最好的一点是Dynamic Faces在后台完成所有这些操作,而且是以一种与JavaServer Faces技术的生命周期完全一致的方式完成的。

  除了简化向应用软件增添Ajax功能外,Dynamic Faces还向我们提供了增添Ajax功能的方法的灵活性。这篇文章将讨论利用Dynamic Faces使应用软件更具交互性和活力的三种方法:

  ·利用Dynamic Faces提供的定制ajaxZone标签确定组件树中需要被Ajax化的部分。

  ·利用Dynamic Faces提供的JavaScript库向单个组件增添Ajax功能。

  ·在一个网页中增添支持Ajax的组件,例如jMaki widget。

  在学习这些技术前,我们先来看看应用软件如何才能使用Dynamic Faces技术。

  开发利用Dynamic Faces的应用软件

  通过向一个标准的JavaServer Faces 1.2实现中增添Ajax功能,Dynamic Faces利用了JavaServer Faces技术的运行时间库的可扩展性。 Dynamic Faces的核心是定制的Lifecycle和ViewRoot实现。这二个实现是JavaServer Faces技术提供的标准Lifecycle和ViewRoot实现的扩展, 一个标准的Lifecycle对象代表JavaServer Faces生命周期的一个实例,一个标准的ViewRoot对象代表一个组件树的根。联合使用定制Lifecycle对象和定制ViewRoot对象,使JavaServer Faces生命周期能够处理Ajax事务,在无需对整个网页更新的情况下重新显示组件树的一部分。这些定制实现服从于不支持Ajax请求的标准实现。

  为了使JavaServer Faces技术运行时间库知道定制Lifecycle对象的存在,我们必须在配置描述器中利用一个初始化参数向FacesServlet实例报告该对象。

<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<init-param>
<param-name>javax.faces.LIFECYCLE_ID</param-name>
<param-value>com.sun.faces.lifecycle.PARTIAL</param-name>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

  此外,我们还必须将Dynamic Faces依赖的Java Archive(JAR)文件添加到应用软件的web archive(WAR)文件的lib目录中。因为Dynamic Faces是基于Java Platform Enterprise Edition 5(Java EE 5)的,我们所需要的几乎所有依赖关系都已经存在。最后一个依赖是Shale Remoting,Dynamic Faces利用它从Java类路径中加载JavaScript文件和其它资源。 Shale Remoting依赖于commons-logging,因此我们必须向应用软件提供commons-logging。

  最后,我们必须在使用它的每个网页中说明该Dynamic Faces标签库。 对于符合标准的非XML语法的JavaServer Pages(JSP)网页而言,这种说明如下所示:

<%@ taglib prefix="jsfExt" uri="http://java.sun.com/jsf/extensions/dynafaces" %>

  对于符合XML语法的JavaServer Pages(JSP)网页而言,这种说明如下所示:

<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="1.2"
xmlns:jsfExt="http://java.sun.com/jsf/extensions/dynafaces"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">

  如果使用Facelets而非JSP,语法与JSP XML的语法非常相似,如下所示:

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:jsfExt="http://java.sun.com/jsf/extensions/dynafaces"
xmlns:f="http://java.sun.com/jsf/core">


  好了。我们可以开始利用Dynamic Faces向应用软件中增添Ajax功能了。

  作为一种手动配置应用软件的替代性方案,我们可以使用Dynamic Faces下载包,其中包括面向JSP和Facelets的空白应用软件。如果使用现成的空白应用软件,所有的设置工作已经预先完成,我们就可以开始编写网页了。

利用ajaxZone标签更新部分网页  确定网页上哪些组件将支持Ajax的一种方式是用Dynamic Faces提供的ajaxZone定制标签封装它们。当这样做时,我们就告诉Dynamic Faces只异步更新使用ajaxZone标签确定的组件树部分。

  例如,假设我们有一个带有一系列按钮的网页,客户在网上购买汽车时,可以用这些按钮选择标准或豪华装修。当客户点击一个按钮时,一系列其它组件的值会发生变化,而不会造成整个网页被更新。当客户改变一个组件的值时,汽车的价格也会改变,但不会造成整个网页的更新。

  图1显示的是cardemo应用软件中网页的一个屏幕快照,它使客户能够选择汽车的配置情况。

  图1显示了二个由ajaxZone标签划分的区域。 当客户点击区域2中的一个按钮时,该区域中组件的值会发生变化。当客户改变区域2中的一个组件的值时,区域1中Your Price输出组件的值也会随之变化。

  要实现这样的功能,我们需要将所有组件封装在ajaxZone标签中,如下所示:

<jsfExt:ajaxZone id="zone1">
<h:panelGrid columns="2">
<h:outputText styleClass="subtitle"
value="#{bundle.basePriceLabel}"/>
<h:outputText
binding="#{carstore.currentModel.components.basePrice}"/>
<h:outputText styleClass="subtitle"
value="#{bundle.yourPriceLabel}"/>
<h:outputText value="#{carstore.currentModel.currentPrice}"/>
</h:panelGrid>
</jsfExt:ajaxZone>
<jsfExt:ajaxZone id="zone2"
action="#{carstore.currentModel.updatePricing}">
<h:commandButton id="Standard" value="#{bundle.Standard}"
styleClass="#{carstore.customizers.Standard.buttonStyle}"
actionListener="#{carstore.choosePackage}"/>
<h:commandButton id="Deluxe" value="#{bundle.Deluxe}"
styleClass="#{carstore.customizers.Deluxe.buttonStyle}"
actionListener="#{carstore.choosePackage}"/>
<h:outputText value="#{bundle.Engine}"
styleClass="optionLabel"/>
<h:selectOneMenu styleClass="optionValue"
binding="#{carstore.currentModel.components.engine}"/>
<h:outputText value="#{bundle.Speakers}"
styleClass="optionLabel"/>
<h:selectOneRadio styleClass="optionValue"
binding="#{carstore.currentModel.components.speaker}"/>
</jsfExt:ajaxZone>

  前面的代码中包含名字分别为zone1和zone2的二个域。象代码显示的那样,zone 1中只有一个输出组件,因此它不会产生任何Ajax请求; Zone 2域中包含有输入和输出组件。当客户点击2个按钮中的1个,或者选择菜单或单选按钮列表中的一个选项时,zone2中的组件会启动一个Ajax请求。这一请求将引起方法表达式#{carstore.currentModel.updatePricing}中定义的操作被调用。

  当使用域时,每个Ajax事务将使得网页中的所有域被更新。前面例子的效果是,当用户选择zone 2中的任何输入组件时,Ajax功能会自动地更新zone 1中的汽车价格数据。

  值得指出的是,我们无需编写一行JavaScript代码就能够实现这一例子,我们也无需任何定制组件。这一应用软件使用了我们熟知的普通而简单的JavaServer Faces组件,但它们已经能够支持Ajax功能了。

  ajaxZone标签向网页创作者提供了一种使用Dynamic Faces的简单、熟悉、直观的方式。在最简单的例子中,ajaxZone标签能够向网页创作者提供所需要的功能。ajaxZone标签支持许多使我们能够进一步定制其操作的其它属性,ajaxZone文档中包含有其属性的完整清单。

  下面的部分将讨论使用Dynamic Faces的另一种方法,它使我们能够细粒度地控制网页中组件的Ajax化。

使用Dynamic Faces fireAjaxTransaction方法  为了对与Ajax相关的任务进行细粒度的控制,我们可以使用Dynamic Faces提供的内置JavaScript库。通过使用现有组件标签中合适的DynaFaces.fireAjaxTransaction JavaScript函数,我们可以对网页中组件异步更新方式有更细粒度的组件级控制。

  例如,假设我们希望网页中的一些组件对一种类型的JavaScript事件━━例如onclick作出响应,并希望该网页中的其它组件对其它类型的JavaScript事件作出响应。又假设我们希望生成一个Ajax请求的每个组件能够引起组件树的不同部分被异步更新。为了完成这些任务,我们需要使用fireAjaxTransaction函数。

  为了使用fireAjaxTransaction函数,需要完成下面的准备工作:

  ·在一个组件标签中增添一个JavaScript事件属性,例如onclick。

  ·将该属性的值设置成DynaFaces.fireAjaxTransaction函数。

  ·向该函数传递一系列参数。

  下面的代码是一个简单的Hello World例子中一个网页的一部分,用户可以输入他或她的名字,点击一个按钮,应用程序会用一条包含用户名字的问候语响应用户的输入。

...
<f:view>
...
<h:form id="form" prependId="false">
...
<h:graphicImage value="wave.med.gif"/>
<p>
Hello, my name is Duke. What is your name?
<p>
<h:inputText id="input" value="#{testBean.name}"/>
<h:commandButton id="button"
actionListener="#{testBean.changeText}"
onclick="DynaFaces.fireAjaxTransaction(this,
{execute: 'input', 'button',
render: 'input', 'text'}); return false;"
value="click"/>
<p>
<h:outputText id="text" value="#{testBean.text}"/>
</h:form>
...
</f:view>

  在上面的例子中,inputText标签代表一个输入域。当用户在该输入域中输入内容,并点击commandButton标签表示的按钮,就会出现下面的情况:

  1、DynaFaces.fireAjaxTransaction函数执行,使得Dynamic Faces向服务器发送一个Ajax请求。

  2、服务器返回一个Dynamic Faces JavaScript库处理的特别XML响应。

  3、合适的库函数用新的值更新HTML DOM树。

  为了告诉fireAjaxTransaction函数如何生成Ajax请求,我们向它传输一系列参数。在上面的例子中,我们向fireAjaxTransaction函数传递了2个参数。下面是调用fireAjaxTransaction函数的代码:

onclick="DynaFaces.fireAjaxTransaction(this,
{execute: 'input', 'button',
render: 'input', 'text'}); return false;"

  This参数指的是代表触发该事件的按钮的标签,其它参数由指示Dynamic Faces如何处理该请求的选项组成。在这个例子中,选项是execute和render。

  Execute和render选项指的是JavaServer Faces生命周期的部分,如图2所示:


图2: Dynamic Faces如何利用execute和render选项划分JavaServer Faces技术的生命周期

  Execute是在postback期间执行的生命周期部分。它包含有处理模式对象的数据转换、验证、更新阶段; Render根据对网页的请求显示该网页。

  在对fireAjaxTransaction函数的调用中使用的execute选项列出了在JavaServer Faces生命周期的execute部分期间必须处理的组件的ID,Hello World例子中的这行代码如下所示。

execute: 'input', 'button'

  接受用户名的input组件必须执行生命周期的execute部分,因为它的数据必须被保存到模式对象中。Button组件也应当执行生命周期的execute部分,因为Invoke Application阶段是生命周期execute片断的一部分。

  当生命周期的render片断显示一个使用Dynamic Faces的网页时,作为一次Ajax请求的结果,它只显示该网页上被选定的组件。我们使用render选项显示要重新显示的组件的ID,Hello World例子中的render选项如下所示:

render: 'input', 'text'

  在这一例子中,作为Ajax请求的结果,生命周期的render片断会重新显示网页上的input和text组件。当用户点击该按钮时,代表input组件的输入字段和代表text组件的输出文本会被再次显示。输入字段会被重新显示,清除在点击该按钮前用户输入的值。输出文本会被重新显示,显示包含在点击该按钮前用户在输入域中输入的值的信息。该网页上的其它组件无需被重新显示。

  除了execute和 render选项外,我们还可以使用其它选项,进一步定制Dynamic Faces处理事件的方式。需要记住的是,使用fireAjaxTransaction函数使我们能够对网页中的哪些组件会得益于Ajax有更多的控制。事实上,fireAjaxTransaction函数让我们能够能够使网页中的任何组件支持Ajax,而无需编写JavaScript或任何其它代码。
联合使用Dynamic Faces和jMaki  至此,我们已经学习了如何使用Dynamic Faces重新显示支持Ajax的JavaServer Faces组件。但是,如何增添曾经在基于JavaServer Faces的应用软件中看到的支持Ajax的widget呢?

  我们可以利用Project jMaki将喜欢的widget封装在JavaServer Faces组件中。这样,我们既能够享受到JavaServer Faces组件模式的好处,也能够获得使用被封装为JavaServer Faces组件的widget的灵活性。 同时,我们无须编写为现有组件实现Ajax功能的JavaScript代码,以及为widget创建JavaServer Faces组件所要求的Java平台代码。

  如何联合使用jMaki和Dynamic Faces呢?对于网页创作者而言,这非常简单,就是将与jMaki widget相关的标签拖到网页中。
为了联合使用jMaki widget和Dynamic Faces,widget开发人员需要对jMaki widget的组件文件作一些小小的修改。这些修改使jMaki widget能够充分利用JavaServer Faces技术提供的组件状态管理系统,正确地转换Dynamic Faces要求的header。修改的细节超出了三篇文章的讨论范围,读者可以参阅相关资料。

  Dynamic Faces开发团队已经完成了转换3个与Dynamic Faces.联合使用的jMaki widget所需要的工作。被转换的jMaki widget是script.aculo.us in-place editor widget、Dojo fisheye widget、Dojo inline-editor widget。

  除了转换fisheye widget,开发团队还修改了jMaki API,使widget能够触发一个JavaServer Faces价值修改事件,如下图所示:

<a:ajax name="dojo.fisheye"
value="#{fishEyeBean.selectedIndex}"
valueChangeListener="#{fishEyeBean.valueChanged}"
args="{items:[
{iconSrc:'images/150x126_jalopy.jpg',caption:'Jalopy',index:0},
{iconSrc:'images/150x126_luxury.jpg',caption:'Luxury',index:1},
{iconSrc:'images/150x126_roadster.jpg',caption:'Roadster',index:2},
{iconSrc:'images/150x126_suv.jpg',caption:'SUV',index:3}
]}"
/>

  Dynamic Faces和jMaki开发团队正在加紧工作,确保所有的jMaki widgets支持Dynamic Faces。

  现在,让我们来站在网页创作者的角度来讨论这一问题。要想搞明白如何联合使用jMaki script.aculo.us in-place editor widget和 Dynamic Faces,我们在一个JavaServer Faces数据表组件中包含该widget,使我们能够编辑该表中一个单元的值。

  在JSP网页中,我们必须说明要求的标签库,以及Dynamic Faces和jMaki标签,如下所示:

<%@taglib prefix="f"
uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h"
uri="http://java.sun.com/jsf/html"%>
<%@taglib prefix="jsfExt"
uri="http://java.sun.com/jsf/extensions/dynafaces"%>
<%@taglib prefix="a"
uri="http://java.sun.com/jmaki-jsf" %>

  下面的代码添加的是<jsfExt:scripts />标签:

<f:view>

<html>
<head>
<title>Table with jMaki</title>
<jsfExt:scripts />
</head>
<body>

  这一标签显示Dynamic Faces所要求的JavaScript文件的<script>元素。

  最后,通过包含一个指定被封装为jMaki widget 的in-place editor的 jMaki ajax标签,我们就将该widget添加到了网页上。

<h:form>

<h:dataTable
...
rows="10" binding="#{ResultSetBean.data}"
value="#{ResultSetBean.list}"
var="customer">
<h:column>
<f:facet name="header">
<h:outputText value="Account Id"/>
</f:facet>
<h:outputText id="accountId"
value="#{customer.accountId}"/>
</h:column>

<h:column>
<f:facet name="header">
<h:outputText value="Customer Name"/>
</f:facet>
<a:ajax name="scriptaculous.inplace"
value="#{customer.name}"/>
</h:column>
</h:dataTable>
...

</h:form>
</body>
</html>
</f:view>

  图3显示的是上述网页:


图3:用户修改一个单元的值之前

  图4显示的是当用户点击Customer Name列中一个单元的链接时的情况:


图4: 用户点击Customer Name列中一个链接后的情况

  需要注意的是,当用户点击Customer Name列中的一个元素时,客户名字元素会被一个输入组件、一个"OK"按钮、一个"Cancel"链接所取代,使用户能够编辑当前的客户名字。如果用户点击"Cancel"而不是"OK",该单元就会被重新显示为原来的值;如果用户输入一个值,并点击"OK"按钮,新的值就会被利用Ajax技术发送到服务器,使该模式更新为新的值。 然后,被编辑的单元就会被重新显示。 图5显示的是是单元被修改后的网页:


图5:在用户向服务器提交新的值后,网页重新显示为新的值

  结论

  Project Dynamic Faces向我们提供了一种向基于JavaServer Faces的应用软件中添加Ajax功能的灵活、有效的方式,而无需放弃JavaServer Faces组件模式的任何优势。在内置的JavaScript库、Ajax实现、Dynamic Faces提供的组件交互模式的帮助下,我们会发现利用Dynamic Faces添加Ajax功能更容易了。基于JavaServer Faces的应用软件能够得益于jMaki widget提供的更多的灵活性。

 查看全文

在咖啡里加糖 论Java世界的Ruby

发表人:xuniji123 | 发表时间: 2006年十二月17日, 12:47

利用动态脚本编写你的Java应用程序以及重用你的Java类库  自从计算机诞生以来,软件开发就倾向于使用高级语言进行开发。从汇编,到C,到C++,再到JAVA,每一次升级就会面临来自各界同样的问题:太慢、而且有太多的Bug、开发者不想放弃对这些原有语言的使用。渐渐地,随着硬件的快速发展,新的研究和开发技术大大改进了编译器、解释器、和虚拟机,开发者不得不向高级语言转移,放弃他们使用的低级语言开发以提高生产力(将他们从低级语言的障碍中释放出来以提高他们的生产力)。

  Java现在在软件开发的很多领域里面占有主导地位,但是在这个发展过程中,动态脚本很有可能无情地取代它的地位。许多年以来,像Python、Perl、Rexx、Groovy、TCL和Ruby这样的语言能够在很多专业领域里面非常出色地工作,例如文件处理、自动测试、软件构建、代码重构、和Web图形页面设计——他们有着历史性的名字“脚本语言”。而且在最近的一些年里,在大多数由Java,C++和其他编译型计算机语言开发的大型工作里面,他们也取得了相应的进展。

  去年的时候,Ruby on Rails(RoR)Web框架使Ruby有了更进一步的发展。RoR结构利用简单的Ruby代码定义了一个典型的多层次Web应用程序——图形页面层、业务逻辑层和数据持久层,因此减小了冗余文件、样本文件代码、生成的源代码以及配置文件。RoR框架能够更加优化更加容易地使用Ruby语言;而且Ruby,这种完善的脚本语言,相对于RoR框架来说可以在更多的领域里面使用。
  
  作为一个长期的Java开发者,我很可能坚持在一段时间里一直用Java作开发。但是我仍然保持在我开发的基于Java的系统里面使用其他的语言,而且Ruby最近显示出来是特别好的一种候选语言。在JRuby解释器的帮助下,Ruby和Java一起工作得很好,包括配置、整合、和Java软件的重用。而且在简单学习Ruby的过程中也提高了我Java代码的质量。使用Ruby可以让我很容易地完成像功能程序和元程序一样的技术手法,这些技术手法我在Java里面都是很难实现的。学习这些Ruby里面的技术手法可以帮助我更好鉴别什么时候而且怎样在Java开发中使用它。

  这篇文章,我希望能够和你一起分享我在开发Java系统的时候使用Ruby的那种兴奋感。我比较一下Java和Ruby的优点和缺点,而且介绍一下JRuby解释器的支持者和反对者。而且我会向大家显示区分Ruby和Java使用的最佳实践以让它们各自得到最优化的使用。我会使用一些简单的代码来举例说明这个观点,并且介绍一个消息实例来展示在Java系统里面怎样结合使用Ruby,使其能够更好地使用动态元程序语言的弹性、表现方式以及功能。

  Ruby vs. Java

  这篇文章从一个Java开发者的角度解释了Ruby,主要是集中比较这两种语言。像Java一样,Ruby也是一种完全的面向对象的语言。但是这两种语言有很大的不同。Ruby是动态类型的而且是在源代码解释器里面运行的,这种语言能够像程序和功能范例一样支持元编程。我这里不会介绍Ruby的具体语法,接下来的文章里面会广泛地覆盖其他各个方面。

  动态类型

  Java有静态类型。你定义每个变量的类型,接下来在编译的过程中,如果你使用了类型错误的变量将会得到一个编译时错误。Ruby却相反,拥有动态类型:你不用定义函数和变量的类型,而且没有到运行的时候不会使用类型检测,如果你调用一个不存在的方法就会得到错误信息。尽管这样,Ruby不会关心一个对象类型,仅仅看它是否在一个方法里面调用了这个对象的方法。因为这个原因,这种动态方法可以得到这样一个duck类型:“如果一个事物走起来像一只鸭子(duck)而且像一只鸭子(duck)呷呷地叫,它就是一只鸭子。”

Listing1.Duck typing

class ADuck
def quack()
puts "quack A";
end
end
class BDuck
def quack()
puts "quack B";
end
end
# quack_it doesn't care about the type of the argument duck, as long
# as it has a method called quack. Classes A and B have no
# inheritance relationship.
def quack_it(duck)
duck.quack
end
a = ADuck.new
b = BDuck.new
quack_it(a)
quack_it(b)


  Java也可以通过反射让你使用动态类型,但是这种笨拙冗长的工作会导致很多混乱的异常发生,像NoSuchMethodError和InvocationTargetException;在实践中,这些异常倾向于在Java反射的代码中突然出现,而且相对于Ruby而言出现频率更高。

  即使在没有使用反射的Java代码中,你会经常丢失掉静态类型的信息。比如,在Command设计模式里面使用execute()方法必须返回Object胜于在Java代码里面使用的特殊类型,结果会导致很多ClassCastException发生。同样的,当在编译时和运行时修改方法签名的时候,运行时错误就会发生。在实践开发中,不论是Java还是Ruby,这样的错误很少引起严重的程序Bug。一个健壮的单元测试——任何时候你都会用到的——通常都能够及时捕捉他们。

  Ruby的动态类型意思是你不用重复问你自己一个问题:在Java里面你是否经常在一行里面遇到这样冗长的代码:
XMLPersistence xmlPersistence
= (XMLPersistence)persistenceManager.getPersistence();

  Ruby消除了这种对于类型定义和转换的需要,上边的代码用一个典型的Ruby等价表达为;
xmlPersistence = persistence_manager.persistence.

  Ruby的动态类型意义上不是弱类型——Ruby经常需要你传递正确类型的对象。事实上,Java强制类型转换比Ruby要弱。例如,Java里面:”4”+2 等于”42”,这里会将整数转化为字符串,在Ruby里会抛出一个TypeError,告诉你这个“can't convert Fixnum into String.”(Fixnum类型是不可以转化为String的)。同样的,Java里,因为作类型校正牺牲了速度,而且过多地做了整型操作,产生像Integer.MAX_VALUE + 1的整型,和Integer.MIN_VALUE等价,可是Ruby类型校正整型只是在需要的时候。

  不论Ruby有什么优点,Java的静态类型可以让它在大规模的项目里面作为首选:Java工具能够在开发时候明白代码意思。IDE能够在类之间依赖跟踪,找到方法和类的用处,自动检标识符而且帮助你检测代码。同样的虽然Ruby工具在这些功能上存在限制,它缺乏类型信息所以不能够完成上边这些工作。
解释性语言  Ruby是在解释器里面执行的,所以你不需要等待编译可以直接测试你的代码;你能够很平坦地利用交互方式执行Ruby,执行你键入的每一行。除开这些反馈,解释性语言在处理程序Bug地时候很少有明显的优点。使用编译性语言,能够分析代码造成的程序Bug,这些领域工程师必须决定发布过的应用程序的确切版本而且需要在源代码配置管理系统里面查找这些代码。在真实生活中,这些通常很简单。使用解释性语言,另一方面,分析的时候源代码是可以马上利用的而且在需要的时候如果突然异常是可以修复的。

  可是解释性语言因为执行慢有一个不幸的名声。对比Java的历史,一种“semi-compiled”语言:在早些年,JVM经常在运行时解释字节码,Java因为速度慢捐献了它的名声。然而很多应用程序花费了开发者很多时间等待用户或者是网络输入输出而且这些瓶颈一只保持着,Java开发者快速学习高效算法来优化它强于使用低级计算机语言进行开发。最近几年里,Java速度有了一定的提升;例如,基于动态分析的最优化及时编译器(just-in-time)有时候让Java胜过C++,这些在基于静态编译中最优化是受到限制的。

  在很多应用程序中,Ruby不比其他语言速度慢。在不久的将来,Ruby将得到更大的进步就像Ruby本地解释器转移到基于字节码的系统,而且JVM JRuby解释器获得了将Ruby编译成Java字节码的能力。最终的,任何平台对于很多功能来说都逐渐被忽略,由此获得了平台独立性。

  功能性编程

  Ruby支持熟练的多样化设计程序范例。另外的对于它的纯面向对象的风格,它同样支持一次性脚本的程序化风格:你可以在类和函数外任何地方写代码,就像函数在任何类之外一样。

  更有趣的是,对于Java程序员寻找的新的和有用的观点,Ruby支持功能范例。你可以在Java里面使用更多的功能程序结构,使用很多类库支持就像Jakarta Commons Collections系列的集合包一样,但是这些语法是笨拙的。Ruby,虽然不是一种纯功能性语言,但是对待功能和匿名块如同完整的语言成员一样,这些都是能够像其他简单对象一样被传递到周围和利用的。

  在Java里面,你经常反复使用集合的Iterator(迭代器),从逻辑上去遍历集合里面的每一个元素。但是这种遍历仅仅是这样一个细节实现:一般来说,你仅仅尝试去接受对集合里面的每一个元素采取同样的逻辑。在Ruby里,你可以将一段代码块传给一个执行它的方法,遍历是在执行后台运行的。例如,[1,2,3,4,5].each{|n|print n*n, “ “}将打印这样的字符串:1 4 9 16 25;迭代器将会遍历这个列表里面的每一个元素将他作为一个变量n传到代码块里面。

  利用在代码块之前和之后执行的指令将代码块封装起来的功能程序是很有用的。比如,在Java里面,你可以使用Command模式保证一个文件的打开和关闭、数据库的事务处理、或者其他的资源调用。这些匿名内部类和回调函数式的无用框架将会使代码变得冗余沉重;除此之外,这里还有一个变迁规则就是变量在匿名Command类里面传递的时候必须定义成为final。而且为了确保最后的代码块在逻辑上能够执行,整个工作就会使用try{…}finally{…}封装起来。

  在Ruby里面,你可以封装任何函数或者代码块,不需要任何方法定义或者匿名内部类。在Listing 2里面,这个文件打开,然后在write()方法执行过后关闭。没有任何需要使用transaction()方法的代码和代码块。

Listing 2. Wrap a code block
File.open("out.txt", "a") {|f|
f.write("Hello")
}

  元程序语言

  你一般情况下是定义你的Java类作为你的源程序,但是你仍然可以在运行时进行类定义的操作。这个需要高级技术比如在加载类的时候增加字节码。比如,Hibernate直接插入数据存取逻辑到商业对象的字节码里面,从额外的数据存取层里保存应用程序。但是类操作,又称为元程序,在实践中仅仅是用来组织基础程序的:应用程序是不能有效地引入这些技巧和脆弱的技术的。

  即使在开发的时候,Java限制了开发者改变类的能力。为了加入一个isBlack()方法检测一个String是否全是空字符串,你不得不加入一个带有静态方法的StringUtils 类;理论上,这个新方法是输入String的。

  另一方面,如何在Ruby里简单地用一个空白来扩展String类?方法。实际上,因为在Ruby里面任何东西都是一个对象,你能够增加Fixnum类,这个等价于Java里面的原始int类型,如同Listing3所表示的 查看全文

JSF“裸体”降临Java Web世界

发表人:xuniji123 | 发表时间: 2006年十二月17日, 12:44

EJB用自己的悲剧人生警告Sun,不可对新技术的推广掉以轻心,但Sun还是再次犯下同样的错误。与Microsoft和Intel成功的商业推广策略截然不同的是,Sun 完全没有估量到,JSP作为一项成功技术的价值和影响力,在JSF的推广上,出现了令人痛心的失误。如果JSF以JSP3.0的名义推出,那么JSF的日子恐怕要比现在好过得多。

  1. JSF没有站在JSP巨人的肩膀上

  前文说过,EJB是Sun的伤心往事,它用自己的悲剧人生,警告Sun,不论技术也好,商务也好,凡事应该有一个全盘的规划,再也不能想到什么是什么了。一项好的技术,如果不加以适当的推广,最后可能逃脱不了被束之高阁的命运,大把的资金投入,自然也难免竹篮打水一场空。

  当然,如何进行商业运作,Sun比我高明得多了,似乎轮不到我在这里说三道四,不过,Java已经不单单属于Sun了,Java已经成为全世界的Java,所以,所有的Java程序员,都有发表自己意见的权利。未必都是真知灼见,但Java世界就是因为有这些不同声音的存在,才显得无比的精彩。

  其他的技术我不敢妄加评论,就JSF这项技术而言,Sun的商业策略实在是不敢恭维。在JSP已经深入人心的时候,为什么不继续沿用JavaServer Pages的这个如雷贯耳的名称,而要标新立异地推出一个JavaServer Faces的怪物呢?你看人家Microsoft,在ASP流行开来之后,推出ASP.NET,是多么的顺理成章。

  暂且不论这两项技术的区别有多大,就冲着似曾相识的名称,Microsoft就让大批的ASP用户,自觉自愿地加入ASP.NET的阵营。没有任何抵抗,Microsoft兵不血刃,不费一枪一弹就完成了从ASP向ASP.NET的过渡。

  同样的策略Intel也曾使用过。第一代“奔腾”芯片推出后,获得了巨大的成功,“奔腾”一词,一时间名噪天下。Intel看到了这一点,并且立刻明白了该怎么做,所以,当下一代芯片制造出来时,Intel完全没有在命名上费什么脑筋,直接冠以“奔腾II”的名字,马上令一大批“奔腾”的爱好者趋之若骛。此后,“奔腾III”“奔腾IV”,Intel将“奔腾”一词的所有油水都榨干了,才心满意足地构思下一个名字。

  相比之下,Sun则完全没有估量到一项成功技术的价值和影响力。令多少对手眼红的JSP背后庞大的用户群,Sun却视若无物,不知道Sun是没有看到这一点呢,还是不屑利用这一优势。

  不管怎样,当JSP如日中天时,不知借JSP之势点燃JSF的大火,反而暴殓天物,另起炉灶,Sun简直就是在自毁JSF的前程。也许Sun主观上并不存在这样的故意性,但客观上造成了这样一种局面,也是不可原谅的失误。

  2. JSF唯有一切从头再来

  如果JSF没有叫做JSF,而是叫做JSP 3.0,情形会是如何呢?

  可以想见,首先,大批的JSP爱好者会蜂拥而至,庆贺JSP的新版本;然后,一批“牛人”们很快发现,JSP的新版本,引入了他们期待已久的组件模型和事件驱动模式,JSP终于有了和ASP.NET抗衡的资本;接下来,“牛人”们必定奋笔疾书,以超凡的热情四处撒播JSP 3.0的种子。

  于是,网络上、论坛里,到处充斥着为JSP 3.0唱赞歌的文章,JSP 3.0成为炙手可热的名词,而Sun专家们借JSP 3.0的名义推销的JSF组件模型和事件驱动模式,说不定现在已经成为Java Web编程的新贵。

  将JSF以JSP3.0的名义发布,绝非戏言,是完全可行的。从技术上来看,JSF是建立在Servlet/JSP基础之上的,和JSP有着天然的联系,将JSF作为JSP3.0的一个崭新的扩充部分,随JSP3.0一起发布,即符合从JSP到JSF的平滑过渡的要求,同时也能满足程序员对于JSP3.0新特征的期待。

  实际上,JSF和JSP融合的趋势越来越明显,例如在JSF1.2版本之前,JSP和JSF各有一套独立的表达式语言(EL,Expression Language),而从JSF1.2开始,这两套不同的表达式语言已经统一为Unified EL,并且从JSF和JSP规范中分离出来,自成一体。所以,让JSF搭上JSP的快车,一起前进,其实是很自然的事。

  可惜,这些只能发生在Sun的梦里了。JSP与JSF,一字之差,Sun将一项颇具潜力的Java Web框架技术,亲手打回到娘胎中,让其以一个初生婴儿的身份,光着身子降临到Java Web世界。这个本来可以衣着光鲜地与ASP.NET一起独步江湖的汉子,现在唯有恨恨地抛下一句“君子报仇,十年不晚”,然后黯然离去了。

 查看全文

Java路径问题最终解决方案之一

发表人:xuniji123 | 发表时间: 2006年十二月17日, 12:40

前言
  Java的路径问题,非常难搞。最近的工作涉及到创建和读取文件的工作,这里我就给大家彻底得解决Java路径问题。

  我编写了一个方法,比ClassLoader.getResource(String 相对路径)方法的能力更强。它可以接受“../”这样的参数,允许我们用相对路径来定位classpath外面的资源。这样,我们就可以使用相对于classpath的路径,定位所有位置的资源!

  Java路径

  Java中使用的路径,分为两种:绝对路径和相对路径。具体而言,又分为四种:

  一、URI形式的绝对资源路径

  如:file:/D:/java/eclipse32/workspace/jbpmtest3/bin/aaa.b

  URL是URI的特例。URL的前缀/协议,必须是Java认识的。URL可以打开资源,而URI则不行。

  URL和URI对象可以互相转换,使用各自的toURI(),toURL()方法即可!

  二、本地系统的绝对路径

  D:/java/eclipse32/workspace/jbpmtest3/bin/aaa.b

  Java.io包中的类,需要使用这种形式的参数。

  但是,它们一般也提供了URI类型的参数,而URI类型的参数,接受的是URI样式的String。因此,通过URI转换,还是可以把URI样式的绝对路径用在java.io包中的类中。

  三、相对于classpath的相对路径

  如:相对于

  file:/D:/java/eclipse32/workspace/jbpmtest3/bin/这个路径的相对路径。其中,bin是本项目的classpath。所有的Java源文件编译后的.class文件复制到这个目录中。

  四、相对于当前用户目录的相对路径

  就是相对于System.getProperty("user.dir")返回的路径。

  对于一般项目,这是项目的根路径。对于JavaEE服务器,这可能是服务器的某个路径。这个并没有统一的规范!

  所以,绝对不要使用“相对于当前用户目录的相对路径”。然而:

  默认情况下,java.io 包中的类总是根据当前用户目录来分析相对路径名。此目录由系统属性 user.dir 指定,通常是 Java 虚拟机的调用目录。

  这就是说,在使用java.io包中的类时,最好不要使用相对路径。否则,虽然在J2SE应用程序中可能还算正常,但是到了J2EE程序中,一定会出问题!而且这个路径,在不同的服务器中都是不同的!

  相对路径最佳实践


  推荐使用相对于当前classpath的相对路径

  因此,我们在使用相对路径时,应当使用相对于当前classpath的相对路径。

  ClassLoader类的getResource(String name),getResourceAsStream(String name)等方法,使用相对于当前项目的classpath的相对路径来查找资源。

  读取属性文件常用到的ResourceBundle类的getBundle(String path)也是如此。

  通过查看ClassLoader类及其相关类的源代码,我发现,它实际上还是使用了URI形式的绝对路径。通过得到当前classpath的URI形式的绝对路径,构建了相对路径的URI形式的绝对路径。(这个实际上是猜想,因为JDK内部调用了SUN的源代码,而这些代码不属于JDK,不是开源的。)
相对路径本质上还是绝对路径
  因此,归根结底,Java本质上只能使用绝对路径来寻找资源。所有的相对路径寻找资源的方法,都不过是一些便利方法。不过是API在底层帮助我们构建了绝对路径,从而找到资源的!

  得到classpath和当前类的绝对路径的一些方法

  下面是一些得到classpath和当前类的绝对路径的一些方法。你可能需要使用其中的一些方法来得到你需要的资源的绝对路径。

  1.FileTest.class.getResource("")

  得到的是当前类FileTest.class文件的URI目录。不包括自己!

  如:file:/D:/java/eclipse32/workspace/jbpmtest3/bin/com/test/

  2.FileTest.class.getResource("/")

  得到的是当前的classpath的绝对URI路径。

  如:file:/D:/java/eclipse32/workspace/jbpmtest3/bin/

  3.Thread.currentThread().getContextClassLoader().getResource("")

  得到的也是当前ClassPath的绝对URI路径。

  如:file:/D:/java/eclipse32/workspace/jbpmtest3/bin/

  4.FileTest.class.getClassLoader().getResource("")

  得到的也是当前ClassPath的绝对URI路径。

  如:file:/D:/java/eclipse32/workspace/jbpmtest3/bin/

  5.ClassLoader.getSystemResource("")

  得到的也是当前ClassPath的绝对URI路径。

  如:file:/D:/java/eclipse32/workspace/jbpmtest3/bin/

  我推荐使用Thread.currentThread().getContextClassLoader().getResource("")来得到当前的classpath的绝对路径的URI表示法。

  Web应用程序中资源的寻址

  上文中说过,当前用户目录,即相对于System.getProperty("user.dir")返回的路径。

  对于JavaEE服务器,这可能是服务器的某个路径,这个并没有统一的规范!

  而不是我们发布的Web应用程序的根目录!

  这样,在Web应用程序中,我们绝对不能使用相对于当前用户目录的相对路径。

  在Web应用程序中,我们一般通过ServletContext.getRealPath("/")方法得到Web应用程序的根目录的绝对路径。

  这样,我们只需要提供相对于Web应用程序根目录的路径,就可以构建出定位资源的绝对路径。

  这是我们开发Web应用程序时一般所采取的策略。

 查看全文

MyEclipse+Spring+Hibernate+Struts+J2EE视频下载

发表人:xuniji123 | 发表时间: 2006年十二月15日, 16:39

http://download.eimhe.com/

看了别忘回复哈!

现在可能关闭了,服务器太忙,大家就耐心点。他还会一直更新的。


Ajax:拥抱JSON,让XML走开

发表人:xuniji123 | 发表时间: 2006年十二月12日, 19:20

Ajax(Asynchronous JavaScript and XML)说到底就是一种浏览器异步读取服务器上XML内容的技术。现在的技术凡是跟XML扯上关系,再加上个概念做幌子,就像金装了一样,拽得不行。门外 的人看得很是热闹,门里的人摇摇头不外如是。XML呢,跨平台的新潮语言?其实XML=TXT。XML只是符合很多规范的文本。它本身什么都不是,只是保 存字符的文件。而浏览器异步读取的只是服务器上的文本内容,所以在Ajax开发时完全不必拘泥于XML。[版权所有,www.jialing.net]

  JSON的来历

  XML 的作用是格式化数据内容。如果我们不用XML还有什么更好的方法吗?这个答案是JSON。介绍JSON之前我先介绍一下JavaScript这门脚本语 言。脚本语言自身有动态执行的天赋。即我们可以把想要执行的语句放在字符串里,通过eval()这个动态执行函数来执行。字符串里的内容会像我们写的脚本 一样被执行。

  示例1:

<HTML>
<HEAD>
 <TITLE>eval example 1</TITLE>
</HEAD>
<BODY>
 <script>
  str = "alert('hello')";
  eval(str);
 </script>
</BODY>
</HTML>

  打开页面会弹出hello窗口。

  我们可以在字符串中放任何脚本语句,包括声明语句:

<HTML>
<HEAD>
<TITLE>eval example 2</TITLE>
</HEAD>
<BODY>
<script>
 define = "{name:'Michael',email:'17bity@gmail.com'}";
 eval("data = "+define);
 alert("name:"+data.name);
 alert("email:"+data.email);
</script>
</BODY>
</HTML>

  如果我们在后台异步传来的文本是JavaScript的声明语句,那么不是一条eval方法就能解析了?对于解析复杂的XML,这样的效率是多么大的提高啊!

  现在就来告诉你什么是JSON:JavaScript Object Notation。我更愿意把它翻译为JavaScript对象声明。比如要从后台载入一些通讯录的信息,如果写成XML,如下:

<contact>
 <friend>
  <name>Michael</name>
  <email>17bity@gmail.com</email>
  <homepage>http://www.jialing.net</homepage>
 </friend>
 <friend>
  <name>John</name>
  <email>john@gmail.com</email>
  <homepage>http://www.john.com</homepage>
 </friend>
 <friend>
  <name>Peggy</name>
  <email>peggy@gmail.com</email>
  <homepage>http://www.peggy.com</homepage>
 </friend>
</contact>

  而写成JSON呢:

[
{
 name:"Michael",
 email:"17bity@gmail.com",
 homepage:"http://www.jialing.net"
},
{
 name:"John",
 email:"john@gmail.com",
 homepage:"http://www.jobn.com"
},
{
 name:"Peggy",
 email:"peggy@gmail.com",
 homepage:"http://www.peggy.com"
}
]

  简单的不只是表达上,最重要的是可以丢弃让人晕头转向的DOM解析了。因为只要符合JavaScript的声明规范,JavaScrip会自动帮你解析好 的。Ajax中使用JSON的基本方法是前台载入后台声明JavaScript对象的字符串,用eval方法来将它转为实际的对象,最后通过 DHTML更新页面信息。
http://soft.yesky.com/356/2708356.shtml

 查看全文

JBuilder被迫改嫁,最后一次与“Borland”拥抱

发表人:xuniji123 | 发表时间: 2006年十一月25日, 22:08

从11月28日起,Borland公司将依次在北京、上海、大连和深圳召开JBuilder 2007和InterBase2007 的新品发布会,即将投入新东家codegear的JBuilder2007,又将为我们带来哪些意想不到的完美体验,CodeGear的JBuilder会成功地重返顶级Java开发工具之巅吗?李维先生将作为主讲人为您讲述JBuilder的第3次蜕变!让我们共同见证JBuilder与Borland的最后一次拥抱!欢迎您前往http://www.csdn.net/subject/borland/index.html 报名参会!

活动内容:

Java市场的现状
JBuilder现在和未来
Eclipse 概观
第3次蜕变的JBuilder : JBuilder On Eclipse

  • 目标市场
  • 三合一的强大Java开发工具
  • 現今最强的视觉化EJB 3/Web Service Java开发工具
  • 功能齐全的开发者利器:ProjectAssist
  • Peer to Peer程序设计
  • Together For JBuilder

JBuilder未来的发展路线图

  • Project “Peloton”

强大,多核心的InterBase 2007

  • 产品路线图
  • 目标市场
  • 案例讨论
 查看全文

EJB3.0:是脱胎换骨,还是重蹈覆辙?

发表人:xuniji123 | 发表时间: 2006年十一月24日, 14:04

今年EJB3.0规范已经正式发布了。Sun非常自信地向业界宣布,这个EJB版本将有效地减轻开发难度,通过使用EJB3.0,可以大大降低开发成本。但也有人批评说,Sun在EJB中加入了很多Java EE 5的新特性,如EJB3.0将使用注释(annotations)来进行配置。这将增加开发人员的学习成本,虽然从表面上是简单了,但实际上并没有明显降低开发难度。还有人批评Sun的EJB3.0的持久层架构抄袭了Hibernate。EJB3.0真的象他们所说的那样是Hibernate的翻版吗?EJB3.0是否能依靠它的新架构和Java EE 5的支持摆脱人们对EJB1.x和EJB2.x的恐惧呢?EJB3.0在未来是否能成为对象持久化的代名词呢?

EJB:刚刚诞生就被打入冷宫

在Java发展史上,曾有过很多重要的时刻。如在上世纪末,也就是在1998年,JSP和EJB的诞生就是一个不同寻常的时刻。JSP在诞生后,就立刻引起了很多开发人员的注意,并很快成为了Web开发的主流。而几乎和它同时诞生的EJB1.0却一直倍受冷落。在EJB1.0诞生后的几年,Sun又推出了EJB2.0规范,不过它的命运也可EJB1.0差不多,还是没有翻身。这其中最大的原因,我想是因为Sun没有兑现它承诺而造成的。

Sun在发布J2EE相关规范和产品时承诺,J2EE将会使开发变得更容易,从而会显著降低开发成本。但在J2EE发布时,满心欢喜的人们却发现,被认为是J2EE中最有价值的组成部分:EJB却是如此的复杂。在编写EJB时需要进行大量的配置,而且还需要实现一大堆的接口。这不但没有降低开发难度,反而成为很多开发人员的恶梦。
在EJB2.x刚出来的几年,国内有很多程序员盲目跟风,但当时,他们中的大多数都只是停留在EJB的“名词”阶段。而当他们开始熟悉并使用EJB时,却发现并不是象他们想得那样美妙。

不知道Sun的EJB设计人员是如何考虑的。本来通过很简单的方法就可以从数据库中得到数据,而EJB却要专门为其修一条一级的高输公路,将本来就不多的数据运了出来,这简直就是多此一举。

在取数据时经过这样的周折,它的效率也大受影响。也许Sun当初根本就没考虑过它的效率。
实体Bean在EJB2.0后就成为EJB最重要的一部分,但是它的概念重来就没清楚过。如Sun建议将业务逻辑代码放到会话Bean中,也就是说,前端应该直接访问会话Bean。而作为对数据直接封装的实体Bean却提供了远程接口,这也就意味着前端也可以直接访问实体Bean。这就与多程序应用结构不太符合。还有就是实体Bean既然是对数据的原始封装,那为什么要提供事务、安全这些业务逻辑层的功能。更不可思议的是实体Bean既然提供了本地接口,那又为什么不通过本地接口,而要通过JNDI查找呢?这些概念上的混淆使得EJB更加难以使用。

近几年非常流行的SOA(Service-Oriented Architecture)模式为企业级应用提供了更好的解决方案。然而SOA中的核心:服务,却和这个自称是企业级的Java Bean的EJB没有什么太大的关系。众所周知,SOA里的服务一般是指Web Services。而实现Web Services的方式很多,如果使用Java实现,一般是使用普通的Java Bean来包装成Web Services。最多也就是使用个无状态的Session Bean。而EJB的其它功能,尤其是强大的实体Bean,却很少使用。这不能不说,EJB已经越来越名不副实了。

 查看全文

Java开发王者首部曲 : JBuilder 2007

发表人:xuniji123 | 发表时间: 2006年十一月20日, 19:28

Java开发王者首部曲 : JBuilder 2007

JBuilder的发展史说起来并不顺畅,从早期JBuilder 1~3版本在Java开发工具竞争场中苦苦追赶对手,到JBuilder 4~8版本时期雄霸Java开发工具王者的宝座,JBuilder可以说是在备尝艰辛之后才拥有光荣的Java开发工具王朝。但是许多人并不知道JBuilderBorland内部的定位非常奇怪,也就是因为这个定位让JBuilder9之后的版本逐渐被其他Java开发工具夺去其第一的地位。这个故事要从JBuilder成功地成为第一的Java开发工具之后说起。

原来在数年前当JBuilder 8打下天下之后,Borland开始走向ALM的市场。由于JBuilder在当时是举世皆知的Borland成名工具,因此当Borland决定开发ALM产品系列时,希望使用Java技术,并且希望能够和JBuilder连接在一起,好借助当时JBuilder在企业的影响力而能够顺利地把BorlandALM产品线打入企业市场。所以当时JBuilderBorland内部被归属为ALM部门的产品,而不属于开发工具部门的产品。

由于JBuilder肩负了ALM的重大任务,在随后的版本中,JBuilder的功能大都是为了与ALM产品连接以及支持最新的EJB服务器,因此,JBuilder R&D花费了大量的时间集成Borland ALM产品,更新使用最新的JDK和各厂商的EJB服务器,几乎把所有精力都放在企业级的应用。然而不幸的是,那时正是开源码和各种Java开源框架蓬勃发展的时期,Java开发者最需要的是Java开发工具能够支持这些最新、最重要的Java框架和Java技术,JBuilder却在Borland错误的定位下逐渐失去其领导地位。不过,虽然在这个时期JBuilder错失了大多数开发人员需要的功能,但是我个人认为JBuilder唯一在开发者需求方面最成功的地方就是集成了Together的强大建模能力,以及能够对于模型/程序码进行稽核和度量的功能,这是任何其他Java开发工具所不能企及的。

2006年是JBuilder转机的一年,因为JBuilder终于脱离了Borland而正式成为CodeGear公司的主力Java开发工具。CodeGear终于能够指正Borland犯下的错误,让JBuilder有机会重返Java开发工具王者的地位,主角就是JBuilder 2007

是什么使JBuilder 2007能够再次成为Java开发工具的首选? 现在版本的JBuilder有什么过人之处以及比不上的地方? 答案就是JBuilder有无人能及的建模和企业级的开发功能,例如JBuilderEJB开发功能。表现不如人意的地方就是缺乏支持主流Java框架,例如HibernateSpringWeb方面的框架,以及充分支持开发人员生产力的功能,例如Build Java项目、追踪臭虫、项目管理等。

而目前EJB 3Java Persistence APIJPA)正如潮水般席卷Java开发社群,Hibernate 3.xOracleTopLink都开始支持JPAJBoss 4.xGlassFish/AppSever 9也都支持EJB 3.0的开发,因此JBuilder 2007的成功运算式就是:

完整建模能力 + 主流Java框架 + 强大EJB3/JPA开发能力 + 高生产力开发者功能

JBuilder 2007将充分而且完美地结合第一名的Java商业开发工具和Java开源框架/程序码成为第一个打通任督二脉的崭新Java开发工具。例如在JBuilder 2007中我可以建立可视化EJB 3开发项目,可视化JPA开发项目,Hibernate/Spring项目,Tapestry项目,Java建模项目等,JBuilder 2007支持的Java相关开发项目绝对是第一的。例如下图就是笔者在JBuilder 2007中使用JBoss 4.x + Hibernate 3.x + InterBase 2007进行可视化EJB 3.0的项目开发:

11281130我将代表公司分别在北京和上海举办JBuilder 2007的发布会,使用Java开发的朋友将有机会一见最强大的新时代Java开发工具 JBuilder 2007。在这个发布会中我将介绍JBuilder的技术发展史,JBuilder 2007的技术架构,令人惊叹的新功能以及JBuilder未来的发展路线图,不管您目前是否使用JBuilder,您都需要看看这个即将震撼Java开发工具界的王者。对于大陆的朋友,您可以在下面的URL中找到相关资讯:

http://www.csdn.net/subject/borland/index.html

CodeGearJBuilder会成功地重返顶级Java开发工具之巅吗? 我想这是有机会的,CodeGear也有决心做到。从CodeGear的第一个推出版本JBuilder 2007看来,这个目标似乎已经不远了。现在连我这个以前不常使用JBuilder的人都愈来愈喜欢JBuilder 2007了,最近一段时间居然发现花在JBuilder 2007集成开发环境中的时间比花在BDS 2006都多了,呵呵,这当然是因为我非常喜欢EJB 3/JPAHibernate 3.x,现在JBuilder 2007是支持这三个最新技术的最完整和强大的Java开发工具。

这篇介绍JBuilder 2007的文章只是第1篇,因为这篇文章的名称就是“首部曲”。在下一篇文章中我将会介绍如何使用JBuilder 2007开发EJB 3.0的应用程序,还将详细介绍如何使用JBoss 4.x + Hibernate 3.x + InterBase 2007+JBuilder 2007进行强大的可视化开发。


Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1390138

 查看全文

Valid XHTML 1.0 Strict and CSS. Powered by pLog
Design by Blog.lvwo.com