第5章JSP与JavaBean

本章导读 
主要内容 
 编写和使用JavaBean
 获取和修改bean的属性 
 bean的辅助类
 JSP与bean结合的简单例子

难点
 获取和修改bean的属性

关键实践 
 记忆测试

在谈论组件之前让我们看一个常见的事——组装电视机。组装一台电视机时,人们可以选择多个组件,例如电阻、电容、显像管等,一个组装电视机的人不必关心显像管是怎么研制的,只要根据说明书了解其属性和功能就可以了。不同的电视机可以安装相同的显像管,显像管的功能完全相同。如果一台电视机的显像管发生了故障,并不会影响其他的电视机; 
如果两台电视机安装了一个共享的组件——天线,当天线发生了故障,两台电视机就会受到同样的影响。

按照Sun公司的定义,JavaBean是一个可重复使用的软件组件。实际上JavaBean是一种Java类,通过封装属性和方法成为具有某种功能或者处理某个业务的对象,简称bean。由于JavaBean是基于Java语言的,因此JavaBean不依赖平台,具有以下特点: 

  可以实现代码的重复利用。
 易编写、易维护、易使用。
 可以在任何安装了Java运行环境的平台上的使用,而无须重新编译。

JSP页面可以将数据的处理过程指派给一个或几个bean来完成,即JSP页面调用这些bean完成数据的处理,并将有关处理结果存放到bean中,然后JSP页面负责显示bean中的数据。例如使用Java程序片或某些JSP指令标记显示bean中的数据(见5.2节),即JSP页面的主要工作是显示数据,不负责数据的逻辑业务处理,如图5.1所示。



图5.1JSP+JavaBean


本章在webapps目录下新建一个Web服务目录ch5,除非特别约定,本章例子中涉及的JSP页面均保存在ch5目录中。创建bean的类的字节码文件须按要求存放,因此要在ch5目录下建立目录结构\ch5\WEBINF\classes(WEBINF字母大写)。
5.1编写和使用JavaBean
5.1.1编写JavaBean



视频讲解

编写JavaBean就是编写一个Java的类,所以只要会写类就能编写一个JavaBean。这个类创建的一个对象称为一个JavaBean,简称bean,分配给bean的变量(成员变量),也称bean的属性。为了能让使用bean的应用程序构建工具(比如Tomcat服务器)使用JSP动作标记知道bean的属性和方法,在类的命名上需要遵守以下规则: 

(1) 如果类的成员变量(也称bean的属性)的名字是xxx,那么为了获取或更改bean的属性的值,类中必须提供两个方法: 
 getXxx(),用来获取属性xxx。
 setXxx(),用来修改属性xxx。
也就是方法的名字用get或set为前缀,后缀是将属性(成员变量)名字的首字母大写的字符序列。




(2) 类中定义的方法的访问权限都必须是public的。
(3) 类中必须有一个构造方法是public、无参数的。

下面我们编写一个创建bean的Java类,并说明在JSP中怎样使用这个类创建一个bean。要求创建bean的类带有包名,即Java源文件须使用package语句给出包名,例如: 


package gping;



或


package tom.jiafei;



以下是用来创建bean的Java源文件。
Circle.java(负责创建bean)


package tom.jiafei;

public class Circle {

double radius;

public Circle() {

radius=1;

}

public double getRadius() {

return radius;

}

public void setRadius(double newRadius) {

radius=newRadius;

}

public double circleArea() {

return Math.PI*radius*radius;

}

public double circleLength() {

return 2.0*Math.PI*radius;

}

}



将上述Java文件保存为Circle.java。注意,保存Java源文件时,“保存类型”选择为“所有文件”,将“编码”选择为“ANSI”。
 5.1.2保存bean的字节码


视频讲解

为了使JSP页面使用bean,Tomcat服务器必须使用相应的字节码文件创建一个对象,即创建一个bean。为了让Tomcat服务器能找到字节码文件,字节码文件必须保存在特定的目录中。

ch5 \WEBINF\classes目录下,根据包名对应的路径,在classes目录下再建立相应的子目录。例如,包名tom.jiafei对应的路径是tom\jiafei,那么在classes目录下建立子目录结构tom\jiafei,如图5.2所示。


图5.2字节码文件的存放位置


将创建bean的字节码文件,例如Circle.class,复制到\WEBINF\classes\tom\jiafei中。为了调试程序方便,可以直接按照bean的包名将bean的源文件(例如Circle.java)保存在\WEBINF\classes\tom\jiafei目录中,然后用命令行进入tom\jiafei的父目录classes(不要进入tom或jiafei目录)编译Circle.java: 


classes>javac tom\jiafei\Circle.java





视频讲解


5.1.3创建与使用bean
 使用bean

使用JSP动作标记useBean加载使用bean,语法格式是: 


<jsp:useBean id="bean的名字" class="创建bean的类" scope="bean有效范围"/>



或


<jsp:useBean id="bean的名字" class="创建bean的类" scope="bean有效范围">

</jsp:useBean>



例如: 


<jsp:useBean id="circle" class="tom.jiafei.Circle" scope="page" />



需要特别注意的是,其中的“创建bean的类”要带有包名,例如: 


class="tom.jiafei.Circle"



  bean的加载原理

当JSP页面使用JSP动作标记useBean加载一个bean时,Tomcat服务器首先根据JSP动作标记useBean中id给出的bean名字以及scope给出的使用范围(bean生命周期),在Tomcat服务器管理的pageContent内置对象中查找是否含有这样的bean(对象)。如果这样的bean(对象)存在,Tomcat服务器就复制这个bean(对象)给JSP页面,就是常说的Tomcat服务器分配这样的bean给JSP页面。如果在pageContent中没有查找到JSP动作标记要求的bean,就根据class指定的类创建一个bean,并将所创建的bean添加到pageContent中。通过Tomcat服务器创建bean的过程可以看出,首次创建一个新的bean需要用相应类的字节码文件创建对象,当某些JSP页面再需要同样的bean时,Tomcat服务器直接将pageContent中已经有的bean分配给JSP页面,从而提高JSP页面
bean的使用效率。

注:  如果修改了字节码文件,必须重新启动Tomcat服务器才能使用新的字节码文件。



 bean的有效范围和生命周期

scope的取值范围给出了bean的生命周期(存活时间),即scope取值决定了Tomcat服务器分配给用户的bean的有效范围和生命周期,因此需要理解scope取值的具体意义。下面就JSP动作标记useBean中scope取值的不同情况进行说明。 
(1) page bean。
scope取值为page的bean称为page bean,page bean的有效范围是用户访问的当前页面,存活时间直到当前页面执行完毕。Tomcat服务器分配给每个JSP页面的page bean是互不相同的。也就是说,尽管每个JSP页面的page bean的功能相同,但它们占有不同的内存空间。page bean的有效范围是当前页面,当页面执行完毕,Tomcat服务器取消分配的page bean,即释放page bean所占有的内存空间。需要注意的是,不同用户(浏览器)的page bean也是互不相同的。也就是说,当两个用户同时访问同一个JSP页面时,一个用户对自己page bean的属性的改变,不会影响到另一个用户。
(2) session bean。

