JavaWeb之BeanUtils及底层实现

您所在的位置:网站首页 beanutils工具类的介绍 JavaWeb之BeanUtils及底层实现

JavaWeb之BeanUtils及底层实现

2023-09-28 03:13| 来源: 网络整理| 查看: 265

JavaWeb之BeanUtil及底层实现 一、BeanUtils的概述1.1为什么使用BeanUtils?1.2导入jar包1.3、model2模式 二、BeanUtils的常用方法三、BeanUtils的方法实例3.1、BeanUtils之初体验BeanUtils.populate(bean,Map);3.2、BeanUtils.setProperty(bean, name, value);设置javaBean的参数3.3、BeanUtils.copyProperties(newObject,oldObject)实现对象的Copy3.4、自定义类型转换器 四、简单的分析底层的实现原理五、BeanUtils的总结

一、BeanUtils的概述 1.1为什么使用BeanUtils? BeanUtils是Apache开发的一种工具。BeanUtils可以帮助我们把属性封装到javabean对象的对应属性中,比如可以把提交的表单数据封装到一个实体对象中.封装时要求参数名称和javabean的属性名相同beanUtils 可以便于对javaBean的对象进行赋值。beanUtils 可以便于对javaBean的属性进行赋值。beanUtils可以将一个Map集合的数据拷贝到一个javabean对象中。 1.2导入jar包

BeanUtils是第三方组织写的工具类,要使用它,得先下载对应的工具JAR包。

相关的jar包(将三个jar包全部导入) commons‐beanutils‐1.9.3.jar // 工具核心包 工具核心包 commons‐logging‐1.2.jar // 日志记录包 日志记录包 commons‐collections‐3.2.2.jar // 增强的集合包 增强的集合包

1.3、model2模式

来源CSDN的Megustas_JJC

二、BeanUtils的常用方法 方法描述BeanUtils.setProperty(bean, name, value);其中bean是指你将要设置的对象,name指的是将要设置的属性(写成”属性名”),value(从配置文件中读取到到的字符串值)BeanUtils.copyProperties(bean, name, value)和上面的方法是完全一样的。使用哪个都可以ConvertUtils.register(Converter converter , …)当需要将String数据转换成引用数据类型(自定义数据类型时),需要使用此方法实现转换。BeanUtils.populate(bean,Map)其中Map中的key必须与目标对象中的属性名相同,否则不能实现拷贝。BeanUtils.copyProperties(newObject,oldObject)实现对象的拷贝 三、BeanUtils的方法实例 3.1、BeanUtils之初体验BeanUtils.populate(bean,Map);

根据jsp页面传入的参数。将数据封装到 javabean 中。 1、login.jsp页面

用户名: 密码:

2、根据得到的数据进行封装 BeanUtils_login.java

