feilong-core 亮点

  • 有常用专属工具类 (如处理日期的 DateUtil,处理集合的 CollectionsUtil,类型转换的ConvertUtil 等等等)
  • 有常用JAVA常量类 (如日期格式 DatePattern, 时间间隔 TimeInterval 等等等)
  • 不必要的Exception 转成RuntimeException,减少不必要的代码
  • 国内中文注释最完善的API
  • 有完善的单元测试

1."看一眼就会爱上他"的方法

1.1 ConvertUtil.toList(T…)

曾经,你调用某个api时,该api需要一个list参数, 但是你现在只有单对象

你需要这么写

  1. List<Long> itemIds = new ArrayList<>();
  2. itemIds.add(itemId);
  3. sdkItemManager.findItemImageByItemIds(itemIds);

总感觉怪怪的, 很烦人

你现在可以这么写

  1. sdkItemManager.findItemImageByItemIds(ConvertUtil.toList(itemId));

一行代码,轻松快乐的写代码

同样,下面的代码

  1. List<Long> skuIds = new ArrayList<>();
  2. skuIds.add(9L);
  3. skuIds.add(10L);
  4. skuIds.add(13L);
  5. skuIds.add(18L);
  6. skuIds.add(20L);
  7. BundleValidateResult result = bundleManager.validateBundle(skuIds);

依然,可以简写

  1. List<Long> skuIds=ConvertUtil.toList(9L, 10L, 13L, 18L, 20L);
  2. BundleValidateResult result = bundleManager.validateBundle(skuIds);

代码的可读性更高,更简洁

PS:如果使用 import static 代码可以更简洁

1.2 CollectionsUtil.getPropertyValueList(Collection<O>, String)

循环集合 objectCollection,取到对象指定的属性 propertyName 的值,拼成 List(ArrayList).

很多场合下,手头上有 bean list, 但是操作的时候,你可能需要使用每个bean里面的某个属性

比如: 提取SalesOrderCommand list里面的id属性组成 List<Long>

  1. List<SalesOrderCommand> salesOrderPage = sdkOrderDao.findOrdersWithOutPage(sorts, searchParam);
  2. //...
  3. List<Long> idList = new ArrayList<>(salesOrderPage.size());
  4. for (SalesOrderCommand cmd : salesOrderPage){
  5. idList.add(cmd.getId());
  6. }
  7. //查询订单行
  8. List<OrderLineCommand> allLineList = sdkOrderLineDao.findOrderDetailListByOrderIds(idList);

这段代码,可以一行代码搞定

  1. List<SalesOrderCommand> salesOrderPage = sdkOrderDao.findOrdersWithOutPage(sorts, searchParam);
  2. //...
  3. List<Long> idList =CollectionsUtil.getPropertyValueList(salesOrderPage, "id");
  4. //查询订单行
  5. List<OrderLineCommand> allLineList = sdkOrderLineDao.findOrderDetailListByOrderIds(idList);

PS: 相似的方法,还有 CollectionsUtil.getPropertyValueSet(Collection<O>, String) 以及 CollectionsUtil.getPropertyValueMap(Collection<O>, String, String)

2.不能不说的异常处理

众所周知,JAVA 有 checked exceptionuncheckedException 之分,也就是我们常说的 RuntimeExceptionException

checked exception有其使用场景,但是我们日常开发过程中,并没有对他做特殊的代码处理

比如,大部分小伙伴的代码是这样的:

  1. public ContactCommand toContactCommand(ContactCommand command) {
  2. try {
  3. BeanUtils.copyProperties(command, this);
  4. } catch (Exception e){
  5. LOGGER.error("", e);
  6. //or e.printStackTrace();
  7. }
  8. return command;
  9. }

其实细究下来,上述代码是不合理的, 如果转换的时候出现了异常,这里就会出现数据没有转换过去的情况,

这理论上是 RuntimeException,但是 org.apache.commons.beanutils.BeanUtils 里面使用的是Exception, 所以小伙伴不能不try… catch一下,可是 catch 代码里面有可能仅仅写了log记录,这有可能会出现逻辑问题 (本来需要抛出异常让事务回滚)

这时可以使用 com.feilong.core.bean.BeanUtil

  1. public ContactCommand toContactCommand(ContactCommand command){
  2. com.feilong.core.bean.BeanUtil.copyProperties(command, this);
  3. return command;
  4. }

当然,如果你确定copy的对象相同属性名称的类型是一致的, 你可以使用 PropertyUtil ,可以有效的避免不必要的类型转换,提高效率

代码简洁,而且内部包装成的是自定义的 BeanOperationException(RuntimeException),如果需要特殊处理,依然可以 try…catch…

3. 有丰富的javadoc

调用方法的时候,可以清晰的感知这个方法的 作用,示例,说明点,参数,返回值,异常等信息

feilong-core 亮点 - 图1

