Apache BeanUtils工具介绍

news2024/12/26 9:19:46

beanutils,顾名思义,是java bean的一个工具类,可以帮助我们方便的读取(get)和设置(set)bean属性值、动态定义和访问bean属性;细心的话,会发现其实JDK已经提供了一个java.beans包,同样可以实现以上功能,只不过使用起来比较麻烦,所以诞生了apache commons beanutils;看源码就知道,其实apache commons beanutils就是基于jdk的java.beans包实现的。

maven:

<dependency>
        <groupId>commons-chain</groupId>
        <artifactId>commons-chain</artifactId>
        <version>1.2</version>
</dependency>

commons-chain包主要有以下三个工具类:BeanUtils、PropertyUtils、ConvertUtils

1、设置、访问Bean的属性

1.1)javabean一般有以下几个特性:

1)类必须是public访问权限,且需要有一个public的无参构造方法,之所以这样主要是方便利用Java的反射动态创建对象实例:

Class beanClass = Class.forName(className);

Object beanInstance = beanClass.newInstance();

2)由于javabean的构造方法是无参的,所以我们的bean的行为配置(即设置bean的属性值)不能在构造方法完成,必须通过set方法来设置属性值。这里的setter方法会按一定的约定来命名,如setHireDate、setName。。。

3)读取和设置bean属性值的命名约定,即getter方法和setter方法,不过这里需要特别注意boolean类型的约定,如下示例:

private String firstName;
private String lastName;
private Date hireDate;
private boolean isManager;
public String getFirstName();
public void setFirstName(String firstName);
public String getLastName();
public void setLastName(String lastName);
public Date getHireDate();
public void setHireDate(Date hireDate);
public boolean isManager();
public void setManager(boolean manager);

4)并不是必须为每个属性提供setter和getter方法,我们可以只定义一个属性的getter方法而不定义setter方法,这样的属性一般是只读属性;

1.2)实战

可以通过BeanUtils和PropertyUtils设置、获取Bean的属性。

1)PropertyUtils设置、获取属性:

  • 基本数据类型:
    • PropertyUtils.getSimpleProperty(Object, String)
    • PropertyUtils.setSimpleProperty(Object, String, Object)
  • 索引类型:
    • PropertyUtils.getIndexedProperty(Object, String)
    • PropertyUtils.getIndexedProperty(Object, String, int)
    • PropertyUtils.setIndexedProperty(Object, String, Object)
    • PropertyUtils.setIndexedProperty(Object, String, int, Object)
  • Map类型:
    • PropertyUtils.getMappedProperty(Object, String)
    • PropertyUtils.getMappedProperty(Object, String, String)
    • PropertyUtils.setMappedProperty(Object, String, Object)
    • PropertyUtils.setMappedProperty(Object, String, String, Object)
  • 嵌套类型:
    • PropertyUtils.getNestedProperty(Object, String)
    • PropertyUtils.setNestedProperty(Object, String, Object)
  • 通用类型:
    • PropertyUtils.getProperty(Object, String)
    • PropertyUtils.setProperty(Object, String, Object)

示例:

//定义bean
@Data
@ToString
public class Course {
	private String name;
    private List<String> codes;
    private Map<String, Student> enrolledStudent = new HashMap<>();
}
@Data
@ToString
public class Student {
	private String name;
}

//测试
Course course = new Course(); //该类必须是public的、且有默认构造方法

String name = "Computer Science";
List<String> codes = Arrays.asList("CS", "CS01");

//Simple Property
PropertyUtils.setSimpleProperty(course, "name", name);
PropertyUtils.setSimpleProperty(course, "codes", codes);
System.out.println(course);
String nameV = (String)PropertyUtils.getSimpleProperty(course, "name");
System.out.println(nameV);

//Indexed Property
PropertyUtils.setIndexedProperty(course, "codes[1]", "CS02");
PropertyUtils.setIndexedProperty(course, "codes", 1, "CS03");
System.out.println(course);
String indexedProperty = (String)PropertyUtils.getIndexedProperty(course, "codes", 1);
String indexedProperty2 = (String)PropertyUtils.getIndexedProperty(course, "codes[1]");
System.out.println(indexedProperty + "," + indexedProperty2);

