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 | 注解 | gmkt@InterfaceDoc | SOA认证之服务API 接口注解 加了格式化 | |
gmkt@MethodDoc | SOA认证之服务API 方法注解 加了格式化,且省去一个个手写方法参数 | |||
gmkt@Lombok | 使用Lombok @Data @ToString | |||
gmkt@Service | 使用@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(也可以不建立,可以放到系统自带的那些快捷模板一起):
- 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】,可参考官网文档:
登高而招,臂非加长也,而见者远;
顺风而呼,声非加疾也,而闻者彰。
假舆马者,非利足也,而致千里;
假舟楫者,非能水也,而绝江河。
君子生非异也,善假于物也。
微信扫一扫下面的二维码,关注公众号:梦语路