Skip to content
This repository has been archived by the owner on Aug 20, 2021. It is now read-only.

Reasons for use feilong core

feilong edited this page Jan 13, 2017 · 12 revisions

对比1:

对比2:

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

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

1.1 ConvertUtil.toList(T...)

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

你需要这么写

List<Long> itemIds = new ArrayList<>();
itemIds.add(itemId);

sdkItemManager.findItemImageByItemIds(itemIds);

总感觉怪怪的, 很烦人

你现在可以这么写

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

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

同样,下面的代码

List<Long> skuIds = new ArrayList<>();
skuIds.add(9L);
skuIds.add(10L);
skuIds.add(13L);
skuIds.add(18L);
skuIds.add(20L);
BundleValidateResult result = bundleManager.validateBundle(skuIds);

依然,可以简写

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

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

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

1.2 CollectionsUtil.getPropertyValueList(Collection, String)

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

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

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

List<SalesOrderCommand> salesOrderPage = sdkOrderDao.findOrdersWithOutPage(sorts, searchParam);

//...

List<Long> idList = new ArrayList<>(salesOrderPage.size());
for (SalesOrderCommand cmd : salesOrderPage){
    idList.add(cmd.getId());
}

//查询订单行
List<OrderLineCommand> allLineList = sdkOrderLineDao.findOrderDetailListByOrderIds(idList);

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

List<SalesOrderCommand> salesOrderPage = sdkOrderDao.findOrdersWithOutPage(sorts, searchParam);

//...

List<Long> idList =CollectionsUtil.getPropertyValueList(salesOrderPage, "id");

//查询订单行
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有其使用场景,但是我们日常开发过程中,并没有对他做特殊的代码处理

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

public ContactCommand toContactCommand(ContactCommand command) {
	try {
		BeanUtils.copyProperties(command, this);
	} catch (Exception e){
		LOGGER.error("", e);
		//or e.printStackTrace();
	}
	return command;
}

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

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

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

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

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

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

3. 有丰富的javadoc

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

源码示例:

/**
 * 计算两个时间相差的的天数(<span style="color:red">绝对值</span>).
 * 
 * <h3>说明:</h3>
 * <blockquote>
 * <p>
 * 值=两个时间相差毫秒的绝对值/{@link TimeInterval#MILLISECOND_PER_DAY}
 * </p>
 * </blockquote>
 * 
 * <h3>示例:</h3>
 * 
 * <blockquote>
 * 
 * <pre class="code">
 * DateExtensionUtil.getIntervalDay(
 *      toDate("2008-08-24",COMMON_DATE),
 *      toDate("2008-08-27",COMMON_DATE)) = 3
 * 
 * DateExtensionUtil.getIntervalDay(
 *      toDate("2016-08-21 12:00:00",COMMON_DATE_AND_TIME),
 *      toDate("2016-08-22 11:00:00",COMMON_DATE_AND_TIME)) = 0
 * 
 * DateExtensionUtil.getIntervalDay(
 *      toDate("2016-08-21",COMMON_DATE),
 *      toDate("2016-08-22",COMMON_DATE)) = 1
 *      
 * DateExtensionUtil.getIntervalDay(
 *      toDate("2016-02-28",COMMON_DATE),
 *      toDate("2016-03-02",COMMON_DATE)) = 3
 * 
 * DateExtensionUtil.getIntervalDay(
 *      toDate("2016-08-31",COMMON_DATE),
 *      toDate("2016-09-02",COMMON_DATE)) = 2
 * 
 * </pre>
 * 
 * </blockquote>
 * 
 * @param date1
 *            date1
 * @param date2
 *            date2
 * @return 如果 <code>date1</code> 是null,抛出 {@link NullPointerException}<br>
 *         如果 <code>date2</code> 是null,抛出 {@link NullPointerException}
 * @see #getIntervalTime(Date, Date)
 * @see #getIntervalDay(long)
 * @since 1.6.0
 */
public static int getIntervalDay(Date date1,Date date2){
    return getIntervalDay(getIntervalTime(date1, date2));
}

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

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

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

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

比如 MapUtilGetSubMapTest

package com.feilong.core.util.maputiltest;

import static java.util.Collections.emptyMap;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;

import java.util.HashMap;
import java.util.Map;

import org.junit.Test;

import com.feilong.core.util.MapUtil;

public class MapUtilGetSubMapTest{

    /**
     * Test get sub map.
     */
    @Test
    public void testGetSubMap(){
        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("a", 3007);
        map.put("b", 3001);
        map.put("c", 3001);
        map.put("d", 3003);
        Map<String, Integer> subMap = MapUtil.getSubMap(map, "a", "c");
        assertThat(subMap, allOf(hasEntry("a", 3007), hasEntry("c", 3001), not(hasKey("b")), not(hasKey("d"))));
    }

    /**
     * Test get sub map 1.
     */
    @Test
    public void testGetSubMap1(){
        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("a", 3007);
        map.put("b", 3001);
        map.put("c", 3001);
        map.put("d", 3003);
        Map<String, Integer> subMap = MapUtil.getSubMap(map, "a", "c", "f");
        assertThat(subMap, allOf(hasEntry("a", 3007), hasEntry("c", 3001), not(hasKey("b")), not(hasKey("d"))));
    }

    /**
     * Test get sub map null keys.
     */
    @Test
    public void testGetSubMapNullKeys(){
        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("a", 3007);
        map.put("b", 3001);
        map.put("c", 3001);
        map.put("d", 3003);
        assertEquals(map, MapUtil.getSubMap(map, null));
    }

    /**
     * Test get sub map empty keys.
     */
    @Test
    public void testGetSubMapEmptyKeys(){
        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("a", 3007);
        map.put("b", 3001);
        map.put("c", 3001);
        map.put("d", 3003);
        assertEquals(map, MapUtil.getSubMap(map));
    }

    /**
     * Test get sub map null map.
     */
    @Test
    public void testGetSubMapNullMap(){
        assertEquals(emptyMap(), MapUtil.getSubMap(null, "a", "c"));
    }

    /**
     * Test get sub map empty map.
     */
    @Test
    public void testGetSubMapEmptyMap(){
        assertEquals(emptyMap(), MapUtil.getSubMap(new HashMap<>(), "a", "c"));
        assertEquals(emptyMap(), MapUtil.getSubMap(emptyMap(), "a", "c"));
    }
}