scope取值为session的bean称为session bean,session bean的有效范围是用户访问的Web服务目录下的各个页面,存活时间是用户的会话期(session)间,直到用户的会话消失(session对象达到了最大生存时间或用户关闭自己的浏览器以及服务器关闭,见4.3.1节)。如果用户访问Web服务目录多个页面,那么每个页面id相同的session bean是同一个bean(占有相同的内存空间)。因此,用户在某个页面更改了这个session bean的属性值,其他页面的这个session bean的属性值也将发生同样的变化。当用户的会话(session)消失,Tomcat服务器取消所分配的session bean,即释放session bean所占有的内存空间。需要注意的是,不同用户(浏览器)的session bean是互不相同的(占有不同的内存空间)。也就是说,当两个用户同时访问同一个Web服务目录,一个用户对自己session bean属性的改变,不会影响到另一个用户(一个用户在不同Web服务目录的session bean互不相同)。 

(3) request bean。
scope取值为request的bean称为request bean, request bean的有效范围是用户请求的当前页面,存活时间是从用户的请求
产生到请求结束。Tomcat服务器分配给每个JSP页面的request bean是互不相同的。Tomcat服务器对请求作出响应之后,取消分配给这个JSP页面的request bean。简单地说,request bean只在当前页面有效,直到响应结束。request bean存活时间略长于page bean的存活时间,原因是Tomcat服务器认为页面执行完毕后,响应才算结束。需要注意的是,不同用户的request bean的也是互不相同的。也就是说,当两个用户同时请求同一个JSP页面时,一个用户对自己request bean属性的改变,不会影响到另一个用户。

(4) application bean。
scope取值为application的bean称为application bean,application bean的有效范围是当前Web服务目录下的各个页面,存活时间直到Tomcat服务器关闭。Tomcat服务器为访问Web服务目录的所有用户分配一个共享的bean,即不同用户的application bean也都是相同的一个。也就是说,任何一个用户对自己application bean属性的改变,都会影响到其他用户(不同Web服务目录的application bean互不相同)。
图5.3是bean的有效期的示意图,图5.4是有效范围示意图。



图5.3bean的有效期



图5.4bean的有效范围





注:  当使用session bean时,要保证用户端支持Cookie。



例5_1中负责创建page bean的类是上述的Circle类,page bean的名字是circle。
例5_1
example5_1.jsp(效果如图5.5所示)


<%@ page contentType="text/html"%>

<%@ page pageEncoding="utf-8"%>

<HTML><body bgcolor=#ffccff>

<style>

#textStyle{

font-family:宋体;font-size:36;color:blue 

}

</style>

<HTML><body bgcolor=#ffccff>

<p id="textStyle">

<jsp:useBean id="circle" class="tom.jiafei.Circle" scope="page" />

<%--通过useBean标记,获得名字是circle的page bean --%>

圆的初始半径是: <%=circle.getRadius()%>

<%double newRadius =100;

circle.setRadius(newRadius);//修改半径

%>

<br>修改半径为<%= newRadius %>

<br><b>圆的半径是: <%=circle.getRadius()%>

<br><b>圆的周长是: <%=circle.circleLength()%>

<br><b>圆的面积是: <%=circle.circleArea()%>

</p></body></HTML>





图5.5page bean



例5_2使用id为girl的session bean,创建session bean的类仍然是上述的Circle.class。在例5_2的example5_2_a.jsp页面中,session bean的半径radius的值是1(如图5.6(a)所示),然后链接到example5_2_b.jsp页面,显示session bean的半径radius的值,然后将session bean的半径radius的值更改为1.618(如图5.6(b)所示)。用户再刷新example5_2_a.jsp或example5_2_b.jsp时看到的session bean的radius的值就都是1.618了(如图5.6(c)所示)。


图5.6session bean



例5_2
example5_2_a.jsp(效果如图5.6(a)(c)所示)


<%@ page contentType="text/html"%>

<%@ page pageEncoding="utf-8"%>

<HTML><body bgcolor=cyan>

<p style="font-family:宋体;font-size:36;color:blue"> 

<%--通过JSP标记,用户获得一个id是girl的session bean: --%>

<jsp:useBean id="girl" class="tom.jiafei.Circle" scope="session" />

<br>这里是example5_2_a.jsp页面。

<br>圆的半径是<%=girl.getRadius()%>

<br>单击超链接,到其他页面看圆的半径。

<a href="example5_2_b.jsp"><br>example5_2_b.jsp</a>

</p></body></HTML>



example5_2_b.jsp(效果如图5.6(b)所示)


<%@ page contentType="text/html"%>

<%@ page pageEncoding="utf-8"%>

<HTML><body bgcolor= #ffccff>

<p style="font-family:黑体;font-size:36;color:blue"> 

<%--用户的id是girl的session bean: --%>

<jsp:useBean id="girl" class="tom.jiafei.Circle" scope="session"/>

<i><br>这里是example5_2_b.jsp页面

<br>当前圆的半径是:  <%=girl.getRadius()%>

<% girl.setRadius(1.618);





%>

<br>修改后的圆的半径是<%=girl.getRadius()%></i>

<br>单击超链接,到其他页面看圆的半径。

<a href="example5_2_a.jsp"><br>example5_2_a.jsp</a>

</p></body></HTML>



例5_3中使用了id为boy的application bean。当第一个用户访问这个页面时,显示application bean的radius的值,然后把application bean的radius的值更改为2.718(如图5.7(a)所示)。当其他用户访问这个页面时,看到的application bean的radius的值都是2.718(如图5.7(b)所示)。


图5.7application bean



例5_3
example5_3.jsp(效果如图5.7(a)(b)所示)


<%@ page contentType="text/html"%>

<%@ page pageEncoding="utf-8"%>

<HTML><body bgcolor=#ffccff>

<p style="font-family:宋体;font-size:36;color:blue"> 

<jsp:useBean id="boy" class="tom.jiafei.Circle" scope="application" />

圆的初始半径是:<%=boy.getRadius()%>

<% boy.setRadius(2.718);

%>

<br><b>修改后的圆的半径是:<%=boy.getRadius()%>

</p></body></HTML>



5.2获取和修改bean的属性

使用useBean动作标记获得一个bean后,在Java程序片或表达式中bean就可以调用方法产生行为,如前面的例5_1~例5_3所示,这种情况下,不要求创建bean的类遵守setXxx和getXxx等规则(见5.1.1节)。获取或修改bean的属性还可以使用JSP动作标记getProperty、setProperty,这种情况下,要求创建bean的类遵守setXxx和getXxx等规则,当JSP页面使用getProperty、setProperty标记获取或修改属性xxx时,必须保证bean有相应的getXxx和setXxx方法,即对方法名字的命名有特殊的要求。下面讲述怎样使用JSP的动作标记getProperty、setProperty去获取和修改bean的属性。
 5.2.1getProperty动作标记


