在实际使用中,有几种常用的Bean,比如表单Bean、页面Bean及共享Bean。在共享Bean中主要包括请求Bean、会话Bean及应用程序Bean。
表单Bean是用来处理表单的。编写Bean,如程序FormBean.java所示。
案例名称:表单Bean使用方法
程序名称:FormBean.java
package std; //封包
import java.io.*; //引入包
public class FormBean implements Serializable //最好实现Serializable接口
{
//属性声明,都用private修饰
private int id=0;
private String nickname="";
//公开的属性
public void setId(int id)
{
this.id=id;
}
public int getId()
{
return id;
}
public void setNickname(String name)
{
this.nickname=name;
}
public String getNickname()
{
return nickname;
}
}
这个Bean里面有两个属性,都是公开属性。编写JSP文件,使用这个Bean,如程序from.jsp所示。
案例名称:表单Bean使用方法
程序名称:form.jsp
<form action="" method="post">
id:<input type=text name="id"><br>
nickname:<input type=text name="nickname"><br>
<input type=submit value="submit"/>
</form>
<jsp:useBean id="st" class="std.FormBean"/>
<jsp:setProperty name="st" property="*"/>
<hr/>
<jsp:getProperty name="st" property="id"/><br>
<jsp:getProperty name="st" property="nickname"/>
注意这里的Bean放在包std中,在Eclipse中创建好工程以后的目录结构如图6-10所示。
图6-10 使用表单Bean的目录结构
这种方法利用表单中对应name的表单域的值去填充Bean里面相应的属性。例子中,id被填充到Bean的id属性中,nickname被填充到Bean的nickname属性。打开时,读取了id的值0,nickname 默认为空。执行的结果如图6-11所示。
图6-11 使用setProperty动作
也可以使用jsp:setProperty动作对每一个属性设置值,如程序form1.jsp所示。
案例名称:表单Bean使用方法
程序名称:form1.jsp
<form action="" method="post">
myid:<input type=text name="myid"><br>
mynickname:<input type=text name="mynickname"><br>
<input type=submit value="submit"/>
</form>
<jsp:useBean id="st" class="std.FormBean"/>
<jsp:setProperty name="st" property="id" param="myid"/>
<jsp:setProperty name="st" property="nickname" param="mynickname"/>
<hr/>
<jsp:getProperty name="st" property="id"/><br>
<jsp:getProperty name="st" property="nickname"/>
在这里,html表单的表单域名称与Bean中的属性并不一致,使用param来把html表单的表单域名称与Bean中的属性对应起来。运行结果如图6-12所示。
图6-12 调用表单Bean
表单Bean用来处理表单的填充。如果没有请求参数和属性对应(比如,修改FormBean,增加一个sex属性),则不采取任何动作,系统不会提供null作为属性的值。这意味着,表单Bean不需要一次填充完毕,可以只填充一部分属性。
自动类型转换并不能像手动类型转换那样能够防止不合法的值。尽管自动类型转换很方便(从请求中获得的值为String类型,自动类型转换保证了上面的String类型的id填充了int类型的id属性),很多开发人员还是避免使用自动转换,选择使用 String类型去定义Bean的每个属性。
Bean属性的名称和请求参数大小写敏感,书写错误就无法调用任何一个动作(id和ID是不同的)。
页面Bean为JSP保留数据,不实现应用程序流中的任何功能。在JSP和Servlet之间,有4种不同的范围值,如表6-1所示。
表6-1 Bean的4种不同范围
范围级别 |
所影响的API |
注 释 |
页面page |
服务方法中的本地变量 |
只用于正在处理的Servlet,无法通过这些方法在JSP和Servlet之间共享数据 |
请求request |
request.setAttribute(key,obj) request.getAttribute(key) |
用于正在处理的Servlet和接受转发控制的Servlet或JSP |
会话session |
session.setAttribute(key,obj) session.getAttribute(key) |
用于相同范围内的任何Servlet或JSP |
应用程序application |
getServletContext() setAttribute(key,obj) getAttribute(key) |
对象包含应用程序范围内的对象 |
可以这样去理解共享Bean的概念:在一个JSP页面(或Servelet)中修改了Bean的属性,然后在另一个页面中读取这个Bean的属性,可以看到这种变化。这是实现数据共享的一种重要方式,也是MVC架构的基础。
Bean一共有4种范围(Scope):page、request、session和application。page对应于本页面的使用,是不可以共享的Bean。后3种都可以共享,范围递增。第1种在request范围内共享,第2种在session范围内共享,第3种在整个应用程序中共享。在共享Bean的应用中,使用forward和include 方法来完成请求的转发和包含。除了这两种方法之外,其他的方法是无效的或不建议使用的。这里所描述的案例是JSP之间共享Bean,也可以是JSP与Servlet之间或Servlet与Servlet之间共享Bean。比如默认的页面Bean不能共享数据,如程序scopePagea.jsp所示。
案例名称:页面Bean
程序名称:scopePagea.jsp
<jsp:useBean id="st" class="std.FormBean"/>
<jsp:setProperty name="st" property="id" value="999"/>
<jsp:forward page="scopePageb.jsp"/>
执行scopePagea.jsp的时候,自动转移到scopePageb.jsp页面。
案例名称:页面Bean
程序名称:scopePageb.jsp
<jsp:useBean id="st" class="std.FormBean"/>
<jsp:getProperty name="st" property="id"/><br>
scopePageb.jsp主要用来读取页面Bean的属性,运行结果如图6-13所示。
图6-13 Page范围
可以看到,在scopePageb.jsp中读取到的id属性值为0,这说明page范围的Bean无法共享。
请求Bean即Request Bean,是在request范围内共享数据的Bean。修改前面的例子,如程序scopeRequesta.jsp所示。
案例名称:请求Bean
程序名称:scopeRequesta.jsp
<jsp:useBean id="st" class="std.FormBean" scope="request"/>
<jsp:setProperty name="st" property="id" value="999"/>
<jsp:forward page="scopeRequestb.jsp"/>
和页面Bean区别是使用Bean的时候带上了“scope="request"”,页面还是自动转到了scopeRequestb.jsp页面上。
案例名称:请求Bean
程序名称:scopeRequestb.jsp
<jsp:useBean id="st" class="std.FormBean" scope="request"/>
<jsp:getProperty name="st" property="id"/>
程序执行结果如图6-14所示。
图6-14 请求范围
发出请求的JSP或Servlet修改的属性值在接受请求的JSP或Servlet中可以读出来,但是,如果两个程序之间没有发生请求关系的话,数据就无法共享。如果编写一个独立的JSP程序,修改了Bean的属性值,scope为request。再写一个JSP程序,scope为request,它并不接受第一个JSP的请求,无法读取修改了的Bean的属性值。
会话Bean属于应用程序的用户会话,与表示方式无关,但是却可以获得指向资源和其他数据的引用,这些数据有助于用户会话来维护和保存状态信息。例如,一个会话Bean可以通过会话保存用户的姓名和地址。
会话Bean即Session Bean,在session 范围内共享数据。它的作用范围比请求Bean大很多。即使两个文件没有发生请求关系,但是也可以共享数据,如程序scopeSessiona.jsp所示。
案例名称:会话Bean
程序名称:scopeSessiona.jsp
<jsp:useBean id="st" class="std.FormBean" scope="session"/>
<jsp:setProperty name="st" property="id" value="999"/>
<a href="scopeSessionb.jsp">to b</a>
会话Bean使用“scope="session"”进行标识,单击超级链接后,自动转到另外一个页面,如程序scopeSessionb.jsp所示。
案例名称:会话Bean
程序名称:scopeSessionb.jsp
<jsp:useBean id="st" class="std.FormBean" scope="session"/>
<jsp:getProperty name="st" property="id"/>
运行结果如图6-15所示。
图6-15 会话范围
到另外一个页面后,同样可以看到Bean属性的值,如图6-16所示。
图6-16 会话范围
这里必须单击链接进入,否则两个页面不在相同的会话中,无法共享数据。
应用程序Bean的作用范围比会话Bean要广,可以用来帮助应用程序的所有用户维持状态。与会话Bean相比,使用它们的机会少一些,但是,如果需要减少内存的消耗或提升显示的效果,使用该应用程序Bean是非常有用的,特别是当许多用户需要存取资料而这些资料的获取成本相对较高时。
应用程序Bean即Application Bean,在application 范围内共享数据。它的范围是最大的。两个文件没有发生请求关系,也不是连在一起的页面,但它们之间可以共享数据。因为application范围是整个应用程序中的所有文件,如程序scopeApplicationa.jsp所示。
案例名称:应用程序Bean
程序名称:scopeApplicationa.jsp
<jsp:useBean id="st" class="std.FormBean" scope="application"/>
<jsp:setProperty name="st" property="id" value="999"/>
这个页面中设置Bean属性的值,试图在另外一个页面中读取出来,其程序如下。
案例名称:应用程序Bean
程序名称:scopeApplicationb.jsp
<jsp:useBean id="st" class="std.FormBean" scope="application"/>
<jsp:getProperty name="st" property="id"/>
先执行scopeApplicationa.jsp,然后再执行scopeApplicationb.jsp,发现数据还是传过来了,如图6-17所示。
图6-17 应用程序范围Bean
<!-- page -->