Student student = new Student();
String studentName = "Joe";
student.setName(studentName);

//Mapped Property
PropertyUtils.setMappedProperty(course, "enrolledStudent(ST-1)", student);
PropertyUtils.setMappedProperty(course, "enrolledStudent", "ST-1", student);
System.out.println(course);
Student mappedProperty = (Student)PropertyUtils.getMappedProperty(course, "enrolledStudent", "ST-1");
Student mappedProperty2 = (Student)PropertyUtils.getMappedProperty(course, "enrolledStudent(ST-1)");
System.out.println(mappedProperty + "," + mappedProperty2);

//Nested Property
PropertyUtils.setNestedProperty(course, "enrolledStudent(ST-1).name", "Joe_1");
String nameValue = (String) PropertyUtils.getNestedProperty(course, "enrolledStudent(ST-1).name");
//等价于 String name = course.getEnrolledStudent("ST-1").getName();
System.out.println(nameValue);

以上还可以使用下面的方式:

private static void test1_1() throws Exception {
        Course course = new Course();
        
        String name = "Computer Science";
        List<String> codes = Arrays.asList("CS", "CS01");
        
        //Simple Property
        PropertyUtils.setProperty(course, "name", name);
        PropertyUtils.setProperty(course, "codes", codes);
        System.out.println(course);
        String nameV = (String)PropertyUtils.getProperty(course, "name");
        System.out.println(nameV);
        
        //Indexed Property
        PropertyUtils.setProperty(course, "codes[1]", "CS02");
        System.out.println(course);
        
        Student student = new Student();
        String studentName = "Joe";
        student.setName(studentName);
        
        //Mapped Property
        PropertyUtils.setProperty(course, "enrolledStudent(ST-1)", student);
        System.out.println(course);
        
        //Nested Property
        PropertyUtils.setProperty(course, "enrolledStudent(ST-1).name", "Joe_1");
        String nameValue = (String) PropertyUtils.getProperty(course, "enrolledStudent(ST-1).name");
        System.out.println(nameValue);
}

2)BeanUtils设置、获取属性:

BeanUtils只有以下两个方法来设置、获取属性

  • BeanUtils.getProperty(Object, String)
  • BeanUtils.setProperty(Object, String, Object)

 示例:

private static void test1_2() throws Exception {
        Course course = new Course();
        
        String name = "Computer Science";
        List<String> codes = Arrays.asList("CS", "CS01");
        
        //Simple Property
        BeanUtils.setProperty(course, "name", name);
        BeanUtils.setProperty(course, "codes", codes);
        System.out.println(course);
        String nameV = (String)BeanUtils.getProperty(course, "name");
        System.out.println(nameV);
        
        //Indexed Property
        BeanUtils.setProperty(course, "codes[1]", "CS02");
        System.out.println(course);
        
        Student student = new Student();
        String studentName = "Joe";
        student.setName(studentName);
        
        //Mapped Property
        BeanUtils.setProperty(course, "enrolledStudent(ST-1)", student);
        System.out.println(course);
        
        //Nested Property
        BeanUtils.setProperty(course, "enrolledStudent(ST-1).name", "Joe_1");
        String nameValue = (String) BeanUtils.getProperty(course, "enrolledStudent(ST-1).name");
        System.out.println(nameValue);
}

2、拷贝Bean的属性

2.1)BeanUtils有一下两个方法:

  • populate:把Map里的键值对值拷贝到bean的属性值中;
  • copyProperties:拷贝一个bean的属性到另外一个bean中,注意是浅拷贝

注意:populate和copyProperties的区别,对于Integer、Float、Boolean类型前者(populate)对于null值,在拷贝到Bean的属性后会变成默认值。

1)populate:

//bean定义
import java.util.Date;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class Employee {
	private Integer id;
	private String name;
	private Boolean isGood;
   private Float score;
	private Date createTime;
	
	public Employee(Integer id, String name, Boolean isGood, Float score, Date createTime) {
           this.id = id;
           this.name = name;
           this.isGood = isGood;
           this.score = score;
           this.createTime = createTime;
	}
}
//测试
Map<String, Object> map = new HashMap<>(2);
map.put("id", null);
map.put("name", "employee1");
map.put("isGood", null);
map.put("createTime", new Date()); //如果是null,会报错
map.put("add", "add1");
// map > obj
Employee e = new Employee();
BeanUtils.populate(e, map);
System.out.println(e); //Employee(id=0, name=employee1, isGood=false, createTime=Tue Aug 15 10:42:14 CST 2023)

