苦尽甘来 一个月学通JavaWeb(二十四 JavaBean)
夜光序言:
一万年的风吹日晒,永不改变对你的爱~~
正文:
1 JavaBean概述
1.1 什么是JavaBean
JavaBean是一种规范,也就是对类的要求。它要求Java类的成员变量提供getter/setter方法,这样的成员变量被称之为JavaBean属性。
JavaBean还要求类必须提供仅有的无参构造器,例如:public User() {…}~~
User.java
package cn.Genius.domain;
public class User { private String username; private String password;
public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } |
1.2 JavaBean属性
JavaBean属性是具有getter/setter方法的成员变量。
- 也可以只提供getter方法,这样的属性叫只读属性;
- 也可以只提供setter方法,这样的属性叫只写属性;
- 如果属性类型为boolean类型,那么读方法的格式可以是get或is。例如名为abc的boolean类型的属性,它的读方法可以是getAbc(),也可以是isAbc();
JavaBean属性名要求:前两个字母要么都大写,要么都小写:
public class User { private String iD; private String ID; private String qQ; private String QQ; … } |
JavaBean可能存在属性,但不存在这个成员变量,例如:
public class User { public String getUsername() { return "Genius"; } } |
上例中User类有一个名为username的只读属性!但User类并没有username这个成员变量!
还可以并变态一点:
public class User { private String hello;
public String getUsername() { return hello; }
public void setUsername(String username) { this.hello = username; } } |
上例中User类中有一个名为username的属性,它是可读可写的属性~
而Use类的成员变量名为hello~
也就是说JavaBean的属性名取决与方法名称,而不是成员变量的名称。但通常没有人做这么变态的事情。
2 内省(夜光:了解)
内省的目标是得到JavaBean属性的读、写方法的反射对象,通过反射对JavaBean属性进行操作的一组API。例如User类有名为username的JavaBean属性,通过两个Method对象(一个是getUsenrmae(),一个是setUsername())来操作User对象。
如果我们还不能理解内省是什么,那么我们通过一个问题来了解内省的作用。现在我们有一个Map,内容如下:
Map<String,String> map = new HashMap<String,String>(); map.put("username", "admin"); map.put("password", "admin123"); |
public class User { private String username; private String password;
public User(String username, String password) { this.username = username; this.password = password; } public User() { } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String toString() { return "User [username=" + username + ", password=" + password + "]"; } } |
现在需要把map的数据封装到一个User对象中~~
User类有两个JavaBean属性,一个叫username,另一个叫password。
你可能想到的是反射,通过map的key来查找User类的Field~
这么做是没有问题的,但我们要知道类的成员变量是私有的,虽然也可以通过反射去访问类的私有的成员变量,但我们也要清楚反射访问私有的东西是有“危险”的,所以还是建议通过getUsername和setUsername来访问JavaBean属性。
2.1 内省之获取BeanInfo
我们这里不想去对JavaBean规范做过多的介绍,所以也就不在多介绍BeanInfo的“出身”了。你只需要知道如何得到它,以及BeanInfo有什么。
通过java.beans.Introspector的getBeanInfo()方法来获取java.beans.BeanInfo实例。
BeanInfo beanInfo = Introspector.getBeanInfo(User.class); |
2.2 得到所有属性描述符(PropertyDescriptor)
通过BeanInfo可以得到这个类的所有JavaBean属性的PropertyDescriptor对象。然后就可以通过PropertyDescriptor对象得到这个属性的getter/setter方法的Method对象了。
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); |
每个PropertyDescriptor对象对应一个JavaBean属性:
- String getName():获取JavaBean属性名称;
- Method getReadMethod:获取属性的读方法;
- Method getWriteMethod:获取属性的写方法。
2.3 完成Map数据封装到User对象中
public void fun1() throws Exception { Map<String,String> map = new HashMap<String,String>(); map.put("username", "admin"); map.put("password", "admin123");
BeanInfo beanInfo = Introspector.getBeanInfo(User.class);
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
User user = new User(); for(PropertyDescriptor pd : pds) { String name = pd.getName(); String value = map.get(name); if(value != null) { Method writeMethod = pd.getWriteMethod(); writeMethod.invoke(user, value); } }
System.out.println(user); } |
3 commons-beanutils
提到内省,不能不提commons-beanutils这个工具。它底层使用了内省,对内省进行了大量的简化~~
使用beanutils需要的jar包:
- commons-beanutils.jar;
- commons-logging.jar;
3.1 设置JavaBean属性
User user = new User();
BeanUtils.setProperty(user, "username", "admin"); BeanUtils.setProperty(user, "password", "admin123");
System.out.println(user); |
3.2 获取JavaBean属性
User user = new User("admin", "admin123");
String username = BeanUtils.getProperty(user, "username"); String password = BeanUtils.getProperty(user, "password");
System.out.println("username=" + username + ", password=" + password); |
3.3 封装Map数据到JavaBean对象中
Map<String,String> map = new HashMap<String,String>(); map.put("username", "admin"); map.put("password", "admin123");
User user = new User();
BeanUtils.populate(user, map);
System.out.println(user); |
4 JSP与JavaBean相关的动作标签
在JSP中与JavaBean相关的标签有:
- <jsp:useBean>:创建JavaBean对象;
- <jsp:setProperty>:设置JavaBean属性;
- <jsp:getProperty>:获取JavaBean属性;
我们需要先创建一个JavaBean类:
User.java
package cn.Genius.domain;
public class User { private String username; private String password;
public User(String username, String password) { this.username = username; this.password = password; } public User() { } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String toString() { return "User [username=" + username + ", password=" + password + "]"; } } |
4.1 <jsp:useBean>
<jsp:useBean>标签的作用是创建JavaBean对象:
- 在当前JSP页面创建JavaBean对象;
- 把创建的JavaBean对象保存到域对象中;
<jsp:useBean id="user1" class="cn.Genius.domain.User" /> |
为我所爱之人~~上面代码表示在当前JSP页面中创建User类型的对象,并且把它保存到page域中了。下面我们把<jsp:useBean>标签翻译成Java代码:
<% cn.Genius.domain.User user1 = new cn.Genius.domain.User(); pageContext.setAttribute("user1", user1); %> |
这说明我们可以在JSP页面中完成下面的操作:
<jsp:useBean id="user1" class="cn.Genius.domain.User" /> <%=user1 %> <% out.println(pageContext.getAttribute("user1")); %> |
<jsp:useBean>标签默认是把JavaBean对象保存到page域,还可以通过scope标签属性来指定保存的范围:
<jsp:useBean id="user1" class="cn.Genius.domain.User" scope="page"/> <jsp:useBean id="user2" class="cn.Genius.domain.User" scope="request"/> <jsp:useBean id="user3" class="cn.Genius.domain.User" scope="session"/> <jsp:useBean id="user4" class="cn.Genius.domain.User" scope="applicatioin"/> |
<jsp:useBean>标签其实不一定会创建对象~
其实它会先在指定范围中查找这个对象,如果对象不存在才会创建,我们需要重新对它进行翻译:
<jsp:useBean id="user4" class="cn.Genius.domain.User" scope="applicatioin"/> |
<% cn.Genius.domain.User user4 = (cn.Genius.domain.User)application.getAttribute("user4"); if(user4 == null) { user4 = new cn.Genius.domain.User(); application.setAttribute("user4", user4); } %> |
4.2 <jsp:setProperty>和<jsp:getProperty>
<jsp:setProperty>标签的作用是给JavaBean设置属性值,而<jsp:getProperty>是用来获取属性值。在使用它们之前需要先创建JavaBean:
<jsp:useBean id="user1" class="cn.Genius.domain.User" /> <jsp:setProperty property="username" name="user1" value="admin"/> <jsp:setProperty property="password" name="user1" value="admin123"/>
用户名:<jsp:getProperty property="username" name="user1"/><br/> 密 码:<jsp:getProperty property="password" name="user1"/><br/> |