按照Sun公司的定义, Javabean是一个可重复使用的软件组件,实际上 Javabean是一种Java类,通过封装属性和方法成为具有某种功能或者处理某个业务的对象,简称bean.由于 Javabean是基于Java语言的,因此 Javabean 不依赖平台,具有以下特点:
- 可以实现代码的重复利用
- 易编写、易维护、易使用
- 可以在任何安装了Java运行环境的平台上的使用,而不需要重新编译
JSP页面可以将数据的处理过程指派给一个或几个bean来完成,即JSP页面调用bean完成数据的处理,并将有关处理结果存放bean中,然后JSP页面负责显示bean中的数据。
一、编写JavaBean和使用JavaBean
1、编写JavaBean
Javabean分为可视组件和非可视组件,在JSP中主要使用非可视组件,对于非可视组件,我们不必去设计它的外观,主要关心它的属性和方法编写 Javabean就是编写一个Java的类,所以只要会写类就能编写一个 Javabean.这个类创建的一个对象称为一个 Javabean,简称bean.为了能让使用这个bean的应用程序构建工具(比如JSP引擎)知道这个bean的属性和方法,只须在类的方法命名上遵守以下规则
- 如果类的成员变量的名字是
xxx
,那么为了获取或更改成员变量的值,即获取或更改属性,类中必须提供两个方法
getXxx(),用来获取属性xx
setXxx(),用来修改属性xxx
也就是方法的名字用get
或set
为前缀,后缀是将成员变量名字的首字母大写的字符序列
- 对于
boolean
类型的成员变量,即布尔逻辑类型的属性,允许使用“is
“代替上面的"get
”和“set
” - 类中声明的方法的访问属性都必须是
public
的 - 类中声明的构造方法必须是
public
、无参数的
2、保存字节码
将.java
文件通过编译生成.class
文件。为了使JSP页面使用bean, Tomcat服务器必须使用相应的字节码创建一个对象,即创建一个bean。为了让 Tomcat服务器能找到字节码,字节码文件必须保存在特定的目录中。(\WEB-INF\classes
)
3、创建与使用bean
1.使用bean
使用JSP动作标记 useBean
来加载使用bean。useBean
标记的语法格式是:
<jsp:useBean id="bean的名字" class="创建bean的字节码” scope="bean有效范围"/>
或
<jsp:useBean id="bean的名字” class="创建bean的类" scope="bean有效范围">
</jsp:useBean>
2.bean的加载原理
当JSP页面使用JSP动作标记 useBean
加载一个bean时,JSP引擎将首先根据JSP动作标记 useBean
给出的bean的id
名字以及 scope
给出的使用范围(bean生命周期),在一个同步块中查找JSP引擎内置 pageContent
对象中是否含有这样的bean。如果这样的bean存在,JSP引擎就分配这样的bean给用户;如果在 pageContent
中没有查找到JSP动作标记要求的bean,就根据class
指定的字节码创建一个JSP动作标记 useBean
要求的bean,并将所创建的bean添加到 pageContent
内置对象中。
从JSP引擎创建bean的过程可以看出,首次创建一个新的bean需要用相应的字节码文件创建对象,当某些JSP页面再需要同样的bean时,JSP引擎直接将内置的 pageContent
中已经有的bean分配给JSP页面,提高了JSP使用bean的效率。
- 注意:如果修改了字节码文件,必须重新启动JSP引擎才能使用新的字节码文件。
3.bean的有效范围
scope
的取值范围给出了bean
的存活时间(生命周期),即scope
取值决定了JSP引擎分配给用户的bean
的存活时间,因此需要理解 scope
取值的具体意义。下面就JSP动作标记 useBean
中scope
取值的不同情况进行说明。
scope
取值page
bean
的有效范围是page
期间。JSP引擎分配给每个JSP页面的page
期间的bean
是互不相同的。也就是说,尽管每个JSP页面的bean的功能相同,但它们占有不同的内存空间。该bean的有效范围是当前页面,当页面执行完毕,JSP引擎取消分配的bean
,即释放 bean所占有的内存空间。简单地说, scope
取值为page
的bean 只在当前页面都有效,直到页面执行完毕。
需要注意的是,不同用户的 scope
取值是page
的bean也是互不相同的。也就是说,当两个用户同时访问一个JSP页面时,一个用户对自己bean
的属性的改变,不会影响到另一个用户。
scope
取值session
bean的有效范围是用户的 session
(会话)期间。如果用户在某个Web服务目录多个页面中相互连接,每个页面都含有相同的一个JSP动作标记 useBean
,即 useBean
标记中id
的值相同、 scope
的值都是 session
,那么,该用户在这些页面得到的bean是相同的一个(占有相同的内存空间)。如果用户在某个页面更改了这个bean的属性,其他页面的这个bean的属性也将发生同样的变化。当用户的会话( session
)消失,JSP引擎取消所分配的bean,即释放bean所占有的内存空间。简单地说, scope
取值为 session
的bean在用户访问的Web服务目录的各个页面都有效,直到用户的会话( session
)消失。
需要注意的是,不同用户(即不同浏览器)的 scope
取值是 session
的bean是互不相同的(占有不同的内存空间)。也就是说,当两个用户同时访问一个JSP页面时,一个用户对自己bean的属性的改变,不会影响到另一个用户。
scope
取值request
bean的有效范围是 request
期间。JsP引擎分配给每个JSP页面的 request
期间的bean是互不相同的。JSP引擎对请求做出响应之后,取消分配给JSP页面的这个bean。简单地说, scope
取值为 request
的bean 只在当前页面都有效,直到响应结束。bean的request
存活时间略长于page
存活时间,因为JSP引擎认为页面执行完毕后,响应才算结束。
需要注意的是,不同用户的 scope
取值是 request
的bean也是互不相同的。也就是说,当两个用户同时请求一个JSP页面时,一个用户对自己bean的属性的改变,不会影响到另一个用户。
scope
取值application
bean的有效范围是 application
期间。JSP引擎为Web服务目录下所有的JSP页面分配一个共享的bean,不同用户的 scope
取值是 application
的bean也都是相同的一个。也就是说,当多个用户同时访问一个JSP页面时,任何一个用户对自己bean的属性的改变,都会影响到其他的用户。直到服务器关闭,才取消有效范围是 application
的bean。
注意:当使用作用域是 session
的bean时,要保证用户端支持 Cooker
。
二、获取和修改bean的属性
1、getProperty动作标记
使用 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的一个属性的名字。该指令相当于Java表达式:<%=bean. getXxx()%>
2、setProperty动作标记
使用 setProperty
动作标记可以设置bean的属性值。使用这个标记之前,必须使用uaeBean
标记得到一个相应的bean。
setProperty
动作标记可以通过两种方式设置bean属性的值
(1)将bean属性的值设置为一个表达式的值或字符串。
- 将bean属性的值设置为一个表达式的值的语法格式
<jsp:setProperty name="bean的id的名字" property="bean的属性" vlue="<%= expression %>"/>
- 将bean属性的值设置为一个字符串语法格式
<jsp:setProperty name="bean的id的名字" property="bean的属性" value=字符串/>
如果将表达式的值设置为bean属性的值,表达式值的类型必须和bean的属性的类型一致。如果将字符串设置为bean的属性的值,这个字符串会自动被转化为bean的属性的类型。Java语言将字符串转化为其他数值类型的方法如下:
转化到int
:Integer. parseInt( Sting s)
;
转化到long
:Long. parselong( Sting s)
;
转化到 float
:Float. parseFloat( Sting s)
;
转化到 double
:Double. parseDouble( Sting s)
。
这些方法都可能发生 NumberFormatException异常。
Student.java
源码:
package red.star;
public class Student {
String name = null;
double height;
public String getName() {
return name;
}
public void setName(String newName) {
name = newName;
}
public double getHeight() {
return height;
}
public void setHeight(double newHeight) {
height = newHeight;
}
}
example4_4.jsp
源码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<jsp:useBean id="zhang" class="red.star.Student" scope="request"></jsp:useBean>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body bgcolor="pink">
<jsp:setProperty property="name" name="zhang" value="张三"/>
<b>学生姓名:<jsp:getProperty property="name" name="zhang"/></b>
<jsp:setProperty property="height" name="zhang" value="<%= 1.8 %>"/>
<b>学生身高:<jsp:getProperty property="name" name="height"/>米</b>
</body>
</html>
(2)通过HTTP表单的参数的值来设置bean的相应属性的值。
当前JSP页面使用 setProperty
设置bean属性值的第2种方式是通过本页面或请求本页面的其他页面中的HTTP表单的参数的值来设置bean的相应属性的值
- 用HTTP表单的所有参数的值设置bean相对应的属性值的使用格式如下:
<jsp:setProperty name="bean的id的名字” property="*"/>
在 setProperty
标记的上述用法中不具体指定bean属性的值将对应表单中哪个参数指定的值,系统会自动根据名字进行匹配对应,但要求bean属性的名字必须在表单中有名称相同的参数名字相对应,JSP引擎会自动将参数的字符串值转换为bean相对应的属性的值。
- 用HTTP表单的某个参数的值设置bean的某个属性值的使用格式如下:
<jsp:setProperty name="bean的名字” property="属性名” param="参数名”/>
setProperty
标记的上述用法具体指定了bean属性的值将对应表单中哪个参数名指定的值,这种设置bean的属性值的方法,不要求 property
给出的bean属性的名字和 param
给出的参数名一致,即不要求bean属性的名字必须和表单中某个参数名字相同。
注意:用HTTP表单设置bean的属性值时,只有提交了表单,对应的setProperty
标记才会被执行。另外,如果表单中提交的信息有汉字,bean中对应的方法需要处理汉字信息,以防止出现乱码。
Goods.java
源码:
package red.star;
public class Goods {
String name = "无名";
double price = 0;
public String getName() {
return name;
}
public void setName(String newName) {
try {
byte bb[] = newName.getBytes("ISO-8859-1");
newName = new String(bb,"utf-8");
}catch(Exception exp){
}
name = newName;
}
public double getPrice() {
return price;
}
public void setPrice(double newPrice) {
price = newPrice;
}
}
example4_5_a.jsp
源码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<jsp:useBean id="iPhone" class="red.star.Goods" scope="request"></jsp:useBean>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body bgcolor="cyan">
<form action="" method="post">
手机名称:<input type="text" name="name">
<br>手机价格:<input type="text" name="price">
<br><input type="submit" value="提交给本页面">
</form>
<form action="example4_5_b.jsp" method="post">
手机名称:<input type="text" name="name">
<br>手机价格:<input type="text" name="price">
<br><input type="submit" value="提交example4_5_b.jsp本页面">
</form>
<jsp:setProperty property="name" name="iPhone" param="name"/>
<jsp:setProperty property="price" name="iPhone" param="price"/>
<br><b>名称:<jsp:getProperty property="name" name="iPhone"/></b>
<br><b>价格:<jsp:getProperty property="price" name="iPhone"/></b>
</body>
</html>
example4_5_b.jsp
源码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<jsp:useBean id="iPhone" class="red.star.Goods" scope="request"></jsp:useBean>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<jsp:setProperty property="name" name="iPhone" param="name"/>
<jsp:setProperty property="price" name="iPhone" param="price"/>
<br><b>名称:<jsp:getProperty property="name" name="iPhone"/></b>
<br><b>价格:<jsp:getProperty property="price" name="iPhone"/></b>
</body>
</html>
三、bean的辅助类
在下面的例子4_6中,使用一个bean列出JSP页面所在目录中特定扩展名的文件。在写bean的类文件 Listfile
时,需要一个实现 FilenameFilter
接口的辅助类:FileExtendName
,该类可以帮助我们的bean列出指定扩展名的文件(把 ListFile.java
编译生成的字节码ListFile. class
和 FileextendName. class
复制到\ch04\WEB-INF\classes\red\star
中)
ListFile.java
源码:
package red.star;
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;
}
}
example4_6.jsp
源码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<jsp:useBean id="file" class="red.star.ListFile" scope="request"></jsp:useBean>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body bgcolor="cyan">
<form action="" method="post">
输入目录名,例如:D:\
<input type="text" name="dir"><br>
输入文件的扩展名,例如Java
<input type="text" name="extendsName">
<input type="submit" value="提交">
</form>
<jsp:setProperty property="dir" name="file" param="dir"/>
<jsp:setProperty property="extendsName" name="file" param="extendsName"/>
<br><b>目录<jsp:getProperty property="dir" name="file"/>中,扩展名是:<jsp:getProperty property="extendsName" name="file"/>
的文件有:
</b>
<%
String fileName[] = file.getAllFileName();
if(fileName != null){
for(int i = 0; i < fileName.length; i ++){
out.print("<br>" + fileName[i]);
}
}
%>
</body>
</html>
四、JSP与bean结合的例子
- 例1:
Triangle.java
源码:
package red.star;
public class Triangle {
double sideA=-1,sideB=-1,sideC=-1,area=-1;
boolean triangle;
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 double getArea() {
double p=(sideA+sideB+sideC)/2.0;
if(triangle)
area=Math.sqrt(p*(p-sideA)*(p-sideB)*(p-sideC));
return area;
}
public boolean isTriangle() {
if(sideA<sideB+sideC&&sideB<sideA+sideC&&sideC<sideA+sideB)
triangle=true;
else triangle=false;
return triangle;
}
}
example4_7.jsp
源码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body bgcolor="cyan">
<jsp:useBean class="red.star.Triangle" scope="request" id="tri"></jsp:useBean>
<form action="" method="post">
输入三角形三边:
边A:<input type="text" name="sideA" value=0 size="5">
边B:<input type="text" name="sideB" value=0 size="5">
边C:<input type="text" name="sideC" value=0 size="5">
<input type="submit" value="提交">
</form>
<jsp:setProperty property="sideA" name="tri"/>
<jsp:setProperty property="sideB" name="tri"/>
<jsp:setProperty property="sideC" name="tri"/>
三角形的三边是:
<jsp:getProperty property="sideA" name="tri"/>
<jsp:getProperty property="sideB" name="tri"/>
<jsp:getProperty property="sideC" name="tri"/>
<br>
<b>这三个边能构成三角形嘛?<jsp:getProperty property="triangle" name="tri"/>
<br>面积是:<jsp:getProperty property="area" name="tri"/></b>
</body>
</html>
- 例2:
ComputerBean.java
源码:
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;
}
}
example4_8.jsp
源码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<jsp:useBean id="computer" class="red.star.ComputerBean" scope="session"></jsp:useBean>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body bgcolor="cyan">
<jsp:setProperty property="*" name="computer"/>
<form action="" method="post" name="form">
<input type="text" name="numberOne" size="6">
<select name="operator">
<option value = "+">+
<option value = "-">-
<option value = "*">*
<option value = "/">/
</select>
<input type="text" name="numberTwo" size="6">
<br>
<input type="submit" value="提交" name="submit">
</form>
<b>
<jsp:getProperty property="numberOne" name="computer"/>
<jsp:getProperty property="operator" name="computer"/>
<jsp:getProperty property="numberTwo" name="computer"/>=
<jsp:getProperty property="result" name="computer"/>
</b>
</body>
</html>
- 例3:
Play.java
源码:
package red.star;
import java.io.*;
public class Play {
int imageNumber = 0, max;
String pictureName[],playImage;
String webDir = "";
String tomcatDir;
public Play() {
File f = new File("");
String path = f.getAbsolutePath();
int index = path.indexOf("bin");
tomcatDir = path.substring(0,index);
}
public void setWebDir(String s) {
webDir = s;
if(pictureName == null) {
File dirImage = new File(tomcatDir + "/webapps/" + webDir + "/image");
pictureName = dirImage.list();
}
if(pictureName != null) {
max = pictureName.length;
}
}
public void setImageNumber(int n) {
if(n < 0) {
n = max -1;
}
if(n == max) {
n = 0;
}
imageNumber = n;
}
public int getImageNumber() {
return imageNumber;
}
public String getPlayImage() {
if(pictureName != null)
playImage = pictureName[imageNumber];
return playImage;
}
}
example4_9.jsp
源码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<jsp:useBean id="play" class="red.star.Play" scope="session"></jsp:useBean>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body bgcolor="cyan">
<%
String webDir = request.getContextPath();
webDir = webDir.substring(1);
%>
<jsp:setProperty property="webDir" name="play" value="<%= webDir %>"/>
<jsp:setProperty property="imageNumber" name="play" param="imageNumber"/>
<image src ="image/<jsp:getProperty name="play" property="playImage"/>" width="120" height="90">
<br>这是当前显示的图像</image>
<br>单击“上一张”或“下一张”按钮浏览图像
<form action="" method="post">
<input type="submit" name="ok" value="上一张">
<input type="hidden" name="imageNumber"value="<%= play.getImageNumber() - 1 %>">
</form>
<form action="" method="post">
<input type="submit" name="ok" value="下一张">
<input type="hidden" name="imageNumber"value="<%= play.getImageNumber() + 1 %>">
</form>
</body>
</html>
- 例4:
ComputerCount.java
源码:
package red.star;
import java.io.*;
public class ComputerCount {
int number = 0;
boolean isCome = false;
File file = new File("count.dat");
private void countPeople() {
if(!file.exists()) {
number ++;
try {
file.createNewFile();
FileOutputStream out = new FileOutputStream(file);
DataOutputStream dataout = new DataOutputStream(out);
dataout.writeInt(number);
out.close();
dataout.close();
}catch(IOException ee) {
}
}else {
try {
FileInputStream in = new FileInputStream(file);
DataInputStream dataIn = new DataInputStream(in);
number = dataIn.readInt();
number ++;
in.close();
dataIn.close();
FileOutputStream out = new FileOutputStream(file);
DataOutputStream dataout = new DataOutputStream(out);
dataout.writeInt(number);
out.close();
dataout.close();
}catch(IOException ee) {
}
}
isCome = true;
}
public int getNumber() {
if(isCome == false)
countPeople();
return number;
}
}
example4_10_a.jsp
源码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<jsp:useBean id="count" class="red.star.ComputerCount" scope="session"></jsp:useBean>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body bgcolor="cyan">
<p>网站的example4_10_a.jsp页面
<br>
您是第<jsp:getProperty property="number" name="count"/>个访问者。
<a href="example4_10_b.jsp">欢迎去example4_10_b.jsp参观</a>
</body>
</html>
example4_10_b.jsp
源码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<jsp:useBean id="count" class="red.star.ComputerCount" scope="session"></jsp:useBean>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body bgcolor="cyan">
<p>网站的example4_10_b.jsp页面
<br>
您是第<jsp:getProperty property="number" name="count"/>个访问者。
<a href="example4_10_a.jsp">欢迎去example4_10_a.jsp参观</a>
</body>
</html>