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;
  }
}

 
 

分类: JSP

0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用 * 标注