javabean以及内省技术详解

来源:互联网 发布:南方全站仪usb传输数据 编辑:程序博客网 时间:2024/04/30 01:01

一、关于javabean
javabean是固定写法的java类
书写格式为:
1)必须有无参构造函数
2)属性必须私有, 我们称为字段
3)提供标准的getter和setter
例: name 字段 的getter: String getName() settter: void setName(String name)

javabean例子:

//快捷键是shift+alt+spublic class User{    private String name;    private int age;    public String getName()    {        return name;    }    public void setName(String name)    {        this.name = name;    }    public int getAge()    {        return age;    }    public void setAge(int age)    {        this.age = age;    }    @Override    //为了方便打印,添加一个toString方法    public String toString()    {        return "User [age=" + age + ", name=" + name + "]";    }}

二、关于 内省
内省是什么?: 通过反射的方式访问javabean的技术
Jdk中的api : PropertyDescriptor类操作Bean的属性
内省的作用:我们可以去实现一种通用性
1.传统的方式去访问javabean
public class Demo1{    public static void main(String[] args)    {        User user=new User();                user.setName("zhangsan");        user.setAge(19);        System.out.println(user);    }    }

2.使用内省的方式来访问javabean

public class Demo1{    public static void main(String[] args) throws Exception    {        User user=new User();        //创建属性描述器        PropertyDescriptor descriptor=new PropertyDescriptor("name",User.class);        //获得写方法        Method writeMethod=descriptor.getWriteMethod();                //调用写方法        writeMethod.invoke(user, "lisi");        System.out.println(user);    }    }


3.简化书写,实现通用性。这里写一个通用的方法,让属性名称为一个变量,假如属性名很多的话,得到属性名后,就可以遍历,然后给他们一一的赋值,这就是内省的魅力。

如果不用反射,那么传统的方式是不可能实现通用的。

下面代码实现能够为任何的javabean赋任何的值,只有用内省的方法才可以做的到:

import java.beans.IntrospectionException;import java.beans.PropertyDescriptor;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import cn.itcast.day08.domain.User;public class Demo2 {    /**     * @param args     * @throws IntrospectionException      * @throws InvocationTargetException      * @throws IllegalAccessException      * @throws IllegalArgumentException      */    public static void main(String[] args) throws Exception {        // 内省                User user = new User();                setProperty(user, "name", "wangwu");        setProperty(user, "age", 11);                System.out.println(user);    }        // 实现一个通用的方法   为任意的一个javabean的任意属性赋任意值    public static void setProperty(Object bean, String fieldName, Object value) throws Exception {        // 创建属性描述器        PropertyDescriptor descriptor = new PropertyDescriptor(fieldName, bean.getClass());                // 获得 写方法        Method writeMethod = descriptor.getWriteMethod();                // 调用 写方法        writeMethod.invoke(bean, value);    }}

由于内省用起来特别麻烦,Apache组织开发了一套用于操作JavaBean的API,如下详讲:

三、BeanUtils工具包
Apache组织开发了一套用于操作JavaBean的API(内省)
核心类 BeanUtils
setProperty(bean, name, value)
copyProperties(target, source);
可以支持String到8中基本数据类型转换
其他引用数据类型都需要注册转换器 ConvertUtils.register(Converter, Class)

注意:1、要想使用beanutils需要导入外部的jar包:commons-beanutils-1.8.0.jar这个jar包到lib目录里面

2、BeanUtils要想使用,还需要导入一个log的jar包:commons-logging.jar
下面我们来看看BeanUtils的魅力:
使用BeanUtils来格式化日期

1.javabean

package cn.itcast.day08.domain;import java.util.Date;// 一个javabean 是否有name属性取决于是否getter或setter方法public class User {    private String name;    // 字段    private int age;        private Date birthday;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    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 "User [name=" + name + ", age=" + age + "]";    }    }

2.beanutils

package cn.itcast.day08.introspector;import java.lang.reflect.InvocationTargetException;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.converters.DateConverter;import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;import cn.itcast.day08.domain.User;public class Demo3 {        public static void main(String[] args) throws Exception {                User user = new User();                String name = "zhangsan";        String age = "19";        String birthday = "19801122";        // 11/22/1980   1980 11 22                // 注册一个转换器        /* 使用匿名内部类来注册转换器        ConvertUtils.register(new Converter() {                        public Object convert(Class beanClass, Object value) {                // String -- Date                String birthday = (String) value;                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");                try {                    return sdf.parse(birthday);                } catch (ParseException e) {                    return null;                }            }        }, Date.class);        */        DateConverter converter = new DateConverter();        converter.setPatterns(new String[]{"yyyy-MM-dd","yyyyMMdd","MM/dd/yyyy"});        ConvertUtils.register(converter, Date.class);                String fieldName = "name";        BeanUtils.setProperty(user, fieldName, name);        BeanUtils.setProperty(user, "age", age);        BeanUtils.setProperty(user, "birthday", birthday);                                System.out.println(user);        System.out.println(user.getBirthday().toLocaleString());            }}

四. WebUtils 工具类

实现任何request提交的表单封装到对应的javabean

1.用户注册jsp页面:

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>       <title>用户注册表单</title>      </head>    <body style="text-align: center;">       <form action="/myday08/servlet2" method="post" >           <table border="1" width="600px">               <tr>                   <td>用户名</td>                   <td>                       <input type="text" name="name" />                   </td>               </tr>                          <tr>                   <td>年龄</td>                   <td>                       <input type="text" name="age" />                   </td>               </tr>               <tr>                   <td>出生日期</td>                   <td>                       <input type="text" name="birthday" />                   </td>               </tr>                              <tr>                   <td>                       <input type="reset" value="重置" />                   </td>                   <td>                       <input type="submit" value="用户注册" />                   </td>               </tr>           </table>       </form>  </body></html>


2.写一个工具类,把request里面所有的参数全部封装到javabean中去:

package cn.itcast.day08.util;import java.lang.reflect.InvocationTargetException;import java.sql.Date;import java.util.Enumeration;import javax.servlet.http.HttpServletRequest;import org.apache.commons.beanutils.BeanUtils;import org.apache.commons.beanutils.ConvertUtils;import org.apache.commons.beanutils.converters.DateConverter;public class WebUtils{    private WebUtils(){}        //定义一个通用工具方法,将请求参数封装到javabean    public static Object request2bean(HttpServletRequest request,Class beanClass){    try{        Object bean=beanClass.newInstance();        //        获得所有请求参数名        Enumeration names = request.getParameterNames();        //注册日期转换器        DateConverter converter=new DateConverter();        converter.setPattern("yyyy-MM-dd");        ConvertUtils.register(converter, Date.class);                //遍历        while(names.hasMoreElements()){//            获得一个参数名            String name = (String)names.nextElement();//            获得参数名对应的参数值            String value = request.getParameter(name);            //将参数名作为属性名 将参数值作为属性值,通过beanutils工具实现属性的封装                        BeanUtils.setProperty(bean, name, value);            }                return bean;            }catch (Exception e)            {                throw new RuntimeException(e);            }//异常要抓下来,不能抛给servlet,把编译时异常包装称运行时异常                    }    }

3.写一个servlet页面,注意查看导入的包名称!分清关系

package cn.itcast.day08.web.servlet;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import cn.itcast.day08.domain.User;import cn.itcast.day08.util.WebUtils;public class Servlet2 extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        // 表单提交的参数封装到javabean        User bean = WebUtils.request2Bean(request, User.class);                System.out.println(bean);    }    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        doGet(request, response);    }}

jsp这块的重点为:

1. jsp运行原理(会被翻译成servlet)
2. jsp脚本表达式和脚本片段
3. jsp九大隐式对象
4. web开发的四个域对象
5. 内省