视频讲解

使用getProperty动作标记可以获得bean的属性值,并将这个值用串的形式发送给用户的浏览器。使用getProperty动作标记之前,必须使用useBean动作标记获得相应的bean。
getProperty动作标记的语法格式是: 


<jsp:getProperty name="bean的id " property="bean的属性" />



或


<jsp:getProperty name="bean的id "property="bean的属性">

</jsp:getProperty>



其中,name取值是bean的id,用来指定要获取哪个bean的属性的值,property取值是该bean的一个属性的名字。

注:  
让request调用setCharacterEncoding方法设置编码为UTF8,以避免显示bean的属性值出现乱码现象。



 5.2.2setProperty动作标记


视频讲解

使用setProperty动作标记可以设置bean的属性值。使用这个标记之前,必须使用useBean标记得到一个相应的bean。

setProperty动作标记可以通过两种方式设置bean属性值。

(1) 将bean属性值设置为一个表达式的值或字符序列。




<jsp:setProperty name="bean的id " property="bean的属性" 

value="<%=expression%>"/>

<jsp:setProperty name="bean的id " property="bean的属性" 

value="字符序列"/>



value给出的值的类型要和bean的属性的类型一致。

(2) 通过HTTP表单的参数值来设置bean的相应属性值。

① 用form表单的所有参数值设置bean相对应属性值的使用格式如下: 


<jsp:setProperty name="bean的id的名字"property="*" />



在setProperty标记的上述用法中不具体指定bean属性值将对应form表单中哪个参数指定的值,系统会自动根据名字进行匹配对应,但要求bean属性的名字必须在form表单中有名称相同的参数名字相对应,Tomcat服务器会自动将参数的字符串值转换为bean相对应的属性值

② 用form表单的某个参数的值设置bean的某个属性值的使用格式如下: 


<jsp:setProperty name="bean的名字"property="属性名"param="参数名" />



setProperty标记的上述用法具体指定了bean属性值将对应表单中哪个参数名(param)指定的值,这种设置bean的属性值的方法,不要求property给出的bean属性的名字和param给出的参数名一致,即不要求bean属性的名字必须和表单中某个参数名字相同。

当把字符序列设置为beans的属性值时,这个字符序列会自动被转化为bean的属性类型。Java语言将字符序列转化为其他数值类型的方法如下。
 转化到int: Integer.parseInt(Sting s)
 转化到long: Long.parseLong(Sting s)
 转化到float: Float.parseFloat(Sting s)
 转化到double: Double.parseDouble(Sting s)
这些方法都可能发生NumberFormatException异常,例如,当试图将字符序列ab23转化为int型数据时就发生了NumberFormatException。

注:  用form表单设置bean的属性值时,只有提交了表单,对应的setProperty标记才会被执行。



例5_4使用Goods类创建request bean。example5_4_a.jsp通过form表单指定example5_4_a.jsp和example5_4_b.jsp中的request bean的name和price属性值。
example5_4_a.jsp和example5_4_b.jsp使用getProperty动作标记以及bean调用方法两种方式显示request bean的name和price属性值。

例5_4
JavaBean

将Goods.java保存在\ch5\WEBINF\classes\tom\jiafei中,用命令行进入tom\jiafei的父录classes,
按如下格式编译Goods.java: 


classes>javac tom\jiafei\Goods.java



Goods.java(负责创建bean)


package tom.jiafei;

public class Goods{

String name="无名";

double price=0;

public String getName() {

return name;

}

public void setName(String newName){

name=newName;

}

public double getPrice() {

return price;

}

public void setPrice(double newPrice) {

price=newPrice;

}

}



JSP页面
example5_4_a.jsp(效果如图5.8(a)所示)


<%@ page contentType="text/html"%>

<%@ page pageEncoding="utf-8"%>

<% request.setCharacterEncoding("utf-8");

%>

<jsp:useBean id="phone" class="tom.jiafei.Goods" scope="request"/>

<HTML><body bgcolor=#ffccff>





<style>

#textStyle{

font-family:宋体;font-size:20;color:blue 

}

</style>

<p id="textStyle">

<form action="" Method="post" >

手机名称:<input type=text id=textStyle name="name">

<br>手机价格:<input type=text id=textStyle name="price"/>

<br><input type=submit id=textStyle value="提交给本页面"/>

</form>

<form action="example5_4_b.jsp" Method="post" >

手机名称:<input type= text name="name" id=textStyle>

<br>手机价格:<input type=text name="price" id=textStyle>

<br><input type=submit id=textStyle value="提交给example5_4_b.jsp页面">

</form>

<jsp:setProperty name="phone" property="name" param ="name" />

<jsp:setProperty name="phone" property="price" param ="price"/>

<br><b>名称: <jsp:getProperty name="phone" property="name"/>

<br><b>名称: <%= phone.getName()%><br>

<br><b>价格: <jsp:getProperty name="phone" property="price"/>

<br><b>价格: <%=phone.getPrice()%>

</p></body></HTML>



example5_4_b.jsp(效果如图5.8(b)所示)


<%@ page contentType="text/html"%>

<%@ page pageEncoding="utf-8"%>

<% request.setCharacterEncoding("utf-8");

%>

<jsp:useBean id="phone" class="tom.jiafei.Goods" scope="page"/>

<HTML><body bgcolor= cyan>

<p style="font-family:黑体;font-size:20;color:red"> 

<jsp:setProperty name="phone" property="name" param ="name" />

<jsp:setProperty name="phone" property="price" param ="price"/>






图5.8设置与获取bean的属性值




<br><b>名称: <jsp:getProperty name="phone" property="name"/>

<br><b>名称: <%= phone.getName()%><br>

<br><b>价格: <jsp:getProperty name="phone" property="price"/>

<br><b>价格: <%=phone.getPrice()%>

</p></body></HTML>





注:  
setProperty和getProperty动作标记适合在处理数据和显示数据不是很复杂的情况下使用,如果业务逻辑或显示数据比较复杂,可能在Java程序片中用bean调用方法更加方便(创建bean的类也不用遵循方法命名的setXXX和getXXX规则)。




5.3bean的辅助类


视频讲解

在写一个创建bean的类时,除了需要用import语句引入JDK提供的类,可能还需要自己编写一些其他的类,只要将这样类的包名和bean类的包名一致即可(也可以和创建bean的类写在一个Java源文件中)。

在下面的例5_5中,使用一个bean列出Tomcat服务器驻留的计算机上某目录中特定扩展名的文件。创建bean的ListFile类,需要一个实现FilenameFilter接口的辅助类FileExtendName,该类可以帮助bean列出指定扩展名的文件(把ListFile.java编译生成的字节码ListFile.class和FileExtendName.class复制到\ch4\WEBINF\classes\tom\jiafei中)。

例5_5使用ListFile类创建request bean。例5_5中用户通过表单设置request bean的extendsName属性值,request bean列出目录中由extendsName属性值指定的扩展名的文件。
例5_5
JavaBean
用命令行进入tom\jiafei的父目录classes,编译ListFile.java(约定见5.1.2节): 


