JSP与Javabean
按照Sun公司的定义,Javabean是一个可重复使用的软件组件,实际上Javabean是一种类,通过封装属性和方法成为具有某种功能或者处理某个失误的对象,简称bean,由于Javabean是基于Java语言的,因此Javabean不依赖平台,具有以下优点:
(1)可以实现代码的复用性。
(2)易编写、易维护、易使用。
(3)可以在任何安装了Java运行环境的平台上使用,而不需要重新编译。
Javabean分为可视组件和非可视组件,在JSP中主要使用非可视组件,对于非可视组件,我们不必设计他的外观,主要关心他的属性和方法。
编写Javabean就是编写一个Java类,所以只要会写类就能编写一个Javabean,这个类创建的一个对象称为Javabean,简称bean。为了能让使用这个bean的应用程序构建工具(比如JSP引擎)知道这个bean的属性和方法,只须在类的方法命名上遵守一下规则:
(1)如果类的成员变量的名字是xxx,那么为了获取或更改成员变量的值,即获得或更改属性,类中必须提供两个方法:
getXxx();//用来获取属性xxx setXxx();//用来修改属性xxx
(2) 对于boolean类型的成员变量,允许使用“is”代替上面的get和set。
(3)类中声明的方法的访问属性都必须是public的。
(4)类中声明的构造方法必须是public、无参数的。
1.保存bean字节码
为了使JSP页面使用bean,服务器必须使用相应的字节码创建一个对象。为了让服务器能找到字节码文件,字节码文件必须保存在特定的目录中。
我们在Web服务目录下的WEB-INF下建立文件 classes,将该文件夹作为根目录保存字节码文件,也就是说比如某类package out; 那么它对应的字节码文件应该保存在WEB-INF/classes/out下。
2.创建与使用bean
格式:
<jsp:useBean id="bean的名字" class="创建bean的字节码文件" scope="有效范围" />
或者
<jsp:useBean id="bean的名字" class="创建bean的字节码文件" scope="有效范围" > </jsp:useBean>
需要特别注意的是,class中的值需要带有包名。
bean的有效范围(后面会有代码和执行效果,有点难理解,多看下代码和文字说明)
这个有效范围就是上面scope决定的,取值有4个,page、session、request、application。
scope的取值决定了JSP引擎分配给用户的bean存活时间,因此需要理解具体意义。
当取page时
回想JSP的运行原理和<%%> java程序片,在每一个用户访问JSP页面时,都会又一个全新的线程执行程序片里的内容,和其他用户不产生关系和影响。当scope取page时,当页面执行完毕,JSP引擎就会释放bean所占用的内存,即作用于只在当前页面有效。同时,一个用户对bean操作不会影响其他用户。
当取request时
request的作用于就是整个请求,发送,执行,响应的一个完整的过程,当做出响应之后,JSP引擎释放bean所占用的内存。这个范围略大于page,因为包含了持续连接(HTTP1.1 及以上支持了持续连接)和请求转发等情况。
当取session时
和session对象的作用区间一样,同一用户,同一Web服务目录下,发呆时间内有效。
当取application时
从服务器一开始执行服务,一直到服务器关闭为止。全局作用。一个用户对其的更改会影响所有用户。
我们下面贴出几个代码,然后演示下这几种属性值。
example4_1.jsp
<%@ page contentType="text/html;charset=GB2312" %> <%@ page import="out.Circle"%> <HTML><BODY bgcolor=white><Font size=3> <jsp:useBean id="circle" class="out.Circle" scope="page" /> <%--通过上述JSP标记,客户获得了一个作用域是page,名字是circle的bean --%> <% circle.setRadius(888); %> <P>圆的半径是:<%=circle.getRadius()%> <P>圆的周长是:<%=circle.circlLength()%> <P>圆的面积是:<%=circle.circleArea()%> <A href="/myfile/next.jsp"><BR>next.jsp </A> </BODY></HTML>
example4_2.jsp
<%@ page contentType="text/html;charset=GB2312" %> <%@ page import="out.Circle"%> <HTML><BODY bgcolor=white><Font size=3> <jsp:useBean id="girl" class="out.Circle" scope="session" /> <%girl.setRadius(300);%> <P>圆的半径是: <%=girl.getRadius()%> <A href="/myfile/next.jsp"><BR>next.jsp </A> </BODY></HTML>
next.jsp
<%@ page contentType="text/html;charset=GB2312" %> <%@ page import="out.Circle"%> <HTML><BODY bgcolor=white><Font size=3> <jsp:useBean id="girl" class="out.Circle" scope="session" /> <P>圆的半径是: <%=girl.getRadius()%> <%girl.setRadius(400);%> <P>修改后的圆的半径是:<%=girl.getRadius()%> <A href="../example4_2.jsp"><BR>example4_2.jsp </A> </BODY></HTML>
example4_3.jsp
<%@ page contentType="text/html;charset=GB2312" %> <%@ page import="out.*"%> <HTML> <BODY> <jsp:useBean id="girl" class="out.Circle" scope="application" > </jsp:useBean> <P>圆的初始半径是:<%=girl.getRadius()%> <%girl.setRadius(1000);%> <P>修改后的圆的半径是:<%=girl.getRadius()%> </BODY></HTML>
page示例:
request示例:
可以看到只要不刷新页面,该bean都生效(这里可以去看代码仔细思考下)
作为对比,我们看如果是page,跳转之后是什么样子。
session不做演示。
最后是application,我们使用2个浏览器,访问发现其中一个页面做出的更改对另一个用户的访问产生了影响。
最后简单说下bean的工作原理:用户访问页面时,JSP引擎会查找pageContent对象中是否含有这种的bean,如果有,则直接为用户分配,如果没有,则根据class指定的字节码创建一个JSP动作标记useBean要求的bean,并将所创建的bean添加到pageContent内置对象中,加速下次使用。
需要注意的是:如果修改了字节码文件,需要重启服务器才能使用新的字节码文件。(因为添加到pageContent内置对象中了,不再读取字节码文件)
2.获取和修改bean的属性
1.getProperty动作标记
使用getProperty动作标记可以获得bean的属性值,并将这个值用串的形式发送给用户的浏览器。
格式:
<jsp:getProperty name="bean的id的名字" property= "bean的属性"/>
或者
<jsp:getProperty name="bean的id的名字" property= "bean的属性"> </jsp:getProperty>
该指令相当于java表达式
<%= bean.getXxx() %>
2.setProperty动作标记
使用setProperty动作标记可以设置bean的属性值。
setProperty动作标记可以通过两种方式设置bean属性的值。
(1)将bean属性的值设置为一个表达式的值或者字符串。
格式:
<jsp:setProperty name="bean的id的名字" property= "bean的属性" value="<%= 表达式%>/>
或者
<jsp:setProperty name="bean的id的名字" property= "bean的属性" value=字符串> </jsp:setProperty>
(2) 通过HTTP表单的参数的值来设置bean的相应属性的值。
通过当前JSP页面或请求本页面的其他页面中的HTTP表单的参数的值来设置bean的相应属性的值。
用HTTP表单的所有参数的值设置bean相对应的属性值的使用格式如下:
<jsp:setProperty name="bean的id的名字" property= "*"/>
在setProperty标记的上述用法不具体指定bean属性的值将对应表单中哪个参数指定的值,系统会自动根据名字进行匹配对应,但要求bean属性的名字必须在表单中有名称相同的参数名字相对应,JSP引擎会自动将参数的字符串值转换为bean相对应的属性的值。
如果名称不一致,需要使用以下的方法:
<jsp:setProperty name="bean的名字" property="属性名" param="参数名"/>
(表单中的名字为参数名,bean中的名字为属性名)
下面栗子演示了set和get的用法,需要注意,Student的字节码文件应放在classes下对应的目录下才行。
example4_4.jsp
<%@ page contentType="text/html;charset=GB2312" %> <%@ page import="out.Student"%> <HTML><BODY bgcolor=white><Font size=3> <jsp:useBean id="zhang" class="out.Student" scope="page"/> <jsp:setProperty name="zhang" property="name" value="张三"/> 名字是:<jsp:getProperty name="zhang" property="name"/> <jsp:setProperty name="zhang" property="number" value="2008001"/> <BR>学号是:<jsp:getProperty name="zhang" property="number"/> <jsp:setProperty name="zhang" property="height" value="<%=1.78%>"/> <BR>身高是:<jsp:getProperty name="zhang" property="height"/> 米 <jsp:setProperty name="zhang" property="weight" value="67.65"/> <BR>体重是:<jsp:getProperty name="zhang" property="weight"/> 公斤 </FONT></BODY></HTML>
Student.java
package out; public class Goods { String name,goodsNumber; double price; public String getName() { return name; } public void setName(String newName) { name=newName; } public String getGoodsNumber() { return goodsNumber; } public void setGoodsNumber(String s) { goodsNumber=s; } public double getPrice() { return price; } public void setPrice(double newPrice) { price=newPrice; } }
演示结果。
下面是一个基于bean的计数器
example4_10.jsp
<%@ page contentType="text/html;Charset=GB2312" %> <%@ page import="out.*" %> <jsp:useBean id="count" class="out.ComputerCount" scope="session"/> <HTML><BODY bgcolor=white><Font size=3> <P>Welcome欢迎您访问本站,这是本网站的comeOne.jsp页面 <BR>您是第 <jsp:getProperty name="count" property="number"/> 个访问本网站的客户。 <A href="example4_10_b.jsp">欢迎去comeTwo.jsp参观</A> </BODY></HTML>
example4_10_b.jsp
<%@ page contentType="text/html;Charset=GB2312" %> <%@ page import="out.*" %> <jsp:useBean id="count" class="out.ComputerCount" scope="session"/> <HTML><BODY bgcolor=white><Font size=3> <P>Welcome欢迎您访问本站,这是本网站的example4_10_b.jsp页面 <BR>您是第 <jsp:getProperty name="count" property="number"/> 个访问本网站的客户。 <A href="example4_10.jsp">欢迎去example4_10.jsp参观</A> <A href="example4_10.jsp">欢迎去example4_10.jsp参观</A> </BODY></HTML>
CoumpterCount.java
package out; 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; } }
因为上述程序用的是scope属性是session,所以对于同一个session周期只计时一次,我们可以在解压目录中的bin下找到我们用于计次的count.dat文件。
同时我们也应该注意到,这个java程序并不是线程安全的,文件输入流输出流并不是线程安全,这样写会导致因为因为多线程操作导致一些意料之外的问题。解决方法就是加上线程锁。
课后题:
1.假设Web服务目录mymoon中的JSP页面要使用一个bean,该bean的包名为blue.sky。请说明,应当怎样保存bean的字节码。
· 在mymoon下的WEB-INF下创建classes/blue/sky,将bean的.java文件编译成字节码文件,存放到前面说的目录下。
2.tom.jiafei.Circle是创建bean的类,下列哪个标记是正确创建session周期bean的标记? ( C )
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”/>
3.假设创建bean的类又一个int型的属性number,下列那个方法是设置该属性值的正确方法? ( A )
A.
public void setNumber(int n) { number=n; }
B.
void setNumber(int n) { number=n; }
C.
public void SetNumber(int n) { number=n; }
D.
public void Setnumber(int n) { number=n; }
4.假设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:getProperty name="moon" property="number"/>
· 不允许
5.编写一个JSP页面,该页面提供一个表单,用户可以通过表单输入梯形的上底、下底和高的值,并提交给本JSP页面,该JSP页面将计算机梯形的面积值任务交给一个bean去完成。JSP页面使用getProerty动作标记显示梯形的面积。
example5.jsp
<%@ page contentType="text/html;charset=gb2312"%> <%@ page import="out.*"%> <jsp:useBean id="compute" class="out.Computer" scope="page"/> <form action="" method="post"> 上底<input type="text" name="upper"> 下底<input type="text" name="lowwer"> 高<input type="text" name="height"> <input type="submit" value="提交"> </form> <jsp:setProperty name="compute" property="*"/> 梯形的面积是:<%=compute.getArea()%>
computer.java
package out; public class Computer { int upper; int lowwer; int height; public double getArea(){ return (upper+lowwer)*height/2; } public int getUpper(){ return upper; } public void setUpper(int n){ upper = n; } public int getLowwer(){ return lowwer; } public void setLowwer(int n){ lowwer = n; } public int getHeight(){ return height; } public void setheight(int n){ height=n; } }
运行效果:
6.编写两个JSP页面a.jsp和b.jsp,a.jsp页面提供一个表单,用户可以通过表单输入矩形的两个边长提交给b.jsp页面,b.jsp调用一个bean去完成计算矩形面积的任务。b.jsp页面使用getProperty动作标记显示矩形的面积。
a.jsp
<%@ page contentType="text/html;charset=gb2312"%> <form action="b.jsp" method="post"> 长<input type="text" name="length"> 宽<input type="text" name="wide"> <input type="submit" value="提交"> </form>
b.jsp
<%@ page contentType="text/html;charset=gb2312"%> <%@ page import="out.*"%> <jsp:useBean id="compute" class="out.ComputeArea" scope="page"/> <% String length = request.getParameter("length"); String wide = request.getParameter("wide"); %> <jsp:setProperty name="compute" property="*"/> <%=compute.getArea()%>
ComputeArea.java
package out; public class ComputeArea{ private double length; private double wide; public double getLength() { return length; } public void setLength(double length) { this.length = length; } public double getWide() { return wide; } public void setWide(double wide) { this.wide =wide; } public double getArea(){ return length*wide; } }
0 条评论