//支持类型转换
Map<String, Object> map = new HashMap<>(5);
map.put("id", "123"); 
map.put("name", 1.9);
map.put("isGood", "2"); 
map.put("score", null);
map.put("createTime", new Date());
map.put("add", "add1");
// map > obj
Employee e = new Employee();
BeanUtils.populate(e, map);
System.out.println(e); //Employee(id=123, name=1.9, isGood=false, score=1.0, createTime=Tue Aug 15 12:34:41 CST 2023)

说明:

  • 对于Integer、Float、Boolean类型,如果是null,则转成bean的属性后会变成默认值(0,0.1,false)
  • 对于Date类型,如果是null或者其他类型,转成bean的时候会报错,需要使用ConvertUtils进行类型转换(见下面)
  • 支持类型转换:比如Integer和String之间

2)copyProperties:

有另外一个对象(类型和Employee不同)

@Data
public class Employee2 {
	private Integer id;
	private String name;
	private String isGood;
	private String score;
	private String createTime;
	private Float f1;
}

测试

private static void test2_1() throws Exception {
        Employee ee = new Employee(null, "employee2", null, null, null);
        Employee2 e1 = new Employee2();
        BeanUtils.copyProperties(e1, ee);
        System.out.println(e1); //Employee2(id=null, name=employee2, isGood=null, score=null, createTime=null, f1=null)
        
        Employee ee2 = new Employee(1, "employee2", true, 4.3f, new Date());
        Employee2 e2 = new Employee2();
        BeanUtils.copyProperties(e2, ee2);
        System.out.println(e2); //Employee2(id=1, name=employee2, isGood=true, score=4.3, createTime=Tue Aug 15 11:45:06 CST 2023, f1=null)
}

说明:

  • 对于Integer、Float、Boolean、Date类型,如果是null,拷贝后也是null
  • 支持类型转换:两个bean只要属性名一样,类型可转换即可拷贝。比如Integer、Float、Boolean类型转成String

2.2)PropertyUtils进行属性拷贝:

1)和BeanUtils区别:

  • PropertyUtils只支持两个Bean之间的属性拷贝,不支持Map到Bean的
  • PropertyUtils在两个Bean之间进行属性拷贝时,必须要保证名字和类型都一样才行,否则会报错。BeanUtils在进行属性拷贝时,名字一样,类型可转换即可。

 

Employee ee = new Employee(null, "employee2", null, null, null);
Employee2 e1 = new Employee2();
PropertyUtils.copyProperties(e1, ee);
System.out.println(e1); //Employee2(id=null, name=employee2, isGood=null, score=null, createTime=null, f1=null)

Employee ee2 = new Employee(1, "employee2", true, 4.3f, new Date());
Employee2 e2 = new Employee2();
PropertyUtils.copyProperties(e2, ee2);
System.out.println(e2); //报错

报错信息:

 

2)说明:

  • PropertyUtils不支持类型转换。
  • 对于null值,PropertyUtils拷贝后也是null

3、ConvertUtils自定义类型转换

1)DateConverter:

DateConverter继承DateTimeConverter,是beanutils包中自带的时间类型转换,包含了:

示例

DateConverter converter = new DateConverter();
converter.setPattern("yyyy-MM-dd");
ConvertUtils.register(converter, java.util.Date.class);

Map<String, Object> map = new HashMap<>(5);
map.put("id", 1); 
map.put("name", "testConvertUtils");
map.put("isGood", false); //可以是Integer或String,1或"1" true 其他表示false,null表示false
map.put("score", 1.1f);
map.put("createTime", "2023-08-15");
map.put("add", "add1");

// map > obj
Employee e = new Employee();
BeanUtils.populate(e, map);
System.out.println(e); //Employee(id=1, name=testConvertUtils, isGood=false, score=1.1, createTime=Tue Aug 15 00:00:00 CST 2023)