classes>javac tom\jiafei\ListFile.java



ListFile.java(负责创建bean)


package tom.jiafei;

import java.io.*;

class FileExtendName implements FilenameFilter {

String str=null;

FileExtendName (String s) {

str="."+s;

}

public boolean accept(File dir,String name) {

return name.endsWith(str);

}

}

public class ListFile {

String extendsName=null;

String [] allFileName=null;

String dir=null;





public void setDir(String dir) {

this.dir =dir;

}

public String getDir() {

return dir;

}

public void setExtendsName(String s) {

extendsName=s;

}

public String getExtendsName() {

return extendsName;

}

public String [] getAllFileName() {

if(dir!=null) {

File mulu=new File(dir);

FileExtendName help=new FileExtendName(extendsName);

allFileName=mulu.list(help);

}

return allFileName;

}

}



JSP页面
example5_5.jsp(效果如图5.9所示)


<%@ page contentType="text/html"%>

<%@ page pageEncoding="utf-8"%>

<% request.setCharacterEncoding("utf-8");

%>

<style>

#textStyle{

font-family:宋体;font-size:36;color:blue 

}

</style>

<jsp:useBean id="file" class="tom.jiafei.ListFile" scope="request"/>

<HTML><body id=textStyle bgcolor=#ffccff>

<form action="" Method="post">

输入目录名(例如D:/2000)<input type=text name="dir" id=textStyle size=15/><br>

输入文件的扩展名(例如java)

<input type=text name="extendsName" id=textStyle size=6>

<input type=submit id=textStyle value="提交"/>

</form>

<jsp:setProperty name="file" property="dir" param="dir"/>

<jsp:setProperty name="file" property="extendsName" param="extendsName"/>

<br><b>目录 <jsp:getProperty name="file" property="dir"/>中

扩展名是 <jsp:getProperty name="file" property="extendsName"/> 的文件有: 

<% String [] fileName=file.getAllFileName();

if(fileName!=null) {

for(int i=0;i<fileName.length;i++) {

out.print("<br>"+fileName[i]);

}

}

%>

</body></HTML>





图5.9特定扩展名的文件

5.4JSP与bean结合的简单例子

JSP页面中调用bean可以将数据的处理从页面中分离出来,实现代码复用,以便更有效地维护一个Web应用。本节将结合一些实际问题,进一步熟悉掌握bean的使用方法。在本节中,创建bean类的包名都是red.star,使用的Web服务目录仍然是ch5
,因此,需要在ch5目录下建立目录结构: 
ch5\WEBINF\classes\red\star,将
创建bean的字节码文件都保存在该目录中。为了调试程序方便,可以直接按照创建bean类的包名将相应的Java源文件保存在Web服务目录的相应目录中,例如将Java源文件保存在Web服务目录ch5的WEBINF\classes\red\star目录中,然后使用MSDOS命令行进入\red\star的父目录classes,按如下格式编译Java源文件: 


classes>javac red\star\源文件名



 5.4.1三角形bean


视频讲解

例5_6使用request bean(Triangle类负责创建)完成三角形的有关数据的处理。例子中的JSP页面提供一个form表单,用户可以通过form表单将三角形三边的长度提交给该页面。用户提交form表单后,JSP页面将计算三角形面积的任务交给一个request bean去完成。

例5_6
JavaBean
用命令行进入red\star的父目录classes,编译Triangle.java(约定见5.1.2节): 


classes>javac  red\star\Triangle.java



Triangle.java(负责创建request bean)


package red.star;

public class Triangle {

double sideA=-1,sideB=-1,sideC=-1;

String area;

boolean isTriangle;

public void setSideA(double a) {

sideA=a;

}

public double getSideA() {





return sideA;

}

public void setSideB(double b) {

sideB=b;

}

public double getSideB() {

return sideB;

}

public void setSideC(double c) {

sideC=c;

}

public double getSideC() {

return sideC;

}

public String getArea() {

double p=(sideA+sideB+sideC)/2.0;

if(isTriangle){

double result= Math.sqrt(p*(p-sideA)*(p-sideB)*(p-sideC));

area=String.format("%.2f",result);   //保留2位小数

}

return area;

}

public boolean getIsTriangle(){

if(sideA<sideB+sideC&&sideB<sideA+sideC&&sideC<sideA+sideB)

isTriangle=true;

else

isTriangle=false;

return isTriangle;

}

}



JSP页面
example5_6.jsp(效果如图5.10所示)


<%@ page contentType="text/html"%>

<%@ page pageEncoding="utf-8"%>

<style>

#textStyle{

font-family:宋体;font-size:36;color:blue 

}

</style>

<% request.setCharacterEncoding("utf-8");

%>

<jsp:useBean id="triangle" class="red.star.Triangle" scope="request"/>

<HTML><body id=textStyle bgcolor=#ffccff>

<form action="" method="post" >

输入三角形三边: 

边A:<input type=text name="sideA" id=textStyle value=0 size=5/>

边B:<input type=text name="sideB" id=textStyle value=0 size=5/>

边C:<input type=text name="sideC" id=textStyle value=0 size=5/>

<br><input type=submit id=textStyle value="提交"/>





</form>

<jsp:setProperty name="triangle" property="*"/>

三角形的三边是: 

<jsp:getProperty name="triangle" property="sideA"/>,

<jsp:getProperty name="triangle" property="sideB"/>,

<jsp:getProperty name="triangle" property="sideC"/>.

<br><b>这三个边能构成一个三角形吗?<jsp:getProperty name="triangle" property="isTriangle"/>

<br>面积是:<jsp:getProperty name="triangle" property="area"/></b>

</body></HTML>





图5.10用bean计算三角形面积




视频讲解

 5.4.2四则运算bean
例5_7使用session bean(ComputerBean类负责创建)完成四则运算。例子中的JSP页面提供一个form表单,用户可以通过form表单输入两个数,选择四则运算符号提交给该页面。用户提交form表单后,JSP页面将计算任务交给session bean去完成。

例5_7
JavaBean
用命令行进入red\star的父目录classes,编译ComputerBean.java(约定见5.1.2节): 


javac red\star\ComputerBean.java



ComputerBean.java(负责创建session bean)


package red.star;

public class ComputerBean {

double numberOne,numberTwo,result;

String operator="+";

public void setNumberOne(double n) {

numberOne=n;

}

public double getNumberOne() {

return numberOne;

}

public void setNumberTwo(double n) {

numberTwo=n;

}

public double getNumberTwo() {

return numberTwo;

}





public void setOperator(String s) {

operator=s.trim();;

}

public String getOperator() {

return operator;

}

public double getResult() {

if(operator.equals("+"))

result=numberOne+numberTwo;

else if(operator.equals("-"))

result=numberOne-numberTwo;

else if(operator.equals("*"))

result=numberOne*numberTwo;

else if(operator.equals("/"))

result=numberOne/numberTwo;

return result;

}

}



