Java常用基础工具库 下面涉及到的示例代码,皆可以通过Github地址https://github.com/Builder34/toolkit-demo 获取.
通用工具类(字符串、时间格式化、BeanUtils、IO) 1. commons-lang3库 1.1. org.apache.commons.lang3.StringUtils类 日常代码中,我们经常和String字符串打交道,经常对字符串进行处理,稍微不注意的话,很容易出现类似NullPointerException这种简单的错误,我们经常写各种if来判断处理这些非业务的逻辑。这时,我们可以利用大牛apache的轮子,通过其StringUtils里面的一些常用方法,改善我们的代码,让我们的业务代码更简洁、优雅。 示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Slf 4jpublic class AppTest { @Test public void stringUtils () { String a = " " ; String b = null ; log.info("StringUtils.isEmpty(a): {}" , StringUtils.isEmpty(a)); log.info("StringUtils.isBlank(a): {}" , StringUtils.isBlank(a)); log.info("StringUtils.trim(d): {}" , StringUtils.trim(b)); String num = "12.3" ; log.info("org.apache.commons.lang3.StringUtils.isNumericSpace(): {} isNumber: {}" , num, StringUtils.isNumericSpace(b)); log.info("com.alibaba.druid.util.StringUtils.isNumber(): {} isNumber: {}" , num, com.alibaba.druid.util.StringUtils.isNumber(num)); } }
注意:common-lang3中的StringUtils. isNumeric()或isNumericSpace()并不能判断字符串中带小数点的数字值字符为数字。可以通过com.alibaba.druid.util.StringUtils.isNumber(str),此方法来判断。
时间转换工具类:
1 2 3 4 5 6 7 8 @Test public void dateFormatUtils () throws Exception { String pattern = "yyyy-MM-dd HH:mm:ss" ; String timeStr = DateFormatUtils.format(new Date(), pattern); long timestamp = DateUtils.parseDate(timeStr, pattern).getTime(); log.info("==> current time: {}" , timeStr); log.info("==> current time timestamp: {}" , timestamp); }
总结
StringUtils.isEmpty(str)/StringUtils.isNotEmpty(str): 判断字符对象是否为null或空串(有空格则认为不是空串)
StringUtils.isBlank(str)/StringUtils.isNotBlank(str): 判断字符对象是否为null或空串(有空格也会认为是空串)
DateFormatUtils.format(date, pattern): 将Date时间对象按表达式的格式转换成时间字符串
DateUtils.parseDate(timeStr, pattern): 将时间字符串反转成Date对象
ToStringBuilder.reflectionToString(obj): 将对象内容转换成字符串输出(下一节有使用到)
…
对于学习某个工具类,我们可以通过Intellij IDEA中可通过打开此类的源代码,然后通过快捷键(MacOS: command+7; Windows: Alt+7)打开查看类方法列表(Structure),从方法名字上大概可以看出具体有那些适合自己使用的方法。
以上示例使用到的jar包可通过maven的pom.xml文件依赖导入:
1 2 3 4 5 6 7 8 9 10 <dependency > <groupId > org.apache.commons</groupId > <artifactId > commons-lang3</artifactId > <version > 3.8.1</version > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > druid</artifactId > <version > 1.1.9</version > </dependency >
2.common-beanutils库 Map、JavaBean是我们日常业务代码中经常使用到的2种类,有时因为业务原因,Map、JavaBean需要相互转换copy啥的操作时,如果手动set/put,字段多的时候,就要吐血了。这里我们推荐使用BeanUtils来简化我们的代码
2.1.org.apache.commons.beanutils.BeanUtils类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 @Test public void beanUtils () throws InvocationTargetException, IllegalAccessException { CompanyBean bean = new CompanyBean(); bean.setId(1 ); bean.setName("中国移动广州分公司" ); bean.setAddress("广州市天河区中山大道" ); bean.setTel("020-10086000" ); CompanyBean destObj = new CompanyBean(); BeanUtils.copyProperties(destObj, bean); log.info("destObj from BeanUtils.copyProperties: {}" , ToStringBuilder.reflectionToString(destObj)); Map<String, Object> map = new HashMap<>(); map.put("id" , 2 ); map.put("name" , "中国联通广州分公司" ); map.put("address" , "广州市天河区中山大道2号" ); map.put("tel" , "020-10000110" ); BeanUtils.populate(destObj, map); log.info("destObj from BeanUtils.populate: {}" , ToStringBuilder.reflectionToString(destObj)); CompanyBean cloneBean = (CompanyBean)BeanUtils.cloneBean(destObj); log.info("cloneBean from BeanUtils.cloneBean: {}" , ToStringBuilder.reflectionToString(cloneBean)); Map newMap = BeanUtils.describe(cloneBean); log.info("newMap from BeanUtils.describe: {}" , new Gson().toJson(newMap)); }
日志输出如下:
1 2 3 2019 -01 -19 13 :17 :21 .064 [main] INFO com.monbuilder .AppTest - destObj from BeanUtils.copyProperties : com.monbuilder .bean .CompanyBean @10683 d9d[id=1 ,name=中国移动广州分公司,address=广州市天河区中山大道1 号,tel=020 -10086000 ]2019 -01 -19 13 :17 :21 .070 [main] INFO com.monbuilder .AppTest - destObj from BeanUtils.populate : com.monbuilder .bean .CompanyBean @10683 d9d[id=2 ,name=中国联通广州分公司,address=广州市天河区中山大道2 号,tel=020 -10000110 ]2019 -01 -19 13 :48 :14 .966 [main] INFO com.monbuilder .AppTest - newMap from BeanUtils.describe : {"address" :"广州市天河区中山大道2号" ,"name" :"中国联通广州分公司" ,"tel" :"020-10000110" ,"id" :"2" ,"class" :"class com.monbuilder.bean.CompanyBean" }
总结
BeanUtils.copyProperties(destObj, sourceObj): JavaBean之间内容的复制
BeanUtils.cloneBean(obj): 复制对象
BeanUtils.populate(destObj, sourceMap): Map转换成JavaBean
BeanUtils.describe(bean): 将JavaBean转换成Map
3.commons-io库 org.apache.commons.io.IOUtils类 这个io工具类非常有用,当我们在处理流的过程中,经常需要把流与字节数组之间相互转换,以及在处理完之后,关闭流等等这些操作时,我们需要写挺多处理逻辑,close时还需要写if判空啥的,但是使用了这个IOUtil后,我们的处理代码或简洁非常多的。
1 2 3 4 5 6 7 8 @Test public void ioUtils () throws IOException { InputStream io = this .getClass().getClassLoader().getResourceAsStream("README.md" ); BufferedReader br = new BufferedReader(new InputStreamReader(io)); log.info("==> IOUtils.toString(br): {}" , IOUtils.toString(br)); IOUtils.closeQuietly(br); IOUtils.closeQuietly(io); }
1 2019 -01 -19 14 :29 :26 .140 [main] INFO com.monbuilder .AppTest - ==> IOUtils.toString (br): toolkit-demo,工具类库使用示例
上面只是简单的展示将文件流内容转换成字符串,之后再关闭流,是不是非常简洁呢?IOUtils里面还有非常多的好方法可以使用,这些可以根据自己在具体的工作场景下,查看IOUtils的方法列表,找到自己需要的方法
总结 IOUtils常用的方法有:
IOUtils.closeQuietly(obj): 可关闭流\Socket\SocketServer等多种对象
IOUtils.copy(InputStream, Writer): 复制输入流
IOUtils.write(byte[], OutputStream): 将字节数组转换成流
IOUtils.toByteArray(InputStream): 将输入流转换成字节数组
IOUtils.toInputStream(String): 将字符串转换成输入流
IOUtils.toString(InputStream): 将输入流转换成字符串
上面介绍的都是来自于apache官方的类库,还有好多类与方法有待我们发掘使用。另外,还介绍另1个非常有名的工具类库:guava,来自于Google;功能也有类似的,当然也有很多的扩展使用,本文就不再详细介绍了。
1 2 3 4 5 <dependency > <groupId > com.google.guava</groupId > <artifactId > guava</artifactId > <version > 23.2-jre</version > </dependency >
JSON工具类 在如今REST API盛行的年代,前后端分离成为标配,json成为两者之间的传输桥梁,在我们工作做打交道肯定非常频繁咯。在Java开发中,JSON工具类的选择并不少:
fastjson 阿里巴巴出品,转换快,但表现不够稳定
Gson google出品,使用简单,轻量
Jackson spring官方使用,性能快,转换快,配置更灵活,不同场景下表现更稳定
比较推荐使用的是Jackson,如果我们使用Spring Boot或Spring Cloud时,构建web项目里面内置的json库就是Jackson库。
下面通过Jackson库简单封装成JavaBean/json互转的工具类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 package com.monbuilder.util;import com.fasterxml.jackson.annotation.JsonInclude;import com.fasterxml.jackson.core.JsonParser;import com.fasterxml.jackson.databind.DeserializationFeature;import com.fasterxml.jackson.databind.ObjectMapper;import lombok.extern.slf4j.Slf4j;import java.text.SimpleDateFormat;@Slf 4jpublic class JacksonUtil { private static ObjectMapper objectMapper = new ObjectMapper(); static { objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true ); objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true ); objectMapper.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true ); objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss" )); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false ); objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); } public static <T> T toJavaObject (String json, Class<T> objClass) { try { return objectMapper.readValue(json, objClass); } catch (Exception e) { log.error("" , e); return null ; } } public static String toJsonString (Object obj) { try { return objectMapper.writeValueAsString(obj); } catch (Exception e) { log.error("" ,e); } return "{}" ; } }
运用上面的工具类,示例:
1 2 3 4 5 6 7 8 9 10 11 12 @Test public void jsonUtils(){ CompanyBean bean = new CompanyBean() bean.setId(1); bean.setName("中国移动广州分公司"); bean.setAddress("广州市天河区中山大道1号"); bean.setTel("020-10086000"); log.info("==> JacksonUtil.toJsonString(bean): {}" , JacksonUtil.toJsonString(bean)); String json = JacksonUtil.toJsonString(bean); log.info("==> JacksonUtil.toJavaObject: {}" , ToStringBuilder.reflectionToString(JacksonUtil.toJavaObject(json, CompanyBean.class))) }
1 2 2019 -01 -19 15 :42 :16 .081 [main] INFO com.monbuilder .AppTest - ==> JacksonUtil.toJsonString (bean): {"id" :1 ,"name" :"中国移动广州分公司" ,"address" :"广州市天河区中山大道1号" ,"tel" :"020-10086000" }2019 -01 -19 15 :42 :16 .144 [main] INFO com.monbuilder .AppTest - ==> JacksonUtil.toJavaObject : com.monbuilder .bean .CompanyBean @376 a0d86[id=1 ,name=中国移动广州分公司,address=广州市天河区中山大道1 号,tel=020 -10086000 ]
最后想要说的是,轮子非常多,当然我们可以重复造轮子,但是我们更提倡的是使用已有优秀的轮子(工具类),开发出更简洁、优雅、业务逻辑更清晰的代码。