public class BeanUtils_login extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) { // 不使用BeanUtils // String username = request.getParameter("username"); // String password = request.getParameter("password"); // User user = new User(); // user.setUsername(username); // user.setPassword(password); // 使用BeanUtils // 1.创建一个bean对象 User user = new User(); // 2.得到所有的数据 类型Map Map map = request.getParameterMap(); // 3.使用BeanUtils的populate方法将数据自动封装到javabean中 try { BeanUtils.populate(user, map); } catch (IllegalAccessException | InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(user.getUsername()); System.out.println(user.getPassword()); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } 3.2、BeanUtils.setProperty(bean, name, value);设置javaBean的参数 public class Demo1 { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException { //频繁的使用getter/setter方法代码过于繁琐、臃肿!下面我们用BeanUtils来进行赋值 // 1.得到Person Bean的字节码对象 Class clazz = Class.forName("cn.syj.Bean.Person"); // 2.实例化一个Person实例 Object obj = clazz.newInstance(); // 3.使用自带的Date时间转化格式。 ConvertUtils.register(new DateLocaleConverter(), Date.class);// 这里面有自定义构造器的概念稍后会详细说明 // 4. 使用哪个BeanUtils对javaBean属性进行赋值 BeanUtils.setProperty(obj, "name", "张三"); BeanUtils.setProperty(obj, "age", "28"); BeanUtils.setProperty(obj, "brithday", "1996-07-16"); // 5.将对象封装的属性进行输出 System.out.println(obj); } }

运行结果

3.3、BeanUtils.copyProperties(newObject,oldObject)实现对象的Copy

1、把一个javaBean的属性拷贝到另一个javaBean对象中

public class Demo2 { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException { // 1.获得Person bean的字节码对象 Class clazz = Class.forName("cn.syj.Bean.Person"); // 2.生成该字节码的一个对象 Object obj1 = clazz.newInstance(); Object obj2 = clazz.newInstance(); //将转换器注册到工具类中,使用了一个自带的转化器(可以自己编写) ConvertUtils.register(new DateLocaleConverter(), Date.class); BeanUtils.setProperty(obj1, "name", "张三"); BeanUtils.setProperty(obj1, "age", "18"); BeanUtils.setProperty(obj1, "brithday", "1996-08-08"); BeanUtils.copyProperties(obj2, obj1); System.out.println(obj1); System.out.println(obj2); } }

运行结果展示: 在这里插入图片描述 2、把一个map集合中的数据拷贝到javaBean中

// 把一个map集合中的数据拷贝到javaBean中 public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException { Class clazz = Class.forName("cn.syj.Bean.Person"); Object obj = clazz.newInstance(); ConvertUtils.register(new DateConverter(), Date.class); Map map = new HashedMap(); map.put("name", "syj"); map.put("age", "26"); map.put("brithday", "1999-08-08"); // 使用日起转换器工具类(并将其进行注册)告诉转化器这个类型的可以进行转化 ConvertUtils.register(new DateLocaleConverter(), Date.class); BeanUtils.copyProperties(obj, map); System.out.println(obj); }

运行结果展示: 在这里插入图片描述

3.4、自定义类型转换器

现在我们不想已经实现的类型转化器(比如日期Date和字符串String之间的转化)我们可以自己定义一个。

在自定义转化器的时候我们应该去实现Converter接口,并重写里面的方法(public T convert(Class type, Object value))参数:type:目前需要转换的数据类型;value:目前参数的值

步骤: 1、创建一个接口实现Converter接口 2、重写接口中的convert方法

public T convert(Class type, Object value) 参数解读: 参数1:数据最终要转化的类型 参数2:要转化的数据(请求参数中的信息) 返回值:转换后的数据

3、将自定义的转换器注册到BeanUtils中。目的就是为了通知在BeanUtils封装数据到javaBean时,怎样将指定类型的数据进行封装

ConvertUtils.register(Converter converter,Class clazz)

参数1:自定义转换器对象 参数2:需要被转化的类型.class

实现将传入的日期字符串以Date的类型进行返回:

// 自定义日期转换器工具(匿名内部类进行实现) ConvertUtils.register(new Converter() { @Override public T convert(Class type, Object value) { // type:目前需要转换的数据类型, value:目前参数的值 if (type != Date.class) return null; String str = value.toString().trim(); if (value == null || "".equals(str)) { return null; } SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-DD"); Date date = null; try { date = sdf.parse(str); } catch (ParseException e) { throw new RuntimeException(e); } return (T) date; } }, Date.class);

在使用的时候我们应该将其注册到转换器工具类中:

ConvertUtils.register(new DateConverter(), Date.class); 举例说明:

public class Demo1 { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException { // 1.得到Person Bean的字节码对象 Class clazz = Class.forName("cn.syj.Bean.Person"); // 2.实例化一个Person实例 Object obj = clazz.newInstance(); // 自定义日期转换器工具 ConvertUtils.register(new Converter() { @Override public T convert(Class type, Object value) { // type:目前需要转换的数据类型, // value:目前参数的值 if (type != Date.class) return null; String str = value.toString().trim(); if (value == null || "".equals(str)) { return null; } SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-DD"); Date date = null; try { date = sdf.parse(str); } catch (ParseException e) { throw new RuntimeException(e); } return (T) date; } }, Date.class); // 3.使用自带的Date时间转化格式。 // ConvertUtils.register(new DateLocaleConverter(), Date.class);// // 这里面有自定义构造器的概念稍后会详细说明 ConvertUtils.register(new DateConverter(), Date.class); // 4. 使用哪个BeanUtils对javaBean属性进行赋值 BeanUtils.setProperty(obj, "name", "张三"); BeanUtils.setProperty(obj, "age", "28"); BeanUtils.setProperty(obj, "brithday", "1996-07-16"); // 5.将对象封装的属性进行输出 System.out.println(obj); } }

运行结果: 在这里插入图片描述

四、简单的分析底层的实现原理

4.1、BeanUtils底层是使用内省完成的(内省的底层是使用反射完成的)

sun公司提供了内省(Introspector)的API, Apache去进行使用访问javabean属性的两种方式: 1、直接调用setXXX或者getXXX方法; 2、通过内省(内省是BenaUtils的底层实现原理)其实就是BeanUtils工具包进行实现 通过Introspector类获得Bean对象的BenaInfo==然后通过BeanInfo来获取属性描述器(PropertyDescriptor)==通过属性描述器(PropertyDescriptor)就可以取得某个属性对应的getter和settter方法最后通过反射技术来调用方法

4.2、实现步骤: (查询Jdk API) Introspector----->BeanInfo----->PropertyDescriptor----->得到属性的getter/setter方法----->反射完成操作

// 1.根据Introspector得到javaBean信息 BeanInfo info = Introspector.getBeanInfo(user.getClass()); // 2.通过BeanInfo获得JavaBean属性的描述器 PropertyDescriptor[] pds = info.getPropertyDescriptors(); // 3.获取javaBean的属性读方法(get)和写方法(set) for (PropertyDescriptor pd : pds) { String name = pd.getName();// 获得属性名 System.out.println("bean属性名称:" + name); Method get = pd.getReadMethod();// 得到javaBean的get方法 Method set = pd.getWriteMethod();// 得到javaBean的set方法 } //4.利用反射完成数据的封装 if ("username".equals(name)) { set.invoke(user, map.get(name)[0]);// 对于名称是写死的(将其使用一个Map进行引入) } if ("password".equals(name)) { set.invoke(user, map.get(name)[0]); }

举例:手动实现内省完成数据的封装 从login.jsp页面进行数据的传输,使用Introspector_Servelt.java进行接收 login.jsp

用户名: 密码:

Introspector_Servelt.java

public class Introspector_Servelt extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 创建一个javaBean实例 User user = new User(); // 得到所有的请求参数 类型Map Map map = request.getParameterMap(); // 手动实现BeanUtil内省 try { // 1.通过Introspector首先获得BeanInfo信息 BeanInfo info = Introspector.getBeanInfo(user.getClass()); // 2.通过BeanInfo获得属性的描述器集合 PropertyDescriptor[] pds = info.getPropertyDescriptors(); // 3.遍历描述器集合 for (PropertyDescriptor pd : pds) { String name = pd.getName();// 得到属性名称 String[] values = map.get(name);// 得到指定的请求的参数集合 // 有值说明存在对应的set方法 if (values != null) { // 得到set方法 Method set = pd.getWriteMethod(); // 利用反射将请求参数的值传入set方法中 set.invoke(user, values[0]); } } } catch (IntrospectionException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(user.getUsername()); System.out.println(user.getPassword()); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }

结果展示:

在这里插入图片描述

五、BeanUtils的总结

BeanUtils.populate(Object bean, Map properties)方法进行数据封装

一般其实不需要自定义转换器,只有在特殊情况下才会自定义转换器

1、如果form参数是String类型,javabean属性String类型 —- 调用 BeanUtils.populate 将form数据封装 javabean 2、如果JavaBean属性类型不是String —- 将form数据封装javabean 需 要转换器 —– 在BeanUtils API 提供很多默认转换器(完成常见转换) 3、如果需要转换类型非常特殊,可以通过自定义转换器完成 定义类实 现Converter接口,实现convert方法 ,在populate调用之前通过 ConvertUtils.register注册转换器

JavaBean就是一个存数据的地方 (1)通过JSP页面中的标签去存储form表单中的数据(action跳转到JSP页面,之后“useBean”,“setProperty”进行数据存储),再在JSP界面中通过“getProperty”显示数据。 (2)在JSP页面中通过action跳转到Servlet程序的url,在Servlet程序中通过BeanUtils工具类的相关方法对JSP页面中的表单信息进行存储。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3