JSP页面
example5_7.jsp(效果如图5.11所示)


<%@ page contentType="text/html"%>

<%@ page pageEncoding="utf-8"%>

<style>

#textStyle{

font-family:宋体;font-size:36;color:blue 

}

</style>

<% request.setCharacterEncoding("utf-8");

%>

<jsp:useBean id="computer" class="red.star.ComputerBean" scope="session"/>

<HTML><body id=textStyle bgcolor=#ffccff>

<jsp:setProperty name="computer" property="*"/>

<form action="" method=post >

<input type=text name="numberOne" id=textStyle size=6/>

<select name="operator" id=textStyle >

<option value="+" id=textStyle>+

<option value="-" id=textStyle>-

<option value="*" id=textStyle>*

<option value="/" id=textStyle>/

</select>

<input type=text name="numberTwo" id=textStyle size=6/>

<br> <input type="submit" value="提交" id=textStyle "/>

</form>

<b>

<jsp:getProperty name="computer" property="numberOne"/>

<jsp:getProperty name="computer" property="operator"/>

<jsp:getProperty name="computer" property="numberTwo"/> =

<jsp:getProperty name="computer" property="result"/></b>

</body></HTML>





图5.11用bean完成四则运算




视频讲解

 5.4.3浏览图像bean

例5_8中的JSP页面通过单击“下一张”或“上一张”超链接浏览图像,JSP页面将获取图像名字的任务交给session bean去完成,JSP页面根据bean获得的图像名字显示图像。例子中使用的图像文件保存在当前Web服务目录的子目录image中(图像文件的名字中不能含有空格)。

例5_8
JavaBean
用命令行进入red\star的父目录classes,编译Play.java(约定见5.1.2节): 


classes>javac  red\star\Play.java



Play.java(负责创建session bean)


package red.star;

import java.io.*;

public class Play {

String pictureName[];//存放全部图片文件名字的数组

String showImage;//存放当前要显示的图片

String webDir="";//Web服务目录的名字,例如ch5

String tomcatDir;//Tomcat的安装目录,例如apache-tomcat-9.0.26

int index=0;//存放图片文件的序号

public Play() {

File f= new File(""); //该文件认为在Tomcat服务器启动的目录中,即bin目录中

String path=f.getAbsolutePath();

int index=path.indexOf("bin");   //bin是Tomcat的安装目录下的子目录

tomcatDir=path.substring(0,index); //得到Tomcat的安装目录的名字

}

public void setWebDir(String s) {

webDir=s;

File dirImage=new File(tomcatDir+"/webapps/"+webDir+"/image");

pictureName=dirImage.list();

}

public String getShowImage() {

showImage=pictureName[index];

return showImage;

}

public void setIndex(int i) {

index=i;

if(index>=pictureName.length)

index=0;

if(index < 0)





index=pictureName.length-1;

}

public int getIndex() {

returnindex ;

}

}




JSP页面
example5_8.jsp(效果如图5.12所示)


<%@ page contentType="text/html"%>

<%@ page pageEncoding="utf-8"%>

<style>

#textStyle{

font-family:宋体;font-size:36;color:blue 

}

</style>

<% request.setCharacterEncoding("utf-8");

%>

<jsp:useBean id="play" class="red.star.Play" scope="session" />

<%

String webDir=request.getContextPath();  //获取当前Web服务目录的名称

webDir=webDir.substring(1); //去掉名称前面的目录符号: /

%>

<jsp:setPropertyname="play" property="webDir" value="<%= webDir %>"/>

<jsp:setPropertyname="play" property="index"param="index" />

<HTML><body bgcolor=cyan><p id=textStyle>

<image src =

 image/<jsp:getProperty name="play" property=

"showImage"/> width =300 height =200></image><br>

<a href ="?index=<%=play.getIndex()+1 %>">下一张</a>

<a href ="?index=<%=play.getIndex()-1 %>">上一张</a>

</p></body></HTML>






图5.12浏览图像




视频讲解

 5.4.4日历bean
例5_9使用session bean(Calendar类负责创建)显示某月的日历。用户单击“下一月”“上一月”超链接可以翻阅日历。也可以输入年份,选择月份,单击 form表单中的提交键查看日历。
例5_9
JavaBean
用命令行进入red\star的父目录classes,编译Calendar.java(约定见5.1.2节): 


classes>javac  red\star\Calendar.java



Calendar.java(负责创建session bean)


package red.star;

import java.time.LocalDate;

import java.time.DayOfWeek;

public class Calendar {

int year ,month ;

String saveCalender;//存放日历

public Calendar(){

year=LocalDate.now().getYear();

month=LocalDate.now().getMonthValue();

}

public void setYear(int y){

year=y;

}

public int getYear(){

return year;

}

public void setMonth(int m){

month=m;

if(month>12){

year++;

month=1;

}

if(month<1){

month=12;

year--;

}

}

public int getMonth(){

return month;

}

public String getSaveCalender(){

LocalDate date=LocalDate.of(year,month,1);

int days=date.lengthOfMonth(); //得到该月有多少天

int space=0;//存放空白字符的个数

DayOfWeek dayOfWeek=date.getDayOfWeek(); //得到1号是星期几

switch(dayOfWeek) {

case SUNDAY:space=0;

break;

case MONDAY:space=1;

break;

case TUESDAY:space=2;

break;

case WEDNESDAY: space=3;

break;





case THURSDAY:space=4;

break;

case FRIDAY:space=5;

break;

case SATURDAY:space=6;

break;

}

String [] c=new String[space+days];


for(int i=0;i<space;i++)

c[i]="--";

for(int i=space,n=1;i<c.length;i++){

c[i]=String.valueOf(n) ;

n++;

}

String head =

"<tr><th>星期日</th><th>星期一</th><th>星期二</th><th>星期三</th>"+

"<th>星期四</th><th>星期五</th><th>星期六</th> </tr>";

StringBuffer buffer=new StringBuffer();

buffer.append("<table border=0>");

buffer.append(head);

int n=0;

while(n<c.length){

buffer.append("<tr>");

int increment=Math.min(7,c.length-n);

for(int i=n;i<n+increment;i++) {

buffer.append("<td align= center>"+c[i]+"</td>");

}

buffer.append("</tr>");

n=n+increment;

}

buffer.append("</table>");

saveCalender=new String(buffer);

return saveCalender;

}

}



JSP页面
example5_9.jsp(效果如图5.13所示)


<%@ page contentType="text/html"%>

<%@ page pageEncoding="utf-8"%>

<style>

#textStyle{

font-family:宋体;font-size:18;color:blue 

}

</style>

<% request.setCharacterEncoding("utf-8");

%>

<HTML><body id=textStyle bgcolor=#ffccff>

<jsp:useBean id="calendar" class="red.star.Calendar" scope="session" />

<jsp:setPropertyname="calendar" property="year"param="year"/>





<jsp:setProperty name="calendar" property="month"param="month" />

<jsp:getProperty name="calendar" property="year" />年