2)自定义: 

ConvertUtils.register(new Converter() {
    public Object convert(Class type, Object value) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            return simpleDateFormat.parse(value.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}, Date.class);
Employee e1 = new Employee();
BeanUtils.setProperty(e1, "createTime", "2022-09-09");
System.out.println(e1.getCreateTime()); //Fri Sep 09 00:00:00 CST 2022

说明:对于setProperty,如果存在时间类型,需要自定义转换器。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/911426.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MyBatis的核心技术掌握,简单易懂

目录 一.MyBatis中的动态SQL 二.MyBatis中的模糊查询 1. # 符号 2. $ 符号 ---问题 ---所以大家知道 # 和 $ 在MyBatis中的模糊查询中的区别了嘛&#xff1f;&#xff1f; 三.MyBatis 中的结果映射 1. resultType&#xff1a; 2. resultMap&#xff1a; ---问题 ---…

grpc整合Springboot

一、grpc的依赖 <dependencies><dependency><groupId>net.devh</groupId><artifactId>grpc-server-spring-boot-starter</artifactId><version>2.9.0.RELEASE</version></dependency></dependencies><build>…

技术未来论:为何校对将是AI时代的新前沿

随着信息时代的逐步深化&#xff0c;AI技术已成为全球进程中的核心动力。其深远的影响已经触及了社会的各个领域。而在这充满机器智慧的时代&#xff0c;一个古老的领域——校对&#xff0c;却意外地与AI结合&#xff0c;成为了新的技术前沿。这是为何&#xff1f; 1.信息的尊…

YOLO目标检测算法调试过程学习记录

先前已经完成过YOLO系列目标检测算法的调试过程&#xff0c;今天主要是将所有的调试加以总结 这里的conda环境就不再赘述了&#xff0c;直接使用requirement.txt文件的即可&#xff0c;也可以参考YOLOX的配置过程5 数据集处理 YOLOv5有自己的数据集格式&#xff0c;博主的数据…

面试热题(二叉树的最大路径)

路径 被定义为一条从树中任意节点出发&#xff0c;沿父节点-子节点连接&#xff0c;达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点&#xff0c;且不一定经过根节点。 路径和 是路径中各节点值的总和。 给定一个二叉树的根节点 root…

Electron学习2 使用Electron-vue和Vuetify UI库

Electron学习2 使用Electron-vue和Vuetify UI库 一、Electron-vue简介二、安装yarn三、创建Electron-vue项目1. 关于 electron-builder2. 安装脚手架3. 运行4. 打包应用程序 四、background.js说明1. 引入模块和依赖&#xff1a;2. 注册协议&#xff1a;3. 创建窗口函数&#x…

企业内部wiki系统工具有哪些?盘点 8款最佳 Wiki 系工具

WiKi支持面向社群的协作式写作&#xff0c;同时也包括一组支持这种写作的辅助工具。有人认为&#xff0c;Wiki系统属于一种人类知识的网络系统&#xff0c;我们可以在Web的基础上对Wiki文本进行浏览、创建、更改&#xff0c;而且这种创建、更改、及发布的代价远比HTML文本小 &a…

Java“牵手”根据关键词搜索(分类搜索)lazada商品列表页面数据获取方法,lazadaAPI实现批量商品数据抓取示例

lazada商城是一个网上购物平台&#xff0c;售卖各类商品&#xff0c;包括服装、鞋类、家居用品、美妆产品、电子产品等。要获取lazada商品列表和商品详情页面数据&#xff0c;您可以通过开放平台的接口或者直接访问lazada商城的网页来获取商品详情信息。以下是两种常用方法的介…

通达信指标公式15:除权除息数据统计分析

#1.关于除权除息指标的介绍&#xff1a;本指标是小红牛原创指标之一&#xff0c;觉得有必要研究一下这个问题&#xff0c;所以就花时间整理一下这个指标相关内容&#xff0c;大家可以在本源码基础上&#xff0c;进一步优化自己的思路。本指标为通达信幅图指标&#xff0c;可以做…

关于通达信指标公式中,出现乱码的解决方法

★★★★★博文原创不易&#xff0c;我的博文不需要打赏&#xff0c;也不需要知识付费&#xff0c;可以白嫖学习小技巧&#xff0c;喜欢的老铁可以多多帮忙点赞&#xff0c;小红牛在此表示感谢&#xff0c;就是对作者的最大支持。愿与诸君共勉&#xff0c;悟道于股市★★★★★…

软件测试下的AI之路(1)

&#x1f60f;作者简介&#xff1a;博主是一位测试管理者&#xff0c;同时也是一名对外企业兼职讲师。 &#x1f4e1;主页地址&#xff1a;【Austin_zhai】 &#x1f646;目的与景愿&#xff1a;旨在于能帮助更多的测试行业人员提升软硬技能&#xff0c;分享行业相关最新信息。…

手机无人直播软件,有哪些优势?

近年来&#xff0c;随着手机直播的流行和直播带货的市场越来越大&#xff0c;手机无人直播软件成为许多商家开播带货的首选。在这个领域里&#xff0c;声音人无人直播系统以其独特的优势&#xff0c;成为市场上备受瞩目的产品。接下来&#xff0c;我们将探讨手机无人直播软件给…

IO流笔记

文件基础知识 创建文件 package org.example; import org.junit.Test;import java.io.File; import java.io.IOException;public class FileCreate{public static void main(String[] args) {}Test//方式1&#xff1a;new File(Strin pathname)public void create01(){File fil…

innovus如何设置size only

我正在「拾陆楼」和朋友们讨论有趣的话题&#xff0c;你⼀起来吧&#xff1f; 拾陆楼知识星球入口 给instance设置size only属性命令如下: dbset [dbGet top.inst.name aa/bb -p] .dontTouch sizeOk 给一个module设置size only需要foreach循环一下: foreach inst [dbGet top.…

Docker常用操作命令(二)

Docker常用操作命令(二) 11、进入容器 docker exec -it 容器名称or容器ID /bin/bash [rootzch01 ~]# docker exec -it 973ff3caff19 /bin/bash 退出容器 root973ff3caff19:/# exit 12、查看容器中的进程 docker top 容器名称or容器ID [rootzch01 ~]# docker top 973ff3c…

Sui第四轮资助:16个团队瓜分

近日&#xff0c;Sui基金会公布了第四轮开发者资助名单&#xff0c;受助项目均是集中在DeFi、支付、基础设施、游戏、预言机等领域的Sui生态项目&#xff0c;他们是从2023年7月1日之前提交的申请中选出的。在此时间之后提交的任何项目目前正在审查中。 在前三轮资助中累积发放…

魔术般的平板式扫描仪,OCR好帮手,文档数字化一键搞定

平板式扫描仪是一种常见的扫描设备&#xff0c;通常用于将纸质文档转换为数字格式&#xff08;OCR&#xff09;&#xff0c;一般的复印店和办公室等场所使用的基本上都是这种扫描仪。它由一个平坦的玻璃板和一个移动的扫描头组成。用户将纸质文档放置在平板上&#xff0c;然后通…

WebDAV之π-Disk派盘 + 一羽记帐

一羽记帐是一款真正让你体验3S极速记账的轻量级APP。针对个人记账,没有花哨冗余的功能。界面美丽、无广告、极速启动、功能全面。一羽记帐功能涵括广,基本可以满足90%人的记账需求。完全无侵入、百分百无广告,无需担心数据安全,所有的操作都不经过任何第三方。 π-Disk派盘…

Leetcode.73矩阵置零

给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法 class Solution {public void setZeroes(int[][] matrix) {int m matrix.length, n matrix[0].length;boolean[] row new boolean[m];boolean[] col…

聚观早报 | 网龙发布EDA白皮书;日产合资旗下品牌使用东风纯电

【聚观365】8月22日消息 网龙发布EDA白皮书 日产合资公司旗下自主品牌将使用东风纯电平台 vivo Pad Air评测 辛巴818五周年专场带货GMV达22.3亿 X删除2014年12月前大多数图片和推文链接 网龙发布EDA白皮书 近日消息&#xff0c;由北京师范大学和联合国教科文组织教育信息…