Java Web之JSP使用Java Bean
write:2022-4-21
前文我们学习了java的会话:Java Web之Session,这节课我们学习java bean,如果在java文件中嵌入大量的java程序片段,会降低jsp的可读性并使jsp的调试跟踪维护变得复杂,因此需要将这些java片段放在java bean中,只需在jsp中通过标签访问这些java bean即可。
文章目录
1.了解JavaBean的概念
1)JavaBean是一种可重复使用、且跨平台的软件组件。
2)JavaBean可分为两种:
一种是有用户界面(UI,User Interface)的JavaBean;
还有一种是没有用户界面,主要负责表示业务数据或者处理事务(如数据运算,操纵数据库)的JavaBean。
3)JSP通常访问的是后一种JavaBean。
2. Java Bean的特征(规范)
一个标准的JavaBean有以下几个特性:
JavaBean是一个公共的(public)类
JavaBean有一个不带参数的构造方法
JavaBean通过setXXX方法设置属性,通过getXXX方法获取属性。如果属性名为“xyz”,那么get方法名为“getXyz”,set方法名为“setXyz”,属性名中的第一个字母在方法名中改为大写。
为什么要有上述的规范:因为Java Bean的出现就是为了使它能够像标准零件一样具有广泛的通用性,都遵守一样得规范,才能被jsp页面以同样的方式访问。
eg:
package mypack;
public class CounterBean{
private int count=0; //定义count属性
public CounterBean(){} //不带参数的构造方法
public int getCount(){ //读取count属性
return count;
}
public void setCount(int count){ //设置count属性
this.count=count;
}
}
假定把CounterBean类发布到helloapp应用中,它的存放位置是:
helloapp/WEB-INF/classes/mypack/CounterBean.class
3. 掌握JSP访问JavaBean的语法
3.1 导入JavaBean类
通过<%@ page import>指令导入JavaBean类,例如: <%@ pageimport=“mypack.CounterBean” %>
(注意:名字必须完整,因此包名也必须包含进来)
3.2 声明JavaBean对象
jsp:useBean标签用来声明JavaBean对象,例如:
<jsp:useBean id=“myBean” class=“mypack.CounterBean” scope=“session” />
id:为所声明的Java Bean对象所提供的唯一的标识符(也就是存放范围内的属性名);scope:Java Bean存在的范围(有四个可选值:page(默认值),request,session,application)
以上jsp:useBean标签和以下Java程序片段的作用是等价的:
<%
mypack.CounterBean myBean = null; //定义myBean局部变量
//试图从会话范围内读取myBean属性
myBean = (mypack.CounterBean) session.getAttribute("myBean");
if (myBean == null){ //如果会话范围内不存在myBean属性
myBean = new mypack.CounterBean();
session.setAttribute("myBean", myBean);
} %>
显然使用jsp:useBean标签代码更简洁。
3.3 读取以及设置JavaBean属性
- 访问Java Bean属性
JSP提供了访问JavaBean属性的标签,如果要将JavaBean的某个属性输出到网页上,可以用jsp:getProperty标签,例如:
<jsp:getProperty name=“myBean” property=“count” />
name:待访问的Java Bean的名字(与前面jsp:useBean标签的id对应);property:待访问的Java Bean的属性名 - 属性赋值
如果要给JavaBean的某个属性赋值,可以用jsp:setProperty标签,例如:
<jsp:setProperty name=“myBean” property=“count” value=“0” />
这个标签是把名为myBean的Java Bean的count属性赋值为0.
4. 理解JavaBean的四种范围
<jsp:useBean id=“myBean” class=“mypack.CounterBean” scope=“session” />中的scope属性,scope属性决定了JavaBean对象存在的范围。scope的可选值包括:
page(默认值)页面范围
request 请求范围
session 会话范围
application 应用范围
同一个Java Bean可以被多个web组件访问,但因被访问的范围不同有不同的生命周期。
4.1 JavaBean在page范围内
客户每次请求访问JSP页面时,都会创建一个JavaBean对象。JavaBean对象的有效范围是客户请求访问的当前JSP网页。
JavaBean对象在以下两种情况下都会结束生命期:
客户请求访问的当前JSP网页通过jsp:forward标记将请求转发到另一个文件
客户请求访问的当前JSP页面执行完毕并向客户端发回响应。
eg:
pageCounter.jsp
<%@ page import="mypack.CounterBean" %>
<html><head><title>Counter</title></head><body>
<jsp:useBean id="myPageBean" scope="page"class="mypack.CounterBean" />
<%-- 把myPageBean的count属性的值加1 --%>
<jsp:setProperty name="myPageBean" property="count"
value="<%=myPageBean.getCount()+1 %>" />
<%-- 打印myPageBean的count属性 --%>
Current count value is :<jsp:getProperty name="myPageBean" property="count" />
<%
String scopeNames[]={"No scope","page","request","session","application"};
//寻找myPageBean的范围
int scope=pageContext.getAttributesScope("myPageBean"); //getAttributesScope()方法获得某个Java Bean的范围
%>
<%--打印myPageBean的范围 --%>
<p>scope=<%=scopeNames[scope]%></p>
</body></html>
运行:
(1)通过浏览器第一次访问
http://localhost:8080/helloapp/pageCounter.jsp,将会看到网页上的内容如下:
Current count value is :1
scope=page
(2)通过浏览器多次访问pageCounter.jsp,会看到CounterBean对象的count属性的值始终为1。(因为每次访问jsp:useBean标签都创建一个新的CounterBean对象,count属性初始值为0)
4.2 JavaBean在request范围内
-
客户每次请求访问JSP页面时,都会创建新的JavaBean对象。
-
JavaBean对象的有效范围为:
客户请求访问的当前JSP网页;
和当前JSP网页共享同一个客户请求的网页,即当前JSP网页中<%@ include>指令以及jsp:forward标签包含的其他JSP文件
-
当所有共享同一个客户请求的JSP页面执行完毕并向客户端发回响应时,JavaBean对象结束生命周期。
-
JavaBean对象作为属性保存在HttpServletRequest对象中,属性名为jsp:useBean标签中JavaBean的id,属性值为JavaBean对象。相当于执行以下语句:request.setAttribute(“myBean”,mybean);
-
JSP还可以通过HttpServletRequest.getAttribute()方法
取得JavaBean对象,例如:
<%CounterBean obj=(CounterBean)request.getAttribute(“myBean”);%> -
eg:requestCounter1.jsp
<%@ page import="mypack.CounterBean" %>
<html><head><title>Counter</title></head><body>
<jsp:useBean id="myRequestBean" scope="request" class="mypack.CounterBean" />
<jsp:setProperty name="myRequestBean" property="count"
value="<%=myRequestBean.getCount()+1 %>" />
Current count value is :<jsp:getProperty name="myRequestBean" property="count" />
<%
String scopeNames[]={"No scope","page","request","session","application"};
int scope=pageContext.getAttributesScope("myRequestBean");
%>
<p>scope=<%=scopeNames[scope]%></p>
</body></html>
运行:
(1)通过浏览器第一次访问
http://localhost:8080/helloapp/requestCounter1.jsp,将会看到网页上的内容如下:
Current count value is :1
scope=request
(2)通过浏览器多次访问requestCounter1.jsp,会看到CounterBean对象的count属性的值始终为1。
接下来
修改requestCounter1.jsp:
<p>scope=<%=scopeNames[scope]%></p>
<jsp:forward page="requestCounter2.jsp" />
requestCounter2.jsp:
<%@ page import="mypack.CounterBean" %>
<html>
<head>
<title>
Counter
</title>
</head>
<jsp:useBean id="myRequestBean" scope="request" class="mypack.CounterBean" />
<body>
Current count value is :<jsp:getProperty name="myRequestBean" property="count" />
</body>
</html>
运行:
(1)通过浏览器第一次访问
http://localhost:8080/helloapp/requestCounter1.jsp,将会看到网页上的内容如下:
Current count value is :1
scope=request
执行requestCounter1.jsp,Servlet容器创建名为myRequestBean的Java Bean对象,count值为1,请求转发到requestCounter2.jsp,发现已经有名为myRequestBean的Java Bean对象,因此Servlet容器不再创建新的Java Bean对象,因为requestCounter1.jsp与requestCounter2.jsp共享HttpServletRequest对象,也共享存放在HttpServletRequest里的myRequestBean以及属性,因此count值为1,当requestCounter2.jsp响应结果回到客户端,因此本次请求完全结束,HttpServletRequest对象结束生命周期,存放在其中的myRequestBean也结束生命周期。
(2)通过浏览器多次访问requestCounter1.jsp,会看到CounterBean对象的count属性的值始终为1。
4.3 JavaBean在session范围内
- JavaBean对象被创建后,它存在于整个Session的生命周期内,同一个Session中的JSP文件共享这个JavaBean对象。(只创建一个Java Bean对象)
- 一个HTTP会话中会包含多个“请求/响应”回合。
- JavaBean对象作为属性保存在HttpSession对象中,属性名为jsp:useBean标签中的JavaBean的id,属性值为JavaBean对象。相当于执行以下语句:session.setAttribute(“myBean”,mybean);
- JSP也可以通过HttpSession.getAttribute()方法取得JavaBean对象,例如:
<%CounterBean obj=(CounterBean)session.getAttribute(“myBean”);%> - eg:
sessionCounter.jsp:
<%@ page import="mypack.CounterBean" %>
<html><head><title>Counter</title></head>
<body>
<jsp:useBean id="mySessionBean" scope="session" class="mypack.CounterBean" />
<jsp:setProperty name="mySessionBean" property="count"
value="<%=mySessionBean.getCount()+1 %>" />
Current count value is :<jsp:getProperty name="mySessionBean" property="count" />
<%
String scopeNames[]={"No scope","page","request","session","application"};
int scope=pageContext.getAttributesScope("mySessionBean");
%>
<p>scope=<%=scopeNames[scope]%></p>
</body></html>
运行:
1)通过浏览器第一次访问
http://localhost:8080/helloapp/sessionCounter.jsp,将会看到网页上的内容如下:
Current count value is :1
scope=session
(2)通过当前浏览器多次访问sessionCounter.jsp,会看到CounterBean对象的count属性的值不断递增。
(3)再打开一个新的浏览器,通过它多次访问sessionCounter.jsp,会看到CounterBean对象的count属性的值从1开始不断递增。(新的浏览器开始新的会话,两个会话独立的,拥有各自的Java Bean对象,不过名字都叫mysessionBean)
4.4 JavaBean在application范围内
- JavaBean对象被创建后,它存在于整个Web应用的生命周期内,Web应用中的所有JSP文件在任何时候都能共享同一个JavaBean对象。
- JavaBean对象作为属性保存在ServletContext对象中,属性名为jsp:useBean标签中JavaBean的id,属性值为JavaBean对象,相当于执行以下语句:application.setAttribute(“myBean”,mybean);
- JSP中也可以通过application.getAttribute()方法取得JavaBean对象,例如:
<%CounterBean obj=(CounterBean)application.getAttribute(“myBean”);%> - eg:
applicationCounter.jsp:
<%@ page import="mypack.CounterBean" %>
<html><head><title>Counter</title></head><body>
<jsp:useBean id="myApplicationBean" scope="application" class="mypack.CounterBean" />
<jsp:setProperty name="myApplicationBean" property="count"
value="<%=myApplicationBean.getCount()+1 %>" />
Current count value is :<jsp:getProperty name="myApplicationBean" property="count" />
<%
String scopeNames[]={"No scope","page","request","session","application"};
int scope=pageContext.getAttributesScope("myApplicationBean");
%>
<p>scope=<%=scopeNames[scope]%></p>
</body></html>
运行:
(1)通过浏览器第一次访问
http://localhost:8080/helloapp/applicationCounter.jsp,将会看到网页上的内容如下:
Current count value is :1
scope=application
(2)通过当前浏览器多次访问applicationCounter.jsp,会看到CounterBean对象的count属性的值不断递增。(当前应用范围内只有一个名为myApplicationBean的对象)
(3)再打开一个新的浏览器,通过它多次访问applicationCounter.jsp,会看到CounterBean对象的count属性的值在第一个浏览器中看到的最后值的基础上不断递增。(不同的浏览器访问的始终是同一个myApplicationBean对象)
(4)重新启动helloapp应用,再通过浏览器多次访问applicationCounter.jsp,会看到CounterBean对象的count属性的值又从1开始不断递增。(上次一关闭应用时,与它关联的JavaBean对象也就终止生命周期,重新启动,Servlet容器会创建新的JavaBean对象)
5. JSP与JavaBean搭配使用的优点
1)使得HTML与Java程序分离,这样便于维护代码。如果把所有的程序代码都写到JSP网页中,会使得代码繁杂,难以维护
2)可以降低开发JSP网页人员对Java编程能力的要求
3)JSP侧重于生成动态网页,事务处理由JavaBean来完成,这样可以充分利用JavaBean组件的可重用性特点,提高开发网站的效率
6. 练习题
- 问题:以下jsp:useBean等价于哪段JSP程序代码?
<jsp:useBean id=“myBean” class=“mypack.CounterBean”
scope=“session” />
选项 (A)
<%
CounterBean myBean=(CounterBean)session.getAttribute(“myBean”);
if(myBeannull){
myBean=new CounterBean();
session.setAttribute(“myBean”,myBean);
}
%>
选项 (B)
<%
CounterBean myBean=(CounterBean)session.getAttribute(“CounterBean”);
if(myBeannull){
myBean=new CounterBean();
session.setAttribute(“CounterBean”,myBean);
}
%>
<jsp:useBean id=“myBean” class=“mypack.CounterBean”
scope=“session” />
选项 ©
<%
CounterBean myBean=(CounterBean)session.getAttribute(“myBean”);
if(myBean==null)
myBean=new CounterBean();
}
%>
答案: A - 问题:对于:
<jsp:useBean id=“myBean”
class=“mypack.CounterBean” scope=“application" />
如何输出myBean的count属性?
选项:
(A) <jsp:getProperty name=“myBean” property=“count” />
(B)
<% CounterBean counterBean=(CounterBean)application.getAttribute(“myBean”); %>
<%=counterBean.getCount()%>
©
<% CounterBean counterBean=application.getAttribute(“myBean”);%>
<%=counterBean.getCount()%>
答案:A,B
注意:application.getAttribute()方法的返回类型是object类型,需要进行强制类型转换,转换为CounterBean类型
-
问题:mypack.CounterBean类的类文件应该发布到helloapp应用的什么目录下?
选项:
(A) /helloapp
(B) /helloapp/WEB-INF/
© /helloapp/WEB-INF/classes
(D) /helloapp/WEB-INF/classes/mypack
答案:D -
问题:在JSP页面中通过jsp:useBean标签来访问JavaBean,而不是通过<% …%>Java程序片段来访问JavaBean,有什么好处?
答案:把程序代码与JSP网页分离,使JSP网页更加简洁,可维护。 -
问题:为什么JavaBean必须遵守特定的规范,比如对于CounterBean的count属性,其get和set方法应该为getCount()和setCount()方法,而不能随心所欲的定义为getCOunt()、insertcount()等等其他名字?
答案:当所有JavaBean遵守相同的规范,jsp:getProperty和jsp:setProperty标签就能自动根据JavaBean的属性来推断出它的get和set访问方法。(因为如果JavaBean遵守相同的规范,那么使用Java Bean的系统就可以按照统一的方式来访问Java Bean)