<jsp:getProperty name="calendar" property="month" />月的日历: <br>

<jsp:getProperty name="calendar" property="saveCalender" />

<br><a href ="?month=<%=calendar.getMonth()+1 %>">下一月</a>

<a href ="?month=<%=calendar.getMonth()-1 %>">上一月</a>

<form action="" method=get >

输入年份<input type=text name="year"id=textStyle size=6 />

选择月份 <select name="month" id=textStyle size =1>

<option value="1">1月</option>

<option value="2">2月</option>

<option value="3">3月</option>

<option value="4">4月</option>

<option value="5">5月</option>

<option value="6">6月</option>

<option value="7">7月</option>

<option value="8">8月</option>

<option value="9">9月</option>

<option value="10">10月</option>

<option value="11">11月</option>

<option value="12">12月</option>

</select><br>

<input type="submit" value="提交" id=textStyle "/>

</form>

</body></HTML>





图5.13查看日历




视频讲解

 5.4.5计数器bean

例5_10使用application bean(ComputerCount类负责创建)记录Web服务目录(通常所说的网站)被访问的次数。只要用户第1次访问(用户的session被创建)Web服务目录,那么当前Web服务目录的访问计数就增加1。如果用户的session没有消失,用户再访问当前Web服务目录,访问的计数不再增1。 
例5_10
JavaBean
用命令行进入red\star的父目录classes,编译ComputerCount.java(约定见5.1.2节): 


classes>javac  red\star\ComputerCount.java



ComputerCount.java(负责创建application bean)


package red.star;

import java.io.*;

public class ComputerCount {

int number=0;

public synchronized void addCount() {

number++;

}

public int getNumber(){

return number;

}

}

import java.time.DayOfWeek;



JSP页面
example5_10_a.jsp(效果如图5.14(a)所示)


<%@ page contentType="text/html"%>

<%@ page pageEncoding="utf-8"%>

<jsp:useBean id="count" class="red.star.ComputerCount" 

scope="application"/>

<% if(session.isNew()) {

count.addCount();

}

%>

<HTML><body bgcolor=cyan>

<h1>这是网站的example5_10_a.jsp页面。

<br>网站访问量:<jsp:getProperty name="count" property="number"/>

<br>

<a href="example5_10_b.jsp">欢迎去example5_10_b.jsp参观</a>

</body></HTML>



example5_10_b.jsp(效果如图5.14(b)所示)


<%@ page contentType="text/html"%>

<%@ page pageEncoding="utf-8"%>

<jsp:useBean id="count" class="red.star.ComputerCount"

scope="application"/>

<HTML><body bgcolor=#ffccff>

<% if(session.isNew()) {

count.addCount();

}

%>

<h1>这是网站的example5_10_b.jsp页面

<br>网站访问量:

<jsp:getProperty name="count" property="number"/>

<br>

<a href="example5_10_a.jsp">欢迎去example5_10_a.jsp参观</a>

</body></HTML>





图5.14两个用户访问Web服务目录



视频讲解

5.5上机实验
提供了详细的实验步骤要求,按步骤完成,提升学习效果,积累经验,不断提高Web设计能力。
5.5.1实验1小数表示为分数
 实验目的

掌握怎样使用 request bean。
 实验要求

(1) 编写inputNumber.jsp,该页面提供一个form表单,该form表单提供一个text文本框,用于用户输入一个纯小数(例如0.618)
。用户在form表单中输入纯小数后,单击submit提交键将纯小数提交给getFraction.jsp页面。

(2) getFraction.jsp使用request bean,并使用setProperty动作标记让request bean将纯小数转换为分数,把分子和分母存放在request bean的名字是numerator 和denominator 的属性(变量)中。然后getFraction.jsp使用getProperty动作标记获取request bean的numerator 和denominator的属性值。

(3) 在Tomcat服务器的webapps目录下(例如D:\apachetomcat9.0.26\webapps)新建一个名字是ch5_practice_one的Web服务目录。把JSP页面都保存到ch5_practice_one目录中。在ch5_practice_one下建立子目录WEBINF(字母大写),然后在WEBINF下再建立子目录classes。将创建request bean的类的Java源文件保存在classes的相应子目录中(见5.1.2节)。

(4) 用浏览器访问JSP页面inputNumber.jsp。

 参考代码
参考代码运行效果如图5.15所示。


图5.15把纯小数表示成分数



JavaBean用命令行进入sea\water的父目录classes,编译Fraction.java(约定见5.1.2节): 


classes>javac  sea\water\Fraction.java



Fraction.java(负责创建request bean)


package sea.water;

public class Fraction {

public double number ;//存放小数

public long numerator ;//存放分子

public long denominator; //存放分母

public double getNumber(){

String numberString=String.valueOf(number);

String xiaoshuPart =

numberString.substring(numberString.indexOf(".")+1);   //得到纯小数部分

return Double.parseDouble("0."+xiaoshuPart);

}

public long getNumerator(){

return numerator;

}

public long getDenominator(){

return denominator;

}

public void setNumber(double number){

this.number=number;

String numberString=String.valueOf(number);

String xiaoshuPart =

numberString.substring(numberString.indexOf(".")+1); //得到小数部分

int m=xiaoshuPart.length();   //m的值就是小数的小数位数

numerator=Long.parseLong(xiaoshuPart);//分子

denominator=(long)Math.pow(10,m);//分母

long greatCommonDivisor=f(numerator,denominator) ; //最大公约数

numerator=numerator/greatCommonDivisor;

denominator=denominator/greatCommonDivisor;

}

private long f(long a,long b) { //求a和b的最大公约数

if(a==0) return 1;

if(a<b) {

long c=a;

a=b;

b=c;

}

long r=a%b;

while(r!=0) {

a=b;

b=r;

r=a%b;

}

return b;

}

}




JSP页面
inputNumber.jsp(效果如图5.15(a)所示)


<%@ page contentType="text/html"%>

<%@ page pageEncoding="utf-8"%>

<style>

#tomStyle{

font-family:宋体;font-size:36;color:blue 

}

</style>

<HTML><body bgcolor=#ffccff>

<form action="getFraction.jsp" id=tomStyle method=post >

输入一个纯小数:<br>

<input type=text name="number" id=tomStyle size=16 value=0.618 />

<br><input type="submit" id=tomStylevalue="提交" /><br>

看小数的分数表示。

</form>

</body></HTML>



getFraction.jsp (效果如图5.15(b)所示)


<%@ page contentType="text/html"%>

<%@ page pageEncoding="utf-8"%>

<HTML><body bgcolor=cyan>

<p style="font-family:宋体;font-size:36;color:red">

<jsp:useBean id="fraction" class="sea.water.Fraction" scope="request" />

<jsp:setProperty name="fraction" property="number"param="number" />

<jsp:getProperty name="fraction" property="number" />

表示成分数是: <br>

<jsp:getProperty name="fraction" property="numerator" /> 

<jsp:getProperty name="fraction" property="denominator" />

