接口定义
统一接口返回类型
- 统一的数据格式,如ResultBean
工作中接口定义出现返回类型是map,json,object,都是不应该的。 map,json虽然格式灵活,但可读性差。
接口应返回统一的数据格式:如基础框架统一封装ResultBean/PageResultBean格式。
ResultBean/PageResultBean是controller专用的,不允许往后传!
- 统一数据格式的目的
- 统一格式
- 便于应用AOP
- 便于包装异常信息
接口入参
- 定义业务bean,封装入参
不允许出现例如json字符串入参
- 入参不要出现与业务无关的实体,如User
接口出参
- 考虑接口失败的场景,合理给出返回参数便于定位
- 如更新数据操作返回主键id
- 新增数据操作返回新对象主键id
//不返回任何数据,没有考虑失败场景,容易返工
@PostMapping("/update")
public void update(long id, xxx) {
}
工具类封装
定义自己的工具类库
基础框架搭建时应定义自己的工具类,尽量不要在业务代码里面直接调用第三方的工具类。如spring提供的BeanUtils与apache-commons-lang提供的该类源和目标入参相反。如果直接调用三方工具类,不便于以后统一修改。
使用父类/接口作为入参
举例,假设我们写了一个判断arraylist是否为空的函数,一开始是这样的。
public static boolean isEmpty(ArrayList<?> list) {
return list == null || list.size() == 0;
}
这个时候,我们需要思考一下参数的类型能不能使用父类。我们看到我们只用了size方法,我们可以知道size方法再list接口上有,于是我们修改成这样。
public static boolean isEmpty(List<?> list) {
return list == null || list.size() == 0;
}
后面发现,size方法再list的父类/接口Collection上也有,那么我们可以修改为最终这样。
public static boolean isEmpty(Collection<?> list) {
return list == null || list.size() == 0;
}
总结一下,思路是抽象的思想,主要是修改参数类型,方法就是往上找父类/接口,一直找到顶为止,记得修改参数名。
使用重载编写衍生函数组
如封装一个读文件的方法,支持多种字符集编码
异常处理
- 基础框架统一定义业务异常类,异常继承RuntimeException。
- 不允许吃掉异常,不合理的异常捕获。(异常上对开发人员就这点要求!异常都抛出到controller上用AOP处理)
- 后台(如队列等)异常一定要有通知机制,要第一时间知道异常。
- 少加空判断,加了空判断就要测试为空的场景!
日志打印
日志打印二要素
日志的最少有以下2点要求:
详细代码可参考文章
- 能找到哪个机器
定位服务器–通过修改nginx配置
- 能找到用户做了什么
定位操作用户-可在filter中将用户信息封装到log4j的MDC(Mapped Diagnostic Context)类中
什么地方应该打日志?
- 修改/新增操作必须打印日志
大部分问题都是修改导致的。数据修改必须有据可查。
- 条件分支必须打印条件值,重要参数必须打印
尤其是分支条件的参数,打印后就不用分析和猜测走那个分支了,很重要!
- 数据量大的时候需要打印数据量
前后打印日志和最后的数据量,主要用于分析性能,能从日志中知道查询了多少数据用了多久。这点是建议。自己视情况而决定是否打印,我一般建议打印。
- 参数非法的时候,把值打印出来
- controller里不建议打日志,日志在AOP里面会打印,而且建议是大部分日志在Services这层打印。
如何检测日志打印是否合理?
不要依赖debug,多依赖日志。代码开发测试完成之后不要急着提交,先跑一遍看看日志是否看得懂。