一、JavaBean簡介
JavaBean是使用Java語言開發的一個可重用的組件,在JSP的開發中可以使用JavaBean減少重複代碼,使整個JSP代碼的開發更簡潔。JSP搭配JavaBean來使用,有以下的優點:
1.可將HTML和Java代碼分離,這主要是爲了日後維護的方便。如果把所有的程序代碼(HTML和Java)寫到JSP頁面中,會使整個程序代碼又多又複雜,造成日後維護上的困難。
2.可利用JavaBean的優點。將日常用到的程序寫成JavaBean組件,當在JSP要使用時,只要調用JavaBean組件來執行用戶所要的功能,不用再重複寫相同的程序,這樣以來也可以節省開發所需的時間。
二、JavaBean開發要求
1.JavaBean本身就是一個類,屬於Java的面向對象編程。
2.在JSP中如果要應用JSP提供的Javabean的標籤來操作簡單類的話,則此類必須滿足如下的開發要求:
(1)所有的類必須放在一個包中,在WEB中沒有包的是不存在的;
(2)所有的類必須聲明爲public class,這樣才能夠被外部所訪問;
(3)類中所有的屬性都必須封裝,即:使用private聲明;
(4)封裝的屬性如果需要被外部所操作,則必須編寫對應的setter、getter方法;
(5)一個JavaBean中至少存在一個無參構造方法,此爲JSP中的標籤所使用。
三、JavaBean的內省操作
JDK中提供了對JavaBean進行操作的一些API,這套API就稱爲內省。所謂JavaBean的內省操作就是根據屬性名,對JavaBean進行讀寫。說上去很簡單,但是有很多細節,比方說JavaBean對屬性的命名有一定的規則,需要解析。有人會問那爲什麼不直接調用JavaBean的setXXX跟getXXX來讀寫屬性值,因爲JavaBean的應用領域大多在J2EE項目中,尤其突出的使用是在EL表達式中。我們可以通過級聯操作獲取屬性值例如“person.birthday.time”。這樣就沒法通過方法來獲取屬性值,只有通過內省,再通過反射調用方法讀寫屬性值。
四、編程實踐
(1)我寫了一個簡單的JavaBean對象,是一個Person對象,包含三個屬性,name,age,birthday,代碼如下:
package cn.rocket.study.introspector;
import java.sql.Date;
/**
* @author rocket
*
*/
public class Person {
private String name ;
private Integer age ;
private Date birthday = new Date(System.currentTimeMillis()) ;
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Person(String name,Integer age){
this.name = name ;
this.age = age ;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
(2)手動實現JavaBean的內省操作
package cn.rocket.study.introspector;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class IntrospectorTest {
public static void main(String[] args) throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
Person person = new Person("rocket", 20);
System.out.println("原始數據是:"+person);
String propertyName = "name" ;
Object val = getProperty(person, propertyName);
System.out.println("通過內省獲取JavaBean屬性:name = "+val);
Object value = "Jack" ;
setProperty(person, propertyName, value);
System.out.println("通過內省設置JavaBean屬性後:name="+getProperty(person, propertyName));
}
//通過內省操作獲取JavaBean屬性值
private static Object getProperty(Object obj, String propertyName)
throws IntrospectionException, IllegalAccessException, InvocationTargetException {
/*
//使用比較簡單的方式
PropertyDescriptor proDescriptor = new PropertyDescriptor(propertyName,obj.getClass());
Method getMethod = proDescriptor.getReadMethod() ;
Object val = getMethod.invoke(obj);//通過反射調用方法
return val;
*/
//使用比較笨的方式
Object returnVal = null ;
BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass()) ;
PropertyDescriptor[] pros = beanInfo.getPropertyDescriptors() ;
for(PropertyDescriptor p:pros){
if(p.getName().equals(propertyName)){
returnVal = p.getReadMethod().invoke(obj);
break ;
}
}
return returnVal ;
}
//通過內省操作設置JavaBean屬性值
private static void setProperty(Object obj, String propertyName, Object value)
throws IntrospectionException, IllegalAccessException, InvocationTargetException {
PropertyDescriptor proDescriptor = new PropertyDescriptor(propertyName,obj.getClass());
Method setMethod = proDescriptor.getWriteMethod() ;//通過反射調用方法
setMethod.invoke(obj, value);
}
}
(3)好在apache給我們提供了一個JavaBean內省操作的工具包,叫BeanUtils,當然他依賴apache旗下的log包,工具包如下:
下面是我使用BeanUtils操作JavaBean屬性的源代碼,BeanUtils功能很強大,不僅可以操作JavaBean屬性,而且可以將Map轉化成JavaBean對象,將JavaBean對象轉換成Map對象,由於篇幅有限,讀者可以自行實踐:
package cn.rocket.study.introspector;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import org.apache.commons.beanutils.BeanUtils;
public class BeanUtilsTest {
public static void main(String[] args) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException{
Person person = new Person("rocket", 12);
BeanUtils.setProperty(person, "birthday.time", "222");
System.out.println(person.getBirthday());
Map<String, Object> map = BeanUtils.describe(person);
System.out.println(map);
}
}