源码示例:

  1. /**
  2. * 计算两个时间相差的的天数(<span style="color:red">绝对值</span>).
  3. *
  4. * <h3>说明:</h3>
  5. * <blockquote>
  6. * <p>
  7. * 值=两个时间相差毫秒的绝对值/{@link TimeInterval#MILLISECOND_PER_DAY}
  8. * </p>
  9. * </blockquote>
  10. *
  11. * <h3>示例:</h3>
  12. *
  13. * <blockquote>
  14. *
  15. * <pre class="code">
  16. * DateExtensionUtil.getIntervalDay(
  17. * toDate("2008-08-24",COMMON_DATE),
  18. * toDate("2008-08-27",COMMON_DATE)) = 3
  19. *
  20. * DateExtensionUtil.getIntervalDay(
  21. * toDate("2016-08-21 12:00:00",COMMON_DATE_AND_TIME),
  22. * toDate("2016-08-22 11:00:00",COMMON_DATE_AND_TIME)) = 0
  23. *
  24. * DateExtensionUtil.getIntervalDay(
  25. * toDate("2016-08-21",COMMON_DATE),
  26. * toDate("2016-08-22",COMMON_DATE)) = 1
  27. *
  28. * DateExtensionUtil.getIntervalDay(
  29. * toDate("2016-02-28",COMMON_DATE),
  30. * toDate("2016-03-02",COMMON_DATE)) = 3
  31. *
  32. * DateExtensionUtil.getIntervalDay(
  33. * toDate("2016-08-31",COMMON_DATE),
  34. * toDate("2016-09-02",COMMON_DATE)) = 2
  35. *
  36. * </pre>
  37. *
  38. * </blockquote>
  39. *
  40. * @param date1
  41. * date1
  42. * @param date2
  43. * date2
  44. * @return 如果 <code>date1</code> 是null,抛出 {@link NullPointerException}<br>
  45. * 如果 <code>date2</code> 是null,抛出 {@link NullPointerException}
  46. * @see #getIntervalTime(Date, Date)
  47. * @see #getIntervalDay(long)
  48. * @since 1.6.0
  49. */
  50. public static int getIntervalDay(Date date1,Date date2){
  51. return getIntervalDay(getIntervalTime(date1, date2));
  52. }

如果你使用maven的话,只需要在依赖的jar 右键, maven—> download javadoc 或者 download sources 会自动下载

feilong-core 亮点 - 图2

4. 每个方法均有完善的 junit test

方法实现之后,有上述的javadoc 详细的描述这个方法的作用 特点,注意点等, 那么怎么证明你写的东西都是正确而胡编乱造的呢?

我们有详细的 junit 单元测试, 每次构建的时候,都会经过maven 的单元测试周期

比如 MapUtilGetSubMapTest

  1. package com.feilong.core.util.maputiltest;
  2. import static java.util.Collections.emptyMap;
  3. import static org.hamcrest.Matchers.allOf;
  4. import static org.hamcrest.Matchers.hasEntry;
  5. import static org.hamcrest.Matchers.hasKey;
  6. import static org.hamcrest.Matchers.not;
  7. import static org.junit.Assert.assertEquals;
  8. import static org.junit.Assert.assertThat;
  9. import java.util.HashMap;
  10. import java.util.Map;
  11. import org.junit.Test;
  12. import com.feilong.core.util.MapUtil;
  13. public class MapUtilGetSubMapTest{
  14. /**
  15. * Test get sub map.
  16. */
  17. @Test
  18. public void testGetSubMap(){
  19. Map<String, Integer> map = new HashMap<String, Integer>();
  20. map.put("a", 3007);
  21. map.put("b", 3001);
  22. map.put("c", 3001);
  23. map.put("d", 3003);
  24. Map<String, Integer> subMap = MapUtil.getSubMap(map, "a", "c");
  25. assertThat(subMap, allOf(hasEntry("a", 3007), hasEntry("c", 3001), not(hasKey("b")), not(hasKey("d"))));
  26. }
  27. /**
  28. * Test get sub map 1.
  29. */
  30. @Test
  31. public void testGetSubMap1(){
  32. Map<String, Integer> map = new HashMap<String, Integer>();
  33. map.put("a", 3007);
  34. map.put("b", 3001);
  35. map.put("c", 3001);
  36. map.put("d", 3003);
  37. Map<String, Integer> subMap = MapUtil.getSubMap(map, "a", "c", "f");
  38. assertThat(subMap, allOf(hasEntry("a", 3007), hasEntry("c", 3001), not(hasKey("b")), not(hasKey("d"))));
  39. }
  40. /**
  41. * Test get sub map null keys.
  42. */
  43. @Test
  44. public void testGetSubMapNullKeys(){
  45. Map<String, Integer> map = new HashMap<String, Integer>();
  46. map.put("a", 3007);
  47. map.put("b", 3001);
  48. map.put("c", 3001);
  49. map.put("d", 3003);
  50. assertEquals(map, MapUtil.getSubMap(map, null));
  51. }
  52. /**
  53. * Test get sub map empty keys.
  54. */
  55. @Test
  56. public void testGetSubMapEmptyKeys(){
  57. Map<String, Integer> map = new HashMap<String, Integer>();
  58. map.put("a", 3007);
  59. map.put("b", 3001);
  60. map.put("c", 3001);
  61. map.put("d", 3003);
  62. assertEquals(map, MapUtil.getSubMap(map));
  63. }
  64. /**
  65. * Test get sub map null map.
  66. */
  67. @Test
  68. public void testGetSubMapNullMap(){
  69. assertEquals(emptyMap(), MapUtil.getSubMap(null, "a", "c"));
  70. }
  71. /**
  72. * Test get sub map empty map.
  73. */
  74. @Test
  75. public void testGetSubMapEmptyMap(){
  76. assertEquals(emptyMap(), MapUtil.getSubMap(new HashMap<>(), "a", "c"));
  77. assertEquals(emptyMap(), MapUtil.getSubMap(emptyMap(), "a", "c"));
  78. }
  79. }