读阿里巴巴Java开发手册v1.2.0之工程结构有感【架构篇】

时间:2023-11-11 22:50:32

首先,把昨天那俩条sql语句的优化原因给大家补充一下,第一条效率极低,第二条优化后的,sql语句截图如下:

读阿里巴巴Java开发手册v1.2.0之工程结构有感【架构篇】

经过几个高手的评论和个人的分析:

  第一条sql语句查询很慢是因为它首先使用了in关键字查询,导致全表扫描,其次我那条sql语句的写法上,是通过子查询根据某一个字段去不断匹配后面查询到的集合数据,最后得到查询结果,这一系列操作下来效率上去才怪呢。

  但是第二条sql语句是通过连接查询,根据建立了索引的字段来等值匹配,最后得到查询结果,速度杠杠的。(一次小小的优化经历,学到了)。

  今天(2017-05-24)在微信公众号上终于等到阿里巴巴集团开源的Java开发手册更新了,从地铁上一路看到公司,真的学到了,人家的开发规约真的是好,讲的很细,很注重细节,这就是差距啊,下面给大家简单总结一下吧(手册原件如果需要,请留言)。

  它的名字是《阿里巴巴Java开发手册v1.2.0》,距2017-02-09发布的第一版已经有6个历史了,它的总体结构分为五大部分:编程规约、异常日志、MySQL数据库、工程结构和安全规约。今天我主要给大家分享总结了工程结构,因为我五一前刚给公司开发了一套内网数据录入系统,虽然没用到什么大的框架和潮流的技术,但是麻雀虽小五脏俱全啊。包括表结构、工程搭建和业务梳理都是自己一个人在开发,当时在开发的时候也是感觉很孤独,因为项目组的其他人都有战友配合作战,而我就一个人,还有页面的调试和美化都是我一个人在搞,在此声明一下,我不是在抱怨,反而很珍惜这种开发机会,真的会沉淀很多东西,谢谢公司。

  切入正题吧,今天给大家分享的是工程结构这块的一些个人总结。

1、项目应用分层:

这里主要给我们讲述了一下,一个项目理想化的项目架构图,和我们平时开发的项目结构稍稍不同,毕竟人家的架构思维那是相当的高啊,这还是最基础的架构图呢。

读阿里巴巴Java开发手册v1.2.0之工程结构有感【架构篇】

上图默认上层依赖于下层,箭头关系表示直接依赖。

  开放接口层:可直接封装service层接口中的方法暴露成RPC接口/服务,通过web封装成http接口,最后进行网管控制、流量控制等。

  终端显示层:各个端的模板渲染并执行显示的层。当前我们主要接触的是js渲染、jsp渲染和移动端渲染等。

  web层:主要是对访问控制进行转发,各类基本参数校验,或者不复用的业务简单处理等。

  service层:相对具体的业务逻辑服务层。

  manager层:通用业务处理层,它有如下特征:1、对第三方平台封装的层,预处理返回结果及转化异常信息;2、对service层通用能力的下沉,比如缓存方案、中间件通用处理、3、与dao层交互,对多个dao的组合复用。

  dao层:数据访问层,与底层MySQL、Oracle、hbase数据库进行数据交互。

  外部接口或第三方平台:包括其他部门的rpc接口,基础平台,其他公司的http接口。

  以上都是阿里项目的工程架构,有一点不同的是我们平时通用的是controller层、service服务层和dao数据访问层,但是他们这里提出了manager层,将一些业务通用的处理方式和需要多个dao组合复用的结果抽取到该层,个人感觉在项目维护上很方便,以前我们都是按模块划分,将各个模块的业务逻辑都往service层堆上去,这样其实也没什么不好,但是我们感觉试着将业务层通用的业务抽取一下,刚才还琢磨着把我前俩天写的项目重构一下,最后还是等到端午吧,也好好模仿一把阿里,哈哈哈。

