1、 一个 Jsp 初学者的学习过程(一)网友评论 0 条 转载到博客 2007-2-8 23:45:34 来源: 本站整理顶一下WEB 开发专业社区,阿里西西 WEB 开发。一个 Jsp 初学者的学习过程(一)TheUnforgiven前言从现在开始我要把我学习 Jsp 的过程写出来。这些东西都是我从书本、网络上搜集整理的,我把它们据为己有后写这样一篇总结供如我一样的初学者参考。请容许我在这里说一些和读者无关的话,对此不感兴趣的请直接跳到第一章或第二章。我在 2003 年七月大学毕业,这之前学了四年计算机专业,由于基本是属于文科学校的计算机专业,学校女生少男生多学习的风气极受影响,所以可以想象我
2、毕业时候的水平。在学校时学习的大多是枯燥的计算机理论知识,我虽知其有用,但实在不感兴趣,我感兴趣的是编码,于是学了一个学期的 pascal,又编了一个学期的 C(学 C的时候是热情高涨的,甚至教课的老师允许或者说支持我逃课回去编码),遇指针、链表,不成,弃之,转而学 C+,不半月,遇“对象”、“类”、 “继承”,不成,复弃之,终不成,无奈之下,日夜游戏,不思进取,不数载,毕业。这以后直至现在一直在一省直机关的信息中心工作,由于是“事业单位”,所以工作很闲,头半年学了两个月的 html,后又学一个月的Asp,由于缺少压力,最终都放弃了。直到我们单位开始了一个项目电子政务,我的境况有了转变。我们找
3、来了两家公司给我们开发软件,领导说让我跟一跟,学写东西,由于当年 C 给我的打击实在太大了,我已认定自己不是那块料,是不具有学程序的天赋的,所以有些不情愿,但是终于由于太闲而且又不甘心自己“一点技术含量都没有”,最终选择了学习 Jsp。我找给我们开发软件的一个程序员朋友,向他要来了 Tomcat、jsdk 和盗版的 Oracle,编写平台就先暂时用我比较熟悉的 Dreamweaver,英文也差,就没用 Jbuilder、Jcreator 什么的,至于资料,没有,只有网络,我就这样开始了我的 Jsp 之旅。我没想到的是当年学的那一点点 C、html、Asp 让我不怎么费力的就走进(近)了 Jsp
4、 的大门,这速度至少出乎了我的意料。值得说明的一点是:我学 Jsp 完全是从实例入手,这之前我的相关理论知识基本为零,所以我在对代码的理解上(很大程度表现在注释上)是使用自己的“土语”的,而不是“ 术语”。我的原则是这篇文字能够让和我一样的初学者能够看懂。对于一个毫无基础的人来说,你对他说“类”、“对象”、“ 接口”、“继承”这些名词,他是无法理解的,因为它们太抽象,所以我必须通过实例和不怎么规范的语言使它们具体化一些。由于我的水平实在有限,可能会出现很多错误,尤其在对某些“代码”的理解上,但是我勇于拿出板砖,希望有热心的高手使劲扔玉_这是我的邮箱:。最后,感谢互联网及在其上分享自己经验的程序
5、员、我的单位的领导、同事、程序员朋友孙罡、大学的朋友彭涛等。第一章 配置服务器环境Jsp 全称是 Java Server Pages(而不是 JavaScript 的缩写,JavaScript是使用 Java 语言的一种脚本语言),用我的话说,它就是一堆使用于网页浏览器上的代码(或者说代码规范),从这个角度讲和 Asp类似。它并不是一种编程语言,但是它需要一种编程语言来编写其中的程序,正如 Asp 使用 VB 作为编程语言一样,Jsp 使用的是 Java语言。安装软件:既然 Jsp 使用 Java,那么我们的服务器操作系统里当然要有相应的Java 环境,否则我们怎么使用 Java 提供的“库函
6、数”呢?JDK 就是这个东西,我们可以从 SUN 公司的网站上下载它,先把它安装到操作系统(我的操作系统是 Windows XP Professional SP2)中,我的安装目录是:D:j2sdk1.4.2_07,装完之后我们还需要进行配置,这一步在下面再说。我们还需要安装 Web 服务器,我们初学者一般可以选用 Tomcat 作为 Jsp 的 Web 服务器。 Web 服务器是什么东西?假如你对 Asp 有一点了解的话,你就会知道 IIS 这东西IIS 就是 Asp 的 Web 服务器,那么 Tomcat 对于 Jsp 来说,它就相当于 Asp 的 IIS。我使用的是Tomcat5.0,你
7、也可以使用更高的版本,注意在安装它之前你得先安装 JDK,我的 Tomcat 的安装目录是:D:Tomcat 5.0。配置:右键“我的电脑”-“ 属性 ”-“高级”-“环境变量”,这里面有用户变量和系统变量之分,说实话,用户变量主要起什么作用我不是很清楚,但是系统变量一定是很重要的,通过“新建”或“编辑之后”,我的相关的用户变量是这样的:classpath.;d:j2sdk1.4.2_07libtools.jar;d:j2sdk1.4.2_07libdt.jar;java_homed:j2sdk1.4.2_07pathd:j2sdk1.4.2_07bin;d:j2sdk1.4.2_07我的相关
8、的系统变量是:CATALINA_HOMEd:Tomcat 5.0classpath.;d:j2sdk1.4.2_07libtools.jar;d:j2sdk1.4.2_07libdt.jar;JAVA_HOMEd:j2sdk1.4.2_07Pathd:j2sdk1.4.2_07bin;d:j2sdk1.4.2_07;(把这句添加进去,而不是最终的值)TOMCAT_HOMEd:Tomcat 5.0Tomcat 在安装完之后在 Windows 系统的“服务”中会多一项“Apache Tomcat”的服务,它是自动的,你可以给它改成手动,这样在不使用的时候可以节省一些系统资源了。既然改成手动了,那么
9、怎么启动它呢?找这两个文件:D:Tomcat 5.0binstartup.bat 和 D:Tomcat 5.0binshutdown.bat,前一个就是启动 Tomcat 的批处理文件了,而后一个就是关闭的。你在安装 Tomcat 的时候可能会发现安装过程中有一个地方可以改端口号,默认是“8080” ,而当你在调试程序时你就要注意这个端口号了。在上面的配置都完成以后,你可以看看是否成功了:先开启Tomcat 服务器,然后在网页地址栏里输入:http:/localhost:8080/(客户端和服务器是同一台机器),安装成功的话你会看见 Tomcat 的欢迎界面。你也可以使用你的 IP 或是机器名
10、,比如我的 IP 是 172.16.20.30,机器名是 ringz,那么输入以下两种形式都是可行的:http:/172.16.20.30:8080/,http:/ringz:8080/。 一个 Jsp 初学者的学习过程(二)TheUnforgiven第二章 轻度接触 server.xml现在开始编写我们的第一个.jsp 文件了,代码如下:-这个文件是在页面输出一句话,你甚至可以用记事本来编写,但主要的问题是,这个文件(比如叫 test.jsp)它放在哪里。Tomcat 的默认目录好象是 D:Tomcat 5.0webappsjsp-examples,早期 4.1 版本目录是 examples
11、,把这个文件放到 jsp-examples 下,开启 Tomcat服务器,在地址栏输入:http:/ringz:8080/jsp-examples/test.jsp。现在要说的问题是:我不想用 8080 这个端口,直接用http:/ringz/jsp-examples/test.jsp 多好啊。这首先要取决你的 80 端口是否被占用,一般来说你的机器里没有安装 IIS 或者停掉 IIS 服务,80 端口就可以使用。具体的修改方法如下:打开这个文件 D:Tomcat 5.0confserver.xml,你会找到这样一段代码:把 port=“8080“改成 port=“80“,保存文件,重启 To
12、mcat 服务器,如果能够启动,说明可以使用 80 端口了;而要是 Tomcat 启动窗口一闪即关掉,就说明 80 端口已经被占用了(这个判断的前提是该server.xml 文件没有错误,如果有其他错误的话,比如少一个 “/”,也会这样)。按照此方法你可以改成其他闲置的端口,比如说,给我们做软件的公司在测试的时候使用的是 7988 端口。除了 80 端口,其他端口都要在地址栏注明,80 之所以不用是因为它是 http 协议的默认端口。接下来的问题是:我不想把写好的.jsp 文件放在 D:Tomcat 5.0webappsjsp-examples 下怎么办?这同样需要修改 server.xml
13、文件:假如你的.jsp 文件都放在 e:MyJsp 下,则在该文件的之间加入这样一段代码:(注意要和文件名的大小写要一致)。这样你可以在地址栏输入 http:/ringz/MyJsp/test.jsp(同样要注意大小写要一致)来运行这个文件。如果改成:,这样在地址栏里输入 http:/ringz/test.jsp 就行了。你感兴趣的话可以看看只输入 http:/ringz 后页面是什么样的。现在你可能会有这个想法:我的一个系统(或者叫一个站点)有一个固定的入口文件,比如叫 login.htm,我希望只在地址栏输入http:/ringz 就可以打开这个文件,这怎么办?这个我们可以通过修改和 se
14、rver.xml 处于同目录下的 web.xml 文件来实现:一般在这个文件的最下有这样一段代码:index.htmlindex.htmindex.jsp你只需要将其中一个改成login.htm就行了。对于这个 web.xml 文件我们以后还会提到,就先不多说了。记住一点:server.xml 或者 web.xml 文件在修改后一定要重启Tomcat 服务器才行。一个 Jsp 初学者的学习过程(三)TheUnforgiven第三章 连接数据库在最初几天我写了几个页面之后,我决定要做一个留言板之类的东西:有登录验证、注册、发表文章、浏览文章、管理文章、管理用户等这些功能。首先的登录验证这个不难,
15、但是有个问题:需要连接数据库了。于是我开始查找资料,并安装了 Oracle 数据库(对于Oracle 数据库的一些最基本的知识我就不在这里说明了,但是需要注意的两点是:一、安装完成后就不要再改变你的机器名,一旦改了再改回来,数据库也用不了;二、安装完后不要使用 Windows 优化大师的清理注册表垃圾的功能,它会删掉一个有用的注册表信息导致 Oracle 的监听无法启动) ,最后写了这个文件:-link.jsp-成功!“);/try 结束catch(Exception e)/当 try 里运行出错时,运行 catch 里的内容out.println(e);/输出错误信息 finally/不论是
16、否出错、结果怎样,都要运行 finally 里的内容/向下为关闭数据库连接if (rs!=null)rs.close();if (stmt!=null)stmt.close();if (con!=null)con.close(); %-Class.forName(CLASSFORNAME);con=DriverManager.getConnection(SERVANDDB);这两句无疑是很重要的,可是 CLASSFORNAME、SERVANDDB 这两个变量是什么呢?它们都来自这句里的 include.inc 文件,该文件与 link.jsp 在同一目录下。-include.inc-假如你用的
17、是 Oracle 的数据库的话,现在你运行这个文件还是会出错,因为 Tomcat 服务器找不到 Oracle 的 JDBC 驱动,你需要甲骨文(oracle)公司提拱的一个包:classes12.jar,你可以在D:oracleora92jdbclib 下找到它,然后把它放到 D:Tomcat 5.0commonlib 下,现在,应该可以了。本章最后的话:向程序员方向发展有两点无疑是很重要的:1、试着读懂代码;2、亲自动手写,然后亲自调试。一个 Jsp 初学者的学习过程(四)TheUnforgiven第四章 第一个 Javabean一、先看看如何取当前时间并显示的代码:-格式化成“yyyy-M
18、M-dd HH:mm:ss“格式的日期时间:未经格式化的 String 格式的日期时间: 未经格式化的 Date 格式的日期时间:-页面的输出内容:格式化成“yyyy-MM-dd HH:mm:ss“格式的日期时间:2005-03-17 09:55:40 未经格式化的 String 格式的日期时间: Thu Mar 17 09:55:40 CST 2005 未经格式化的 Date 格式的日期时间:Thu Mar 17 09:55:40 CST 2005通常我们需要的是这种格式化后的时间:2005-03-17 09:55:40。现在有这样一个问题:“2005-03-17 09:55:40”是一个字
19、符串,有些时候我们需要在这个字符串里提取出年、月、日等的相关信息,怎么办呢?看下面的代码:-规则的字符串-规则的字符串(年 4 位,月 2 位,日 2 位,中间用字符“-” 分隔):原字符串为:“);String year=date.substring(0,4);/取第 0+1 位至第 4 位String month=date.substring(5,7);/取第 5+1 位至第 7 位String day=date.substring(8,10);/取第 8+1 位至第 10 位out.println(“year=“+year+“,month=“+month+“,day=“+day);%-从
20、上面的代码我们可以看出来:这只能针对规则的字符串(年 4 位,月 2 位,日 2 位) ,要是不规则的呢?年可能 2 位也可能 4 位,月和日可能 1 位也可能 2 位,怎么办?通过对上面的代码修改,可以得到下面的通用的代码(这个“通用”有一个前提 年月日之间必须以“-”分隔):-不规则的字符串-不规则的字符串(年、月、日长度不一定,中间用字符“-”分隔):原字符串为:“);int a=date.indexOf(“-“);/求第一个“-”的位数int b=date.lastIndexOf(“-“);/求最后一个“-”的位数int len=date.length();/求字符串的长度year=d
21、ate.substring(0,a);/取第一个“-”前的字符串month=date.substring(a+1,b);/取两个“-”之间的字符串day=date.substring(b+1,len);/取最后一个“-” 以后的字符串out.println(“year=“+year+“,month=“+month+“,day=“+day);%-现在这个问题解决了。可是我们会想到:每次需要对一个表示年月日的字符串进行分割的时候都需要在.jsp 页面里写上这么一段代码,不但麻烦而且使页面显得混乱,能不能以一种看起来更清晰的方法解决这个问题呢?当然可以了,用 javabean 就行了。二、第一个 j
22、avabean什么是 javabean?我在接触到这个问题时苦恼不已,因为我始终无法理解这个概念,直到我相继写了几个之后,我蓦然发现:它不就是一个类吗?!现在,我们先不去管什么是类,先看下面的这个javabean:-DateBean.java-/该 bean 能够从 jsp 文件中得到一个表示年月日(用“-” 分隔)的字符串,然后返回给 jsp 文件分别表示年、月、日的字符串package ringz.javabeans; /ringz.javabeans 是我的包名,我自己写的javabean 都在这个包里public class DateBean /这个 class 的名字是 DateBe
23、an,那么这个javabean 文件的名就必须叫:DateBean.javaprivate String dateStr;private String year;private String month;private String day;/public void setDateStr(String str) /私有变量 dateStr 的 set 方法this.dateStr=str;public String getDateStr() /私有变量 dateStr 的 get 方法return dateStr;public String getYear()/得到年的字符串int a=dat
24、eStr.indexOf(“-“);/求第一个“-”的位数year=dateStr.substring(0,a);/取第一个“-”前的字符串return year;public String getMonth()/得到月的字符串int a=dateStr.indexOf(“-“);/求第一个“-”的位数int b=dateStr.lastIndexOf(“-“);/求最后一个 “-”的位数month=dateStr.substring(a+1,b);/取两个“-”之间的字符串return month;public String getDay()/得到日的字符串int b=dateStr.las
25、tIndexOf(“-“);/求最后一个 “-”的位数int len=dateStr.length();/求字符串的长度day=dateStr.substring(b+1,len);/取最后一个 “-”以后的字符串return day;-一个 javabean 里最主要的是 set 和 get 方法:set 方法用于从.jsp 页面向 javabean 传值;get 方法用于从 javabean 向.jsp 页面传值。下面看.jsp 页面如何使用这个 javabean:-ymd_use_bean.jsp-使用 javabean 从字符串中取得年月日信息“);out.println(“year=
26、“+ymd.getYear()+“,month=“+ymd.getMonth()+“,day=“+ymd.getDay();catch(Exception e)%请在下边的文本框中输入代表年月日的字符串,格式:XXXX-XX-XX,其中代表年、月、日的位数可以不限定。(必须使用两个“-”分开,如:1999-9-29)-你在这段代码里能看到 get 方法,可是 set 方法呢?怎么没看见?这里面的玄机在之间和 form 里的这句:,这里我不想重点说明.jsp 文件如何引用 javabean,你不清楚的话请查阅其他资料。另外在这里提一个小技巧你自己试一试:把 try 和 catch 的内容去掉,看
27、看结果是什么样的;把 catch 的内容改成这样:catch(Exception e)out.print(e);再看看结果是什么样的。然后自己分析一下为什么会这样。这是一个我经常使用的小技巧,不知道别人是不是也用这种方法来解决这种问题。上面已经说了 javabean 就是一个类,下面我要用自己的话说一下什么是类,我是怎么理解类这个概念(理解的不一定准确,还请高手们给予指正,免的误人子弟_!):先是想起一个笑话:说有一种机器,从机器的一侧放进一头猪,机器的另一侧就会出香肠。引申一下。这台机器在一个仓库里,这个仓库里还有一台能自动出猪毛和一台出猪皮的机器。现在这个仓库就可比做一个类,而每台机器就是
28、一个方法,因为这个仓库是只针对猪的仓库,所以这个仓库一定在 java.pig 这个包(java 的 API说白了就是类库或者按照 C 的说法就是函数库 里有很多类,这些类是分类存放的,每一个分类称做一个包,比如,和输入输出有关的类就放在 java.io 包里,和绘制图形相关的类就放在 java.awt 包里)里面,我们给这个仓库起名叫 PigFactory,这就是类名。现在拿来一头猪:Japanese 属于类 Pig,先通过和 PigFactory 同名的构造函数 PigFactory()为处理这头猪新建一个实例:java.pig.PigFactory pf = new java.pig.Pi
29、gFactory();现在我们可以通过这个实例对这头猪进行操作了 由于我们只想要它的皮,那就使用出皮的机器就行了,这台机器作为一个方法叫做 getSkin(),那么:Skin pigskin = pf.getSkin(Japanese);猪皮(pigskin)出来了,并且运送出仓库,它属于类“皮”(Skin)了。类似的,还有一些专门处置牛、羊的仓库,它们也有自动出皮的机器,所以也是方法:getSkin(),这也就是为什么我们会发现很多不同的类里边有相同名称的方法,如:getString 方法。我们可以发现:这台自动出皮的机器是如何工作的,我们并不关心,我们所关心的只是怎样使用它。我们也可以自己
30、开发一个类(或者javabean) ,它的工作原理和 SUN 给我们开发好的 API 里的类是基本一致的。在使用时我们所关心的仅仅是如何把值传给它和如何从它那里得到值。以上是我的理解,可能有很多不确切的地方,希望大家指正。说了这很多废话以后,你可能想问:我们上面写的 javabean 现在可以用了吗?还不行。刚刚我们写好的是一个.java 文件,必须把它编译成.class 文件以后 Jsp 才能调用它。下面说怎么编译,由于我现在没有使用专门的 java 开发工具(如 JBuilder) ,所以只能使用我们安装的 JDK(java 2 sdk)所提供的编译工具:把 DateBean.java 这
31、个文件放到 C:下, “开始”-“ 运行”-“cmd 命令”,在开启的窗口中将当前路径改为 C:,然后输入:javac DateBean.java,回车,如果窗口中没有提示出错的话, OK,编译成功了。这时你会发现和 DateBean.java 处于同目录的地方多了一个DateBean.class 文件,就是它了。现在的问题是它应该放在哪了。由于是我自己写的 javabean,所以我不打算把他们和 Tomcat 自带的放在一起:之前我们定义了自己的根目录:e:MyJsp,在它的下面新建一个 WEB-INF 文件夹(注意大小写) ,其下再建一个 classes 文件夹,放在这里就行了。当然你可以
32、专门为你自己开发的 javabean 做一个包就像 SUN 那样 我自己的包名叫 ringz.javabeans,所以我在 classes 文件夹下建了一个 ringz 的文件夹,里面再建一个javabeans 文件夹,然后把我开发的.class 文件放到这里。这时使用的时候要注意包名:。本章需要注意的当然是每次改完后的.java 文件都要重新编译成.class文件,而且使用.class 文件时要重启 Tomcat 服务器。一个 Jsp 初学者的学习过程(五)TheUnforgiven第五章 分页功能的实现在我逐步把我的留言板的功能完善的同时,我渐渐熟悉了对数据库的操作,这时我发现留言信息的目
33、录越来越长了,我需要实现一个分页功能了,最初我尝试自己解决这个问题:1、我应该把它的关键部分封装成一个 bean,使它尽可能的能够重用;2、通过资料了解有两种数据库查询方案:一、一次取得所有资料,然后在指定的页显示指定的资料;二、分次查询数据库,每次只获得本页的数据。考虑到数据库中记录数越多,方案一所占的服务器资源就越多(将所有的记录都放到内存中,假如有 50 万条记录的话$*%#) ,所以应该采用方案二;3、首先要知道目标数据库里共有多少条记录(select count(*) from 表名) ,然后确定每页显示多少条记录,再根据它计算一共分多少页(最大页数)显示,这部分由 bean1(在我
34、的代码里就随便起个名叫PageBean)实现;获取当前要显示第几页的请求,查询本页要显示哪些条记录,将每条记录的内容作为一组数据返回给显示页面,这部分由 bean2(CountBean)实现;显示页面(.jsp 文件)显示各条记录的内容。到这里我发现有两个难点:(1)查询从第 m 条到第 n 条记录的 SQL 语句不会写,通过在网上查找资料,这个问题得到解决;(2)bean2 返回给显示页面的值是个二维的数组,这个数组怎么传呢?于是不得不上网翻书查找资料,最终发现由 Vector(向量)来解决,由于没有工具书,无法针对 Vector 进一步学习,就只好分析代码,好在最后分析明白了到目前为止,也
35、只是明白了那段代码,仍然无法做到能够应用。下面是这三个文件的代码:-PageBean.java-/该 bean 用于实现分页功能时得到总的记录数和最大的页数package ringz.javabeans;import java.io.*; import java.sql.*;public class PageBeanprivate int maxRowCount;/最大记录数private int onePageRowCount;/每页显示的记录数private int maxPageCount;/最大页数private String classforname;private String s
36、ervanddb;private String sql;/得到关于目标数据库的搜索条件public void setSql(String s1,String s2,String sql)this.classforname=s1;this.servanddb=s2;this.sql=sql;/得到 onePageRowCountpublic void setOnePageRowCount(int counts)onePageRowCount=counts;/计算 maxRowCount 并返回public int getMaxRowCount()throws ExceptiontryClass.
37、forName(classforname);/载入驱动程式类别Connection con=DriverManager.getConnection(servanddb);/建立数据库连接Statement stmt=con.createStatement();/建立 Statement 变量ResultSet rs=stmt.executeQuery(sql);if (rs.next()maxRowCount=rs.getInt(1);rs.close();stmt.close();con.close();return maxRowCount;/trycatch (Exception e) e
38、.printStackTrace();throw e;/getMaxRowCount()/根据 maxRowCount 和 onePageRowCount 计算出 maxPageCount 并返回public int getMaxPageCount()if (maxRowCount%onePageRowCount=0)maxPageCount=maxRowCount/onePageRowCount;elsemaxPageCount=maxRowCount/onePageRowCount+1;return maxPageCount;-CountBean.java-/该 bean 用于接收具体页数
39、然后返回该页应显示的记录package ringz.javabeans;import java.util.*;import java.io.*; import java.sql.*;public class CountBeanprivate int pageNum;/当前是第几页private String classforname;private String servanddb;private String sql;Vector v=new Vector();/得到关于目标数据库的搜索条件public void setSql(String s1,String s2,String sqlst
40、r)this.classforname=s1;this.servanddb=s2;this.sql=sqlstr;/得到 pageNumpublic void setPageNum(int pagenum)this.pageNum=pagenum;/返回结果public Vector getResult(String listname)throws Exceptionint num=listname.length;/得到数组的长度String listName=new Stringnum;/定义一个大小为 num 的 string 型数组for(int i=0;i分页的实现 =“+min+“;
41、/*按需要改变page2.setSql(s1,s2,sqlstr);if(maxRowCount0)out.println(“共有“+maxRowCount+“条记录 ,每页显示“+onePageRowCount+“条。“);%标题作者日期“);out.println(“+title+“);out.println(“+name+“);out.println(“+time+“);out.println(“);%“+pageNum+“页 共“+maxPageCount+“页“);if (maxPageCount1)/不只有一页if (pageNum=1)/当前页是首页out.print(“首页 | 上一页 | 下一页 | “);