一、JavaBean的概念
1、JavaBean就是MVC设计模式中的model层
2、种类:数据bean(pojo),逻辑bean
数据bean分为:
- 表单bean
封装表单里的参数,属性名字、个数和类型要和表单的参数的名字、个数和类型一致。
- 结果bean
封装外部的信息,主要是封装数据库的记录。要求属性名字、个数、类型 和数据库里的字段名字、个数、类型一致。又叫实体类
逻辑bean分为:
- 业务bean
又叫业务层,作用是完成对请求的操作
- 持久bean
又叫dao或数据访问层。作用是完成对外部数据操作的封装
3、Javabean优点
- 提高代码的可复用性
对于通用的事务处理逻辑,数据库操作等都可以封装在JavaBean中,通过调用JavaBean的属性和方法可以快速进行程序设计
- 程序易于开发维护
实现逻辑的封装,使事务处理和显示互不干扰
- 支持分布式应用
4、bean的语法要求
表单bean:自动完成对表单数据的收集 。如我们做的银行系统中的 userBean,就是一个表单bean。
public class SimpleBean{
private String name;
private String password;
public SimpleBean(){
}
public void getName(){
}
public void setName(){
}
}
- 必须放在包对应的目录结构下—所有的JavaBean必须放在一个包里
- 是一个主类public。类名和文件名一样。和任何接口、类没有联系
- 属性要隐藏,要和表单里的参数名、类型一样或者或数据里的字段名、类型一致
- 属性是private ,不能允许外部直接访问,对每一个属性设定get、set方法。外部需要通过相应的方法来操作属性
- 要显式的写无参构造方法 。通过有参构造的方式去设定属性值往往比较麻烦,所以用无参构造出bean的对象,然后通过调用set方法来设定属性值
二、JavaBean的使用
2.1、创建JavaBean
1、创建JavaBean
- 通过java代码创建bean对象
<%@page contentType="text/html;charset=gb2312"%>
<%@page import="cn.zte.pxb.*"%>
<%
// 实例化对象
SimpleBean zs = new SimpleBean() ;
zs.setName ("lisa");
zs.setPassword("123456") ;
%>
<h1>姓名:<%=zs.getName()%></h1>
<h1>密码:<%=zs.getPassword()%></h1>
- 通过标签创建bean对象
<%@page contentType="text/html;charset=gb2312"%>
<jsp:useBean id="zs" scope="page"
class="cn.zte.pxb.SimpleBean"/>
<%
zs.setName("tom") ;
zs.setPassword("123") ;
%>
<h1>姓名:<%=zs.getName()%></h1>
<h1>密码:<%=zs.getPassword()%></h1>
< jsp:useBean id=“zs” scope=“page” class=“cn.zte.pxb.SimpleBean”/>这个标签的意思是:
-
发送请求
-
scope=“page”,创建page内置对象
-
执行这个jsp,先会在page内置对象中找有没有zs这个属性名的值 page.getAttribute(“zs”)
-
page.getAttribute(“zs”)==null,如果没有,就会去web-inf下的class下找到对应包的字节码文件(class=“cn.zte.pxb.SimpleBean”),加载到虚内存的方法区的类代码区
-
在堆里创建出SimpleBean对象—属性名开辟属性空间,方法名开辟方法空间(SimpleBean zs=(SimpleBean)page.getAttribute(“zs”);)。调用SimpleBean类的无参构造方法来初始化对象
-
将对象地址交给page内置对象管理
会先判断有没有zs这个bean对象,如果有就不创建,如果没有,就会创建一个新的new SimpleBean对象,命名为zs
<%--
if (page.getAttribute("zs")==null)
page.setAttribute("zs",new SimpleBean());
SimpleBean zs=(SimpleBean)page.getAttribute("zs");
--%>
- EL表达式自动收集表单数据到Bean里
<%@page contentType="text/html;charset=gb2312"%>
<jsp:useBean id="zs" scope="page" class="cn.zte.pxb.SimpleBean"/>
<jsp:setProperty name="zs" property="*"/>
${zs.name}<br>
${zs.password}
< jsp:useBean id=“zs” scope=“page” class=“cn.zte.pxb.SimpleBean”/>
userBean标签
完成Bean对象的创建 ----如果没有属性名为zs的属性值,就新建一个属性名为zs的SimpleBean对象
< jsp:setProperty name=“zs” property=“*”/>
setProperty标签
完成bean数据的收集 ----在内置对象里找属性名为“zs”的属性值,给simpleBean所指的所有属性设值 (表单里提交的姓名和密码,从request里拿到),自动设值,相当于下面:
zs.setName(request.getParameter(“name”));
zs.setPassword(request.getParameter(“password”))
z s . n a m e ∗ ∗ ∗ ∗ {zs.name}** ** zs.name∗∗∗∗{zs.password}
完成将结果渲染到页面 -----取值。zs.name,zs是内置对象里的属性名,name代表的不是属性,而是getName()方法名 ,name在bean中是私有的,不能直接调用属性。
通过标签/框架自动收集表单数据到Bean中,数据在外部是以表单数据存在,在内部是以bean对象存在,通过bean来传递数据。
2、一些异常情况
- 表单里参数类型和Bean里类型不一致----会自动转换数据类型
zs.setAge(request.getParameter(“age”))----setAge的参数类型是int,而request里获取的参数类型是String,**标签会自动将request里获取到的字符串类型的年龄值转化为int类型的年龄值 **
标签不仅能够自动收集,还能够自动转换
- 表单里参数个数和Bean里不一致。—找的到属性名的就set值,找不到就set原型
表单,两个参数
<form action="JBDemo04.jsp" method="get">
用户名:<input type="text" name="name"><br>
密 码:<input type="text" name="password"><br>
<input type="submit" value="提交">
<input type="reset" value="重置">
</form>
Bean,三个参数
public class SimpleBean{
private String name;
private String password;
private int age;
public SimpleBean(){
sout();
}
public void getName(){
}
public void setName(String name){
}
public void getPassword(){
}
public void setPassword(String password){
}
public int getAge(){
return
}
public void setAge(int age){
}
}
jsp
<%@page contentType="text/html;charset=gb2312"%>
<jsp:useBean id="ls" scope="page" class="cn.mldn.lxh.SimpleBean"/>
<jsp:setProperty name="ls" property="*"/>
<%--<jsp:setProperty name="ls" property="age" value="20"/> --%>
<h1>姓名:<%=request.getParameter("name")%></h1><br> //lisi
<h1>密码:<%=request.getParameter("password")%></h1><br> //123
<h1>年龄:<%=request.getParameter("age")%></h1><br> //null
<h1>姓名:<jsp:getProperty name="ls" property="name"/></h1> //lisi
<h1>密码:<jsp:getProperty name="ls" property="password"/></h1> //123
<h1>年龄:<jsp:getProperty name="ls" property="age"/></h1> //0
ls.setAge(request.getParameter(“age”)) ; // request.getParameter(“age”)为null,没有数据,set原型,0
当表单里参数个数比bean里个数少时,标签自动设值时会给bean里多的属性设置原型(int类型是0 )
有一个漏洞:当表单里name和password输入为空时,如果按照set原型的话,应该给name和passwprd属性set空字符串,但是标签set的是null—这样很容易引发空指针异常
<%--<jsp:setProperty name="ls" property="name" param="password"/>--%>
<%--<jsp:setProperty name="ls" property="name"
value="password"/>--%>
<jsp:setProperty name="ls" property="age" value="20"/>
- 通过param,直接给name属性set表单里参数名为“password” 的值
- 通过value,直接给name属性set值为“password”
- 通过value,还可以给表单中没有的属性age,直接设值为“20”
标签收集还不够健壮。框架相比更优化, 找的到的属性就设置属性值,找不到的就设置原型。
2.2、Bean的传递
1、创建一个JavaBean类
CountBean.java
package cn.mldn.lxh ;
public class CountBean
{
private int coun=0;
public CountBean()
{
System.out.println("** CountBean() ...") ;
System.out.println("¤ --------------------------------- ¤") ;
}
public void setCoun(int coun)
{
this.coun = coun ;
}
public int getCoun()
{
return ++this.coun ;
}
}
2、request内置对象传递JavaBean
requestJBDemo01.jsp
<%@page contentType="text/html;charset=gb2312"%>
<jsp:useBean id="cb" scope="request" class="cn.mldn.lxh.CountBean"/>
访问第
<font color="red" size="15">
<jsp:getProperty name="cb" property="coun"/>
</font>
<jsp:forward page="requestJBDemo02.jsp"/>
<%--<a href="requestJBDemo02.jsp">requestJBDemo02.jsp</a> 这种request会消失--%>
requestJBDemo02.jsp
<%@page contentType="text/html;charset=gb2312"%>
<jsp:useBean id="cb" scope="request" class="cn.mldn.lxh.CountBean"/>
访问第
<font color="red" size="15">
<jsp:getProperty name="cb" property="coun"/>
</font>
次!!
- 首先在request内置对象中,找有没有属性名为cb的值,如果没有,则创建CountBean对象,将对象地址交给request管理。
- 先在page内置对象中查找cb属性值,没有再去request里查找,找到了之前创建的CountBean对象,调用getCoun()方法–coun++,coun=1
- 服务端跳转到requestJBDemo02.jsp (request还存活)
- 先在request中找到属性名为cb的属性值,找到了,就不再创建对象
- 先在page内置对象中查找cb属性值,没有再去request里查找,找到了之前创建的CountBean对象,调用getCoun()方法–coun++,coun=2
- 所以最后输出到页面的就是2
当用服务端跳转时,request请求会被销毁,则需要重新创建CountBean对象
3、session传递javabean
sessionJBDemo01.jsp
<!--127.0.01:8080/test/02_JavaBean/sessionJBDemo01.jsp-->
<%@page contentType="text/html;charset=gb2312"%>
<jsp:useBean id="cb" scope="session" class="cn.mldn.lxh.CountBean"/>
访问第
<font color="red" size="15">
<jsp:getProperty name="cb" property="coun"/>
</font>
次!!
<a href="sessionJBDemo02.jsp">sessionJBDemo02.jsp</a>
sessionJBDemo02.jsp
<%@page contentType="text/html;charset=gb2312"%>
<jsp:useBean id="cb" scope="session" class="cn.mldn.lxh.CountBean"/>
访问第
<font color="red" size="15">
<jsp:getProperty name="cb" property="coun"/>
</font>
次!!
- 先在该请求对应的session内置对象里找属性名为cb的属性值,没找到就创建CountBean对象,并将对象地址交给session管理
查找cb属性值,先在当前page寻找,然后在请求request中查找,最后在session里找
- 在session找到属性名为cb的属性值,调用getCoun()–coun++,coun=1
- 请求结束,返回第一次,然后客户端跳转到sessionJBDemo02.jsp,发起新的请求,session还在。所以可以在session里头找到属性名为cb的属性值,所以不会创建countBean对象
- 在session找到属性名为cb的属性值,调用getCoun()–coun++,coun=2
4、application传递
<%@page contentType="text/html;charset=gb2312"%>
<jsp:useBean id="cb" scope="application" class="cn.mldn.lxh.CountBean"/>
访问第
<font color="red" size="15">
<jsp:getProperty name="cb" property="coun"/>
</font>
次!!
- 在application内置对象里找找属性名为cb的属性值,没找到,创建一个countBean对象,交给application管理
- (先到page里找,没有到request,没有到session,)此时session里有一个countBean对象(前面例子session,用户没下线,session还在),于是调用session里的getCount()方法 ,coun++=====3。找到后就不去application里拿了。所以页面显示的值是3
没有指定在哪找属性值时,会按照这样的查找顺序,直到查到就不再往下一个对象查
page—>request—>session—>application
5、page传递
page是不能传递数据的,只会在当前页面有效
传递数据最好用reqeust的服务端跳转