</p></body></HTML>




5.5.2实验2记忆测试
 实验目的

掌握使用session bean存储用户的数据,和4.6.5节的记忆测试实验进行比对,体会使用bean的方便和好处。
 实验要求

(1) 编写choiceGrage.jsp,该页面中的form表单中使用radio标记选择记忆测试级别: 初级、中级和高级。初级需要记忆一个长度为5个字符的字符序列(例如★■★▲●),中级需要记忆一个长度为7个字符的字符序列,高级需要记忆一个长度为10个字符的字符序列。在choiceGrage.jsp页面选择级别后,单击form表单的提交键提交给giveTest.jsp页面。

(2) 编写giveTest.jsp页面,该页面获取choiceGrage.jsp页面提交的级别后,使用session bean显示testString
的属性值(例如属性值是长度为7个字符的字符序列),然后提示用户在5秒内记住这个字符序列。5秒后,该页面将自动定向到answerTest.jsp页面。

(3) 编写answerTest.jsp页面,该页面的form表单提供用户给出答案的界面,即使用radio标记让用户选择字符序列中的各个字符,以此代表用户认为自己记住的字符序列。单击提交键,将选择提交给judgeAnswer.jsp页面。
(4) 编写judgeAnswer.jsp页面,该页面负责判断有户是否记住了giveTest.jsp页面给出的字符序列。
(5) 在Tomcat服务器的webapps目录下新建名字是ch5_practice_two的目录,即新建Web服务目录ch5_practice_two。把JSP页面都保存到ch5_practice_two目录中。在ch5_practice_two目录下建立子目录WEBINF(字母大写),然后在WEBINF目录下再建立子目录classes,即在ch5_practice_two目录下建立\WEBINF\classes目录结构。将创建session bean类的Java源文件按
照包名保存在classes的相应子目录中(见5.1.2节)。
(6) 用浏览器访问JSP页面choiceGrage.jsp。
(7) 将本实验与4.6.5节的实验进行对比,感受使用session bean的好处。

 参考代码
请比较4.6.5节的记忆测试实验,体会使用bean的方便和好处。参考代码运行效果如图5.16所示。


图5.16记忆测试


JavaBean
用命令行进入sea\water的父目录classes,编译Memory.java(约定见5.1.2节): 


classes>javac  sea\water\Memory.java



Memory.java(负责创建session bean)


package sea.water;

import java.util.ArrayList;

import java.util.Random;

public class Memory {

static ArrayList<String> list=new ArrayList<String>();

static {

list.add("★");

list.add("●");

list.add("▲");

list.add("■");

list.add("◆");

}





int grade=5 ;//存放级别,例如初级grade存放的值是5,中级是7,高级是10

String testString;//存放需要记忆的字符序列,例如,★■★▲●

boolean isGivenTestString=false;  //存放是否已经给了测试题目

public void setGrade(int n){

grade=n;

}

public int getGrade(){

return grade;

}

public void giveTestString(){

StringBuffer buffer=new StringBuffer();

Random random=new Random();

for(int i=0;i<grade;i++) {

int index=random.nextInt(list.size());

String str=list.get(index); //从list中得到一个字符,例如★

buffer.append(str);

}

testString=new String(buffer);

}

public void setIsGivenTestString(boolean b){

isGivenTestString =b;

}

public boolean getIsGivenTestString(){

return isGivenTestString;

}

public String getTestString(){

return testString;

}

}




JSP页面
choiceGrade.jsp(效果如图5.16(a)所示)


<%@ page contentType="text/html"%>

<%@ page pageEncoding="utf-8"%>

<HTML><body bgcolor=#ffccff>

<style>

#textStyle{

font-family:宋体;font-size:26;color:blue 

}

</style>

<form action="giveTest.jsp" id ="textStyle" method=post >

 <input type=radio name="grade"value="5" />初级

 <input type=radio name="grade"value="7" checked="ok" />中级

 <input type=radio name="grade"value="10" />高级

<br><input type="submit" id ="textStyle" value="提交"/>

<input type="reset" id ="textStyle" value="重置" />

</form>

</body></HTML> 




giveTest.jsp(效果如图5.16(b)所示)


<%@ page contentType="text/html"%>

<%@ page pageEncoding="utf-8"%>

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

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

<jsp:useBean id="memory" class="sea.water.Memory" scope="session" />

<HTML><body bgcolor=#ffccff>

<style>

#tomStyle{

font-family:宋体;font-size:36;color:blue 

}

</style>

<%String grade=request.getParameter("grade");

String testString =""; //存放测试题目,例如★■★▲●

if(grade == null){

memory.setGrade(memory.getGrade());

}

else {

memory.setGrade(Integer.parseInt(grade));

}

if(memory.getIsGivenTestString()== false) {

memory.giveTestString();

testString=memory.getTestString(); //得到测试的题目

memory.setIsGivenTestString(true);

}

else if(memory.getIsGivenTestString()== true){

response.sendRedirect("answerTest.jsp");   //定向到答题页面

}

%>

<p id=tomStyle>给5秒记住您看到的字符序列:<br>

<%= testString %>

<br>5秒后,将转到答题页。

<%response.setHeader("refresh","5");

%>

</p></body></HTML> 



answerTest.jsp(效果如图5.16(c)所示)


<%@ page contentType="text/html"%>

<%@ page pageEncoding="utf-8"%>

<jsp:useBean id="memory" class="sea.water.Memory" scope="session" />

<HTML><body bgcolor=#ffccff>

<style>

#tomStyle{

font-family:宋体;font-size:26;color:blue 

}

</style>

<form action="judgeAnswer.jsp" id=tomStyle method=post>

您记住的字符序列是怎样的,请选择:

<%

int n=memory.getGrade();





memory.setIsGivenTestString(false);

for(int i=1;i<=n;i++){

out.print("<br>第"+i+"个字符:");

out.print

("<input type=radio id=tomStyle name=R"+i+" value='★'/>★"+

"<input type=radio id =tomStyle name=R"+i+" value='●' />●"+ 

"<input type=radio id =tomStyle name=R"+i+" value='▲' />▲"+ 

"<input type=radio id =tomStyle name=R"+i+" value='■' />■"+ 

"<input type=radio id =tomStyle name=R"+i+" value='◆' />◆");

}

%>

<br><input type="submit"id=tomStyle value="提交"/>

<input type="reset" id=tomStyle value="重置" />

</form>

</body></HTML> 



judgeAnswer.jsp(效果如图5.16(d)所示)


<%@ page contentType="text/html"%>

<%@ page pageEncoding="utf-8"%>

<jsp:useBean id="memory" class="sea.water.Memory" scope="session" />

<HTML><body bgcolor=white >

<p style="font-family:宋体;font-size:26;color:blue"> 

<%memory.setIsGivenTestString(false);

request.setCharacterEncoding("utf-8"); 

int n=memory.getGrade();

StringBuffer buffer=new StringBuffer();

for(int i=1;i<=n;i++){

buffer.append(request.getParameter("R"+i)); //获取radio提交的值

out.print(""+request.getParameter("R"+i));

}

