IDEA的Live Templates代码模板

IDEA的Live Templates代码模板

一、简介

本着“复杂的事情简单化,简单的事情标准化”的做事基本指导原则,我们发现日常编码中,有大量的代码可以提炼出模板进而简单化/自动化。

  • 1.可以大大提高编码效率;
  • 2.统一了通用代码风格;

如果我们想做流程或者自动化,没有一个统一标准的话,我们要考虑的点就会很多:

“标准”打磨形成“规范”,“规范”梳理成“流程”,“流程”推演到“自动化”

将下面文件放到templates文件夹下,便可直接使用(省去大家配置时间)——任何代码处输入gmkt会有自动提示。

在Idea安装配置目录(比如:/Users/ares/Library/Preferences/IntelliJIdea2017.2/templates,无templates文件夹的,创建一个便可。不同系统具体请参考)。

上面MyGroup.xml中,如支持如下功能:

编号 板块 使用输入 功能作用 备注
1 日志相关 gmktLog 日志变量申明
gmktLogInfo 打印方法入参
gmktLogRR 打印任何方法调用的入参和返回值(通常用于RPC服务调用) 使用时需要选中或鼠标放在当前代码上,然后执行快捷键如:command+alt+t
2 异常处理 gmktTryCatch try...catch中加入日志打印和Cat.logEvent() 使用时先选中当前需要try...catch的代码,然后执行快捷键如:command+alt+t
gmktTransaction try...catch过程中引入CAT的Transaction
3 枚举类 gmktEnum 生成isValidEnum()和getXXXEnumByCode()方法 使用ImmutableMap;默认枚举类有int类型的code属性
gmktEnum2 生成getXXXEnumByCode()方法 默认枚举类有int类型的code属性
4 集合判断和处理 gmktEmpty 生成if ( CollectionUtils.isEmpty() ) {}
gmktNotEmpty 生成if ( CollectionUtils.isNotEmpty() ) {}
gmktTransform Map迭代
gmktContainsAny 使用CollectionUtils.containsAny(a,b)判断是否有交集
gmktIntersection 使用CollectionUtils.intersection(a,b)求交集
5 注解 [email protected] SOA认证之服务API 接口注解 加了格式化
[email protected] SOA认证之服务API 方法注解 加了格式化,且省去一个个手写方法参数
[email protected] 使用Lombok @Data @ToString
[email protected] 使用@Service @Slf4j 实现类注解
6 异步/并发调用 gmktCallableFuture 快速使一个方法调用变为异步调用(Callable和Future) 默认已申明了线程池executorService变量

说明:

  • 1.快捷方式和模板,可按自己习惯修改(不过,组内最好统一)
  • 2.大家平时发现、提炼出来让其更丰富
  • 3.上面xml更新时间为2018-09-28

二、适用场景示例

开发中,需要打印日志的地方很多,手写这些代码——低效、枯燥无味,但通常又不可不写,因此需要借助工具提高生产力~

  • 1.统一日志变量声明——必写;
  • 2.打印方法入参——通常也是必写(除非使用统一注解方式);
  • 3.调用RPC服务(或是任何一个方法的调用),打印输入输出——通常为了方便排错,这里也必写;
  • 4.异常处理时,记录日志并cat埋点 ;

如下代码中1~4,这是日常开发中,敲写最频繁最多的,天天手敲这些是不是很无趣。归纳总结后,我们可以抽象出代码模板,借助IDEA的【Live Templates】支持,每次编码过程中,只要输入快捷键, 便可帮助我们自动快捷生成相关代码。

@Component
public class ShopComponent {

    /** 1.日志变量声明——必写 */
    private static final Logger LOGGER = LoggerFactory.getLogger(ShopComponent.class);

    @Autowired
    private UserAuthoriseRPCService rpcService;