2、项目异常分层处理规约:

  因为dao数据访问层产生的异常很多,类型也很多,无法用细粒度的异常进行处理,所以直接将异常丢给service层,为啥要将数据访问层的异常丢到manager/service层,因为通常在manager/service层中会有日志打印,不管是发生异常还是异常抛出,都会时刻记录运行情况到日志文件中去,要是刚才在dao层也将异常打印,又因为dao和service是同台服务器,这样就相当于打印了2次日志,浪费性能和储存。

  service产生的异常必须记录到磁盘日志文件中去,尽可能带上参数信息,相当于保护案发现场。

  web层大哥们,不能在爽啦,必须处理了,如果产生的异常会导致页面的正常渲染,则采用拦截器或异常处理的方式,跳转到异常错误友好页面,加上友好的错误提示信息,最后还要在开发接口层将产生的异常处理成错误码和错误信息返回。

3、分层领域模型规约:

  我们以前的项目中我见过有3类模型类,第一类是web层与视图层传递参数的query类,第二类是与数据表对应的pojo类,第三类是为了响应数据定义的扩展vo类。

  下面我们来看看阿里是如何将模型进行规约的,我感觉非常啰嗦但是非常好,其实很多电商公司也估计是这么做的,我之前接触的一个电商项目大概就是这种设计,好长时间了记不清了:

  DO(data object):与数据库中的数据表一一对应,通常是应用于数据访问层dao中用于向上传输数据源对象。

  DTO(data transfer object):数据传输对象,该模型类主要是应用于service层和manager层,将service层和manager层业务处理后进行向外传输对象。

  BO(business object):业务对象,主要是service层输出的封装的业务逻辑的对象。

  Query:数据查询对象,各层接受上层传递过来的多个参数并将这些参数封装到query对象中。

  VO(view object):视图层对象,主要是web层向视图层传输的数据对象。

4、二方库依赖:

  定义GAV遵从一下规则:

  (1)、GroupID格式:com.{公司/BU}.业务线.[子业务线],最多四级。

  (2)、ArtifactID格式:产品线名-模块名。注意:语意不重复不遗漏,最好到*仓库中去查证一下。

  (3)、Version格式:版本号根据自己公司的规定。

最后给大家送上几条建议,也是在手册中看到的,只不过写到这儿印象比较深刻,还没忘就给大家写在这儿吧:

一:数据订正时,在调用修改和删除方法之前,最好先查询要修改或删除的记录是否存在,确认无误后再进行更新。

二:在查询数据时能避免使用IN关键字就避免,是在避免不了,则需要仔细评估IN后边的数据集合中总数是否超过1000,最好控制在1000以内,我上次的优化经历起源于它,就是匹配的集合数据远远超过1000条,最后导致查询效率极低。

三:sql.xml文件中配置参数尽量使用#{},尽量不要使用${},容易造成sql注入问题。

四:接口过时必须加@Deprecated注释,并且添加注释清晰地说明替代旧接口的新接口或服务。

五:一般不要在pojo类中定义属性的变量时,建议不要加is前缀,但是在数据表中定义属性对应的字段是尽量加上is_前缀,原因是:如果在给属性的变量名加上is前缀极可能会发生,部分框架解析时会引起序列化错误。

六:在定义项目中的包结构时,统一使用小写并单数形式。

七:service层和mapper接口中定义的方法,建议不要写修饰符,目的就是代码结构看着简单,阿里给出的解释,所以我就把我以前的都删掉了,好习惯就应该从现在开始。

八:如果项目中要实现分页逻辑,如果在判断总记录数为0时,则直接返回,避免执行后面的分页语句,给大家送张截图,是我前几天自己写的分页逻辑:

   @Override
public List<Task> findOrdersByUserId(Task task,Page page) {
int count = vinTaskMapper.countOrdersByUserId(task);
page.setMaxRow(count);
if(count == 0){
return new ArrayList<Task>();
}
return vinTaskMapper.findOrdersByUserId(task,page);
}

九:禁止使用存储过程,因为难以调试和扩展,更没有移植性。

好了,就总结到这儿吧,这里虽然没什么干货和技术要点,但是我的目的是给大家分享一点编程习惯,具备好的代码风格是作为一个优秀程序员的基本素能,最后希望大家写出来的代码能够越看越美,越看越想看,哈哈哈。