String userAnswer=new String(buffer);

String testString=memory.getTestString();   //得到测试的题目

if(testString.equals(userAnswer)){

out.print("您记忆不错");

}

else {

out.print("您没记忆住!答案是:<br>"+testString);

}

%>

<br><a href="giveTest.jsp">返回,继续练习记忆</a>

<br><a href="choiceGrade.jsp">重新选择级别</a>

</p></body></HTML>



5.5.3实验3成语接龙
 实验目的

掌握使用application bean存储所有用户共享的数据。
 实验要求

(1) 编写inputIdioms.jsp,该页面使用application bean显示目前成语接龙的信息。提供form表单,用户根据目前成语接龙的信息输入一个成语,单击提交键提交给当前页面,如果输入成语符合成语接龙规则(例如输入的成语的首字和成语接龙中的最后一个成语的末字相同),application bean就将用户输入的成语添加到成语接龙中。

(2) 在Tomcat服务器的webapps目录下新建名字是ch5_practice_three的Web服务目录。把JSP页面都保存到ch5_practice_three目录中。在ch5_practice_three下建立子目录WEBINF(字母大写),然后在WEBINF目录下再建立子目录classes,即在ch5_practice_three目录下建立\WEBINF\classes目录结构。将创建application bean的类的Java源文件按照包名保存在classes的相应子目录中(见5.1.2节)。

(3) 用浏览器访问JSP页面inputIdioms.jsp。

 参考代码

参考代码运行效果如图5.17所示。


图5.17成语接龙


JavaBean
用命令行进入sea\water的父目录classes,编译ContinueIdioms.java(约定见5.1.2节): 


classes>javac  sea\water\ ContinueIdioms.java




ContinueIdioms.java(负责创建application bean)


package sea.water;

import java.util.LinkedList;

import java.util.Iterator;

import java.util.NoSuchElementException;

public class ContinueIdioms {

LinkedList<String> listIdioms ;   //存放成语的链表

public String nowIdioms;//当前参与接龙的成语

public ContinueIdioms(){

listIdioms=new LinkedList<String>();

}

public synchronized void setNowIdioms(String s){

nowIdioms=s;

try{

String previous=listIdioms.getLast(); //得到上次添加的成语

//上一个成语的最后一个字符

char endChar=previous.charAt(previous.length()-1);

char startChar=nowIdioms.charAt(0);   //当前成语的第一个字符

if(startChar == endChar)

listIdioms.add(nowIdioms);

}

catch(NoSuchElementException exp){

listIdioms.add(nowIdioms);

System.out.println(exp);





}

}

public String getAllIdioms(){

StringBuffer buffer=new StringBuffer();

Iterator<String> iterator =listIdioms.iterator();

if(iterator.hasNext() == false)

buffer.append("→");

while(iterator.hasNext()){

buffer.append(iterator.next()+"→");

}

return new String(buffer);

}

}




JSP页面
inputIdioms.jsp (效果如图5.17(a)(b)所示)


<%@ page contentType="text/html"%>

<%@ page pageEncoding="utf-8"%>

<jsp:useBean id="idioms" class="sea.water.ContinueIdioms"

scope="application" />

<style>

#tomStyle{

font-family:宋体;font-size:26;color:blue 

}

</style>

<% request.setCharacterEncoding("utf-8");

%>

<jsp:setProperty name="idioms" property="nowIdioms" param ="nowIdioms" />

<HTML><body bgcolor=#ffccff>

<p id=tomStyle>

目前的接龙情景: <br>

<textArea id=tomStyle rows=5 cols=38>

<%= idioms.getAllIdioms() %>

</textArea><br>

<formaction="" id=tomStyle  method=post >

继续接龙,输入成语:<textname="nowIdioms" value=10 />

<br><input type="text" name ="nowIdioms"id=tomStyle />

<input type="submit"id=tomStyle value="提交"/>

</form>

</p></body></HTML> 



5.6小结
 JavaBean是一个可重复使用的软件组件,是遵循一定标准、用Java语言编写的一个类,该类的一个实例称作一个JavaBean。
 一个JSP页面可以将数据的处理过程指派给一个或几个bean来完成,我们在JSP页面中调用这些bean即可。在JSP页面中调用bean可以将数据的处理代码从页面中分离出来,实现代码复用,更有效地维护一个Web应用。
 bean的生命周期分为page、request、session和application。
习 题 5

1. 假设Web服务目录mymoon中的JSP页面要使用一个bean,该bean的包名为blue.sky。请说明,应当怎样保存bean的字节码文件。
2.  假设Web服务目录是mymoon,star是mymoon的一个子目录,JSP页面a.jsp保存在star中,并准备使用一个bean,该bean的包名为tom.jiafei。下列哪个叙述是正确的?
A. 创建bean的字节码文件保存在\mymoon\WEBINF\classes\tom\jiafei中
B.  创建bean的字节码文件保存在\mymoon\star\WEBINF\classes\tom\jiafei中
C. 创建bean的字节码文件保存在\mymoon\WEBINF\star\classes\tom\jiafei中 
D. 创建bean的字节码文件保存在\mymoon\WEBINF\classes\start\tom\jiafei中
3.  tom.jiafei.Circle是创建bean的类,下列哪个标记是正确创建session bean的标记?
A. <jsp:useBean id="circle"  class="tom.jiafei.Circle" scope="page" />
B.  <jsp:useBean id="circle"  class="tom.jiafei.Circle " scope="request" />
C. <jsp:useBean id="circle"  class="tom.jiafei.Circle " scope="session" />
D. <jsp:useBean id="circle"  type="tom.jiafei.Circle " scope="session" />
4. 假设创建bean的类有一个int型的属性number,下列哪个方法是设置该属性值的正确方法?
A.  public void setNumber(int n){B. void setNumber(int n){

number=n;number=n;

} }
C.  public void SetNumber(int n) {D.  public void Setnumber(int n){
number=n;number=n;
}}
5. 假设JSP页面使用标记


<jsp:useBean id="moon" class="tom.jiafei.AAA" scope="page"/>



创建了一个名字为moon的bean,该bean有一个String类型、名字为number的属性。如果创建moon的Java类AAA没有提供public String getNumber()方法,JSP页面是否允许使用如下getProperty标记获取moon的number属性值?


<jsp:getPropertyname="moon" property="number"/>



6. 编写一个JSP页面,该页面提供一个表单,用户可以通过表单输入梯形的上底、下底和高的值,并提交给本JSP页面,该JSP页面将计算梯形面积的任务交给一个page bean去完成。JSP页面使用getProperty动作标记显示page bean中的数据,例如梯形的面积。
7. 编写两个JSP页面a.jsp和b.jsp,a.jsp页面提供一个表单,用户可以通过表单输入矩形的两个边长提交给b.jsp页面,b.jsp调用一个request bean去完成计算矩形面积的任务。b.jsp页面使用getProperty动作标记显示矩形的面积。