    public PageModel queryShopByPage(int shopAccountId, int pageNo, int pageSize){
        /** 2.打印方法入参——通常也是必写(除非使用注解方式)*/
        LOGGER.info("queryShopByPage()->shopAccountId = {}, pageNo = {}, pageSize = {}", shopAccountId, pageNo, pageSize);

        try {
             /** 3.调用RPC服务,打印输入输出——通常为了方便排错,这里也必写 */
            LOGGER.info(" rpcService.queryPagedShopIdsByShopAccountId(shopAccountId, pageNo, pageSize)->Req:");
            OperateResult<PageModel> result = rpcService.queryPagedShopIdsByShopAccountId(shopAccountId, pageNo, pageSize);
            LOGGER.info(" rpcService.queryPagedShopIdsByShopAccountId(shopAccountId, pageNo, pageSize)->Res: result = {}" , result);

            if (result == null || result.getCode() != OperateResult.CODE_SUCCESS || result.getData() == null) {
                return new PageModel();
            }
            return result.getData();
        }catch (Exception e){
            /** 4.异常处理,日志记录,cat埋点 */
            LOGGER.error("queryShopByPage()->exception:", e);
            Cat.logEvent(CAT_Event_Type, "ShopCategoryInfoQuery", "fail");
        }
        return new PageModel();
    }
}

三、自定义模板方法

  • 1.自定义模板,主要如下截图,首先创建一个自己管理组MyGroup(也可以不建立,可以放到系统自带的那些快捷模板一起):
    IDEA的Live Templates代码模板
  • 2.日志模板相关配置整理如下(编写代码过程中输入gmkt,便会有自动提示,回车便会自动生成相应代码块),如:
1.作用:
    日志变量声明
2.Abbreviations示例:
    gmktLog
2.Template text示例:
    gmktLog|private static final Logger LOGGER = LoggerFactory.getLogger($CLASS$.class);
3.Edit Variable示例:
    CLASS = className()
1.作用:
    打印方法入参
2.Abbreviations示例:
    gmktLogInfo
2.Template text示例:
   LOGGER.info("$METHOD_NAME$()->$FORMAT$);
3.Edit Variable示例:
   METHOD_NAME = methodName()
   METHOD_NAME = methodName()<p>FORMAT = groovyScript(" _1.collect { it + ' = {}'}.join(', ') + '\",' + _1.collect {it}.join(', ') ", methodParameters())
1.作用:
    调用方法,打印输入输出
2.Abbreviations示例:
    gmktLogRR
2.Template text示例:
  LOGGER.info("$A$->Req:");
  $SELECTION$
  LOGGER.info("$A$->Res: $EXPR_COPY$ = {}" , $EXPR$);
3.Edit Variable示例:
  A = groovyScript("def result=''; def params=\"${_1}\".replaceAll(';', '').split('=').toList(); result=params[1]; return result", SELECTION)
  EXPR = variableOfType("")
  EXPR_COPY = escapeString(EXPR)

四、举一反三

遵守统一的规范,那么:

  • 1.如果接口输出有约定,那么如下一样不需要每次手敲代码:
if (result == null || result.getCode() != OperateResult.CODE_SUCCESS || result.getData() == null) {
    return new PageModel();
}
  • 2.如果DTO–>Entity有约定,下面代码一样不用每次手写get、set(下面的代码是最常见的,经常我们调用外部服务,然后把结果转换为自己的对象,但通常属性都一样或者有点点区别而已):
public class XXXConvert {
     public static CouponListRequest item2ListRequest(CouponItemRequest itemRequest){
        CouponListRequest listRequest = new CouponListRequest();
       
        listRequest.setBusinessId(itemRequest.getBusinessId());//get  set
        listRequest.setCityId(itemRequest.getCityId());//get  set
        listRequest.setAppPlatform(AppPlatformEnum.MT.code);//get  set
        listRequest.setDevicePlatform(itemRequest.getPlatform());//get  set
        listRequest.setFromApp(true);
        listRequest.setUserId(itemRequest.getUserId());//get  set
        listRequest.setLat(itemRequest.getLat());//get  set
        listRequest.setLng(itemRequest.getLng());//get  set
        listRequest.setPageNo(itemRequest.getOffset());//get  set
        listRequest.setPageSize(itemRequest.getLimit());//get  set
        listRequest.setUuid(itemRequest.getUuid());//get  set

        return listRequest;
    }
}
  • 3.应该还有很多…
  • 4.我们可以形成自己的IDEA插件

五、收益

  • 1.可以大大提高编码效率;
  • 2.统一了通用代码风格;

六、参考

有关IDEA的【Live Templates】,可参考官网文档:

登高而招,臂非加长也,而见者远;
顺风而呼,声非加疾也,而闻者彰。
假舆马者,非利足也,而致千里;
假舟楫者,非能水也,而绝江河。
君子生非异也,善假于物也。