【JavaEE】Java內省Introspector、PropertyDescriptor與JavaBean
1.Java內省概念
Sun公司開發了一套API,專門用於操作Java物件的屬性。【Introspector】
在開發框架時,需要使用Java物件的屬性來封裝程式的資料,使用反射技術完成此類操作過於麻煩,我們使用內省。
內省(Introspector) 是Java 語言對 JavaBean 類屬性、事件的一種預設處理方法。
JavaBean是一種特殊的類,主要用於傳遞資料資訊,這種類中的方法主要用於訪問私有的欄位,且方法名符合某種命名規則。
如果在兩個模組之間傳遞資訊,可以將資訊封裝進JavaBean中,這種物件稱為”值物件”(Value Object),或”VO”。
方法比較少。這些資訊儲存在類的私有變數中,通過set()、get()獲得。
在Student中有屬性name, age, birthday。我們可以通過getName, setName來訪問name屬性,這就是預設的規則。
Java JDK中提供了一套 API 用來訪問某個屬性的 getter/setter 方法,這就是內省。
PropertyDescriptor類:
PropertyDescriptor類表示JavaBean類通過儲存器匯出一個屬性。主要方法:
1. getReadMethod(),獲得用於讀取屬性值的方法;
2. getWriteMethod(),獲得用於寫入屬性值的方法;
3. setReadMethod(Method readMethod),設定用於讀取屬性值的方法;
4. setWriteMethod(Method writeMethod),設定用於寫入屬性值的方法。
通過PropertyDescriptor與Introspector的比較可以看出,都是需要獲得PropertyDescriptor,只是方式不一樣:
PropertyDescriptor通過建立物件直接獲得,Introspector需要遍歷,
所以使用PropertyDescriptor類更加方便。
Introspector類,將JavaBean中的屬性封裝起來進行操作。
1.在程式中把一個類當做JavaBean來看,呼叫Introspector.getBeanInfo()方法,
得到的BeanInfo物件封裝了這個類的屬性資訊。
2.通過BeanInfo來獲取屬性的屬性描述器PropertyDescriptor 。
3.通過PropertyDescriptor獲取某個屬性對應的getter/setter方法,
然後通過反射機制來呼叫這些方法。
BeanInfo bi = Introspector.getBeanInfo(Student.class);
PropertyDescriptor [] pds = bi.getPropertyDescriptors();
BeanUtils工具包
內省操作非常的繁瑣,所以所以Apache開發了一套簡單、易用的API來操作Bean的屬性,BeanUtils工具包。
beanutils內省框架(依賴commons-logging):apache
準備包:commons-beanutils.jar, commons-logging.jar
BeanUtils工具包:
下載:commons-beanutils.jar http://commons.apache.org/beanutils/
commons-logging.jar http://commons.apache.org/logging/
1.獲得屬性的值,例如,BeanUtils.getProperty(stu,”stuName”),返回字串
2.設定屬性的值,例如,BeanUtils.setProperty(stu,”age”,38),引數是字串或基本型別自動包裝。
設定屬性的值是字串,獲得的值也是字串,不是基本型別。
3.BeanUtils的特點:
①對基本資料型別的屬性的操作:String<—–>基本型別 在WEB開發、使用中,錄入和顯示時,值會被轉換成字串,但底層運算用的是基本型別,這些型別轉到動作由BeanUtils自動完成。
②非基本型別的屬性的操作:String<—-> 其他型別
例如:
public void test5 () throws Exception{
Student s = new Student ();
//給BeanUtils註冊轉換器,
ConvertUtils.register(new Converter (){
//type是目標型別, value是當前傳入的值
public Object convert(Class type, Object value) {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
//字串轉換為Date
String v= (String) value;
try{
Date d = df.parse(v);
return d;
}catch (ParseException e){
throw new RuntimeException (e);
}
}
}, Date.class);
BeanUtils.setProperty(s, "birthday", "1990-08-25");
System.out.println(s.getBirthday());
}
/**
* 給BeanUtils註冊轉換器,引數:converter 要註冊的轉換器
* clazz 此轉換器執行的轉換的目標類
*/
public static void register(Converter converter, Class clazz);
public interface Converter {
/*
*將特定輸入轉換成特定的輸出型別
*引數:type 目標轉換型別,value 待轉換的輸入值
*返回值: 轉換的結果
*/
public Object convert(Class type, Object value);
}
2. Java內省例項
JavaBean
package cn.edu;
import java.util.Date;
public class Student {
private String stuName;
private int age;
private Date birthday;
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "Student [stuName=" + stuName + ", age=" + age + ", birthday="
+ birthday + "]";
}
}
package cn.edu;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;
public class BeanInfoUtil {
public static void main(String[] args) throws Exception {
Student stu = new Student();
BeanInfoUtil.setProperty(stu, "stuName","Tom");
BeanInfoUtil.getProperty(stu, "stuName");
setPropertyByIntrospector(stu, "stuName","Ben");
getPropertyByIntrospector(stu, "stuName");
/*
* 3.BeanUtils工具包操作JavaBean
* */
BeanUtils.setProperty(stu, "stuName", "Green");
BeanUtils.setProperty(stu, "age", 18);
System.out.println("get stuName:"+BeanUtils.getProperty(stu, "stuName"));
System.out.println("get age:"+BeanUtils.getProperty(stu, "age"));
convertUtilsGetBirthday(stu, "1990-08-25");
convertUtilsGetBirthday2(stu, "1993-08-25");
}
/**
* 1.直接通過 PropertyDescriptor類的操作Bean屬性
* */
public static void setProperty(Student stu, String stuName, String value) throws Exception, IllegalArgumentException, InvocationTargetException{
//1.獲取stuName屬性
PropertyDescriptor propDesc=new PropertyDescriptor(stuName,Student.class);
//2.得到setStuName()方法
Method methodSetStuName=propDesc.getWriteMethod();
//3.呼叫setStuName()方法
methodSetStuName.invoke(stu, value);
System.out.println("set name:"+stu.getStuName());
}
public static void getProperty(Student stu, String stuName) throws Exception{
PropertyDescriptor proDescriptor =new PropertyDescriptor(stuName,Student.class);
Method methodGetStuName=proDescriptor.getReadMethod();
Object objStuName=methodGetStuName.invoke(stu);
System.out.println("get name:"+objStuName.toString());
}
/**
* 2.通過Introspector類獲取BeanInfo物件,再通過BeanInfo獲取PropertyDescriptor,操作Bean屬性
* */
public static void setPropertyByIntrospector(Student stu,String stuName, String value)throws Exception{
//1.獲取BeanInfo物件
BeanInfo beanInfo=Introspector.getBeanInfo(Student.class);
//2.通過BeanInfo物件獲取PropertyDescriptor
PropertyDescriptor[] proDescrtptors=beanInfo.getPropertyDescriptors();
//3.遍歷
if(proDescrtptors !=null && proDescrtptors.length > 0){
for(PropertyDescriptor propDesc : proDescrtptors){
if(propDesc.getName().equals(stuName)){
Method methodSetUserName=propDesc.getWriteMethod();
methodSetUserName.invoke(stu, value);
System.out.println("set stuName:"+stu.getStuName());
break;
}
}
}
}
public static void getPropertyByIntrospector(Student stu,String stuName)throws Exception{
BeanInfo beanInfo=Introspector.getBeanInfo(Student.class);
PropertyDescriptor[] proDescrtptors=beanInfo.getPropertyDescriptors();
if(proDescrtptors !=null && proDescrtptors.length > 0){
for(PropertyDescriptor propDesc : proDescrtptors){
if(propDesc.getName().equals(stuName)){
Method methodStuUserName=propDesc.getReadMethod();
Object objStuName=methodStuUserName.invoke(stu);
System.out.println("get StuName:"+objStuName.toString());
break;
}
}
}
}
/**
* 給BeanUtils註冊時間日期轉換器
* */
public static void convertUtilsGetBirthday(Student stu, String date) throws Exception{
//給BeanUtils註冊轉換器, type是目標型別, value是當前傳入的值
ConvertUtils.register(new Converter (){
public Object convert(Class type, Object value) {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
//字串轉換為Date
String v= (String) value;
try{
Date d = df.parse(v);
return d;
}catch (ParseException e){
throw new RuntimeException (e);
}
}
}, Date.class);
BeanUtils.setProperty(stu, "birthday", date);
System.out.println(stu.getBirthday());
}
/**
* 給BeanUtils註冊時間日期轉換器
* */
public static void convertUtilsGetBirthday2(Student stu, String date) throws Exception{
ConvertUtils.register(new DateLocaleConverter(), Date.class);
BeanUtils.setProperty(stu, "birthday", date);
System.out.println(stu.getBirthday());
}
}
/*
set name:Tom
get name:Tom
set stuName:Ben
get StuName:Ben
get stuName:Green
get age:18
Sat Aug 25 00:00:00 CDT 1990
Wed Aug 25 00:00:00 CST 1993
* */
3.Java封裝客戶端請求引數至JavaBean
JavaBean
public class User {
private String username;
private String password[];
private String gender;
public String getUsername() {//讀屬性,屬性名稱username
return username;
}
public void setUsername(String username) {//寫屬性,屬性名username
this.username = username;
}
public String[] getPassword() {
return password;
}
public void setPassword(String[] password) {
this.password = password;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "User [username=" + username + ", password="
+ Arrays.toString(password) + ", gender=" + gender + "]";
}
}
封裝請求引數的幾種方案:
/*1.使用Java內省,將請求引數的值封裝到JavaBean中。
約定優於編碼:表單的輸入域的name取值和JavaBean中的屬性(getter和setter方法)保持一致
*/
private void test1(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Enumeration<String> e = request.getParameterNames();//引數名
User user = new User();
while(e.hasMoreElements()){
String paramName = e.nextElement();//即是JavaBean中的屬性名稱
String paramValue = request.getParameter(paramName);
//JavaBean的內省
try {
PropertyDescriptor pd = new PropertyDescriptor(paramName, User.class);
Method m = pd.getWriteMethod();//setter方法
m.invoke(user, paramValue);
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
/*2.getParameterMap獲取引數*/
private void test6(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//key:請求引數名 value:請求引數值陣列
Map<String,String[]> map = request.getParameterMap();
for(Map.Entry<String, String[]> me:map.entrySet()){
System.out.println(me.getKey()+"="+Arrays.asList(me.getValue()));
}
}
/*
3.getParameterMap獲取引數結合Java 內省,封裝到JavaBean中
*/
private void test2(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//key:請求引數名 value:請求引數值陣列
Map<String,String[]> map = request.getParameterMap();
User user = new User();
for(Map.Entry<String, String[]> me:map.entrySet()){
String paramName = me.getKey();//引數名稱
String paramValues[] = me.getValue();//引數值
try {
PropertyDescriptor pd = new PropertyDescriptor(paramName, User.class);
Method m = pd.getWriteMethod();//setter方法
if(paramValues.length > 1){
m.invoke(user, (Object)paramValues);
}else{
m.invoke(user, paramValues);
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
/*3.藉助第三方工具包:藉助BeanUtil框架*/
private void test8(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
User user = new User();
try {
BeanUtils.populate(user, request.getParameterMap());
} catch (Exception e) {
e.printStackTrace();
}
}
相關文章
- java 內省(Introspector)JavaROS
- 聊聊Java內省IntrospectorJavaROS
- 內省機制(操作javaBean的資訊)JavaBean
- JAVA的內省機制(introspector)與反射機制(reflection)----轉載http://yangzhibin-java.iteye.com/b...JavaROS反射HTTP
- java內省api的操作JavaAPI
- Javassist之內省與定製(四)Java
- JSP與JavaBean詳談JSJavaBean
- 【JavaEE】Java的13個規範Java
- lombok get/set 與 JavaBean get/setLombokJavaBean
- Junit、Assert、內省、Properties類與配置檔案的使用
- 嵌入式狗的JAVA之路 JavaBeanJavaBean
- javabeanJavaBean
- JDBC與JavaBean學習筆記(二)JDBCJavaBean筆記
- javaBean分析JavaBean
- 求助,(javabean)JavaBean
- JavaEE死了Java
- Objective-C的Introspection(內省)ObjectROS
- 利用類反射模擬內省功能反射
- Java 內部類與閉包Java
- Java類與匿名內部類Java
- 程式設計字典-Java(JavaEE)學習線路圖程式設計Java
- JavaEE進階知識學習----Java NIO-4Java
- 畢業設計 java cocos2dx JavaEEJava
- 十、理解JavaBeanJavaBean
- 楊小楊 資料庫生成javabean小工具(java)資料庫JavaBean
- Java、JavaEE、JavaSE、JavaME、JavaWEB之間有什麼區別?JavaWeb
- JavaBean之Builder模式JavaBeanUI模式
- jsp servlet javabeanJSServletJavaBean
- javabean 的執行JavaBean
- 如何理解區別伺服器端的Javabean與EJB伺服器JavaBean
- JSP開發入門(三)----JSP與JavaBean (轉)JSJavaBean
- DWR中Java方法的引數及返回值、物件javabeanJava物件Bean
- JAVA基礎之介面與內部類Java
- jsp呼叫javabean,javabean封裝資料庫的問題JSJavaBean封裝資料庫
- JavaEE面試題收集Java面試題
- JavaEE概念介紹Java
- JavaEE 啟示錄Java
- 【Java專案(2)】基於Javaee的通訊錄系統Java