JAVA项目设计(一):程序结构设计

  1. 从单体项目开始说起
  2. 领域模型规约
  3. 项目结构
    1. 包路径设计
    2. 包结构设计
    3. 静态资源和配置文件
    4. 从单体走向微服务架构
    5. x-common 核心子项目设计
      1. common

从单体项目开始说起

在阿里规范下的应用分层:根据业务架构实践,结合业界分层规范与流行技术框架分析,推荐分层结构如图所示,
默认上层依赖于下层,箭头关系表示可直接依赖,如:开放 API 层可以依赖于 Web 层 (Controller 层),也可以直接依赖于 Service 层,依此类推

开放 API 层:可直接封装 Service 接口暴露成 RPC 接口;通过 Web 封装成 http 接口;网关控制层等。

终端显示层:各个端的模板渲染并执行显示的层。当前主要是 velocity 渲染,JS 渲染,JSP 渲染,移
动端展示等。

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

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

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

DAO 层:数据访问层,与底层 MySQL、Oracle、Hbase、OB 等进行数据交互。

第三方服务:包括其它部门 RPC 服务接口,基础平台,其它公司的 HTTP 接口,如淘宝开放平台、支
付宝付款服务、高德地图服务等。

外部数据接口:外部(应用)数据存储服务提供的接口,多见于数据迁移场景中。


补充下:biz 层

biz 是 Business 的缩写,是业务逻辑层。项目前期或者小项目中,和 service 没什么太大区别,但是项目大了以后区别就很大了:service 是比较底层的 api,biz 是应用层的 api。下文微服务架构下也会提到 biz 层,不过和这里的 biz 理念上稍微有点不同,本章节中单体架构下 biz 层已经没有研究的价值了,搞不清楚也不用细究

领域模型规约

POJO:简单的Java对象(Plain ordinary Java Objects)实际就是普通JavaBeans,使用POJO名称是为了避免和EJB混淆起来, 而且简称比较直接。

DO(Data Object):与数据库表结构一一对应,通过DAO层向上传输数据源对象。

PO(persistant object):持久对象,搞不清楚,就理解成DO吧。

DTO(Data Transfer Object):数据传输对象,Service或Manager向外传输的对象。

BO(Business Object):业务对象。由Service层输出的封装业务逻辑的对象。

AO(Application Object):应用对象。在Web层与Service层之间抽象的复用对象模型,极为贴近展示层,复用度不高。

VO(View Object):显示层对象,通常是Web向模板渲染引擎层传输的对象。

Query:数据查询对象,各层接收上层的查询请求。注意超过2个参数的查询封装,禁止使用Map类来传输。


实际项目开发时,我觉得没有必要刻意照搬这么多层对象,对象转换工作能烦死人

我目前用的:DO(就是 entity)DTOQueryVO

项目结构

下文以 Spring Boot 典型项目结构为例,新建项目后:

  • src/main/java:放置项目Java源代码
  • src/main/resources:放置项目静态资源和配置文件
  • src/test/java:放置项目测试用例代码

包路径设计

一般的工程中包的组织方式为 {com.公司名.组织架构.业务},比如:com.aliyun.oss.user

包结构设计

|_config:放置一些配置类(web配置、springboot启动配置、yml\properties)相关的代码
|_filter:放置一些过滤器相关的代码
|_interceptor:放置一些拦截器相关的代码
|_controller:放置控制器代码
|_service:放置具体的业务逻辑代码(接口和实现分离)
   |__impl:存放业务逻辑实际实现
|_manager:放置具体的业务逻辑代码(接口和实现分离)
   |__impl:存放业务逻辑实际实现
|_dao/mapper:放置数据访问层代码接口
|_model:放置数据模型代码
   |__entity:放置数据库实体对象定义
   |__dto:存放数据传输对象定义
   |__vo:存放显示层对象定义,避免暴露数据库结构
   |__query:存放各层的查询入参对象定义
|_wrapper:放置VO、DO、DTO 之间的转换器
|_exception:放置异常类、全局异常处理类
|_constant:放置常量定义
|_enum:放置枚举定义
|_annotation:放置项目自定义注解
|_aspect:放置切面代码
|_utils:放置工具类和辅助代码
问: 1、缓存实现类放哪里?

静态资源和配置文件

|_mapper:存放mybatis的XML映射文件(如果是mybatis项目)
|_static:存放网页静态资源,比如下面的js/css/img
   |__js:
   |__css:
   |__img:
   |__font:
|_template:存放网页模板,比如freemarker等
   |__header
   |__sidebar
   |__bottom
   |__XXX.html
|_application.yml       基本配置文件
|_application-dev.yml   开发环境配置文件
|_application-test.yml  测试环境配置文件
|_application-prod.yml  生产环境配置文件

从单体走向微服务架构

微服务强调的是服务的分治,需要对系统功能进行梳理和拆分,原先独立的项目会被拆分成独立的子项目,拆分方案示例如下:

|_x
    |__x-common
    |__x-user-front 前台用户体系,参考后台用户体系
    |__x-user-admin 后台用户体系,涉及到用户、角色、菜单、接口权限等等
        |__x-user-admin-common
        |__x-user-admin-dao
        |__x-user-admin-service
        |__x-user-admin-rpc-lib
        |__x-user-admin-rpc
    |__x-pay 支付业务板块
        |__x-pay-common 依照业务情况可能会抽取枚举、常量、DTO等
        |__x-pay-dao
        |__x-pay-service
        |__x-pay-rpc-lib 支付微服务接入包(区分admin\front)
        |__x-pay-rpc 支付微服务提供者
        |__x-pay-job 消息队列、任务调度
    |__x-biz 应用服务层(也叫应用聚合层,组合微服务)
        |__x-biz-pay-common
        |__x-biz-pay
    |__x-gateway 对接应用服务层
    |__x-log 系统日志
        |__x-log-common
        |__x-log-dao
        |__x-log-admin 日志后台接口
        |__x-log-consumer 日志消费入库、分析端,提升成事件库
        |__x-log-provider 日志接入工具包
    |__x-ops 运维中心
        |__x-develop 代码生成
        |__x-nacos 微服务注册\配置中心
        |__x-sentinel 限流服务
        |__x-monitor 监控
        |__x-oss 存储管理
    |__x-demo
        |__x-demo-mybatis
        |__x-demo-oss
        |__x-demo-rpc-lib
        |__x-demo-rpc-service

备注:

(1)为体现服务分治思路,彼此之间做成树形层级结构,如 x-demo 文件夹下存在 x-demo-mybatis 文件夹

(2)为方便源代码管理,以上每个项目均独立托管代码仓库管理,彼此之间同样为平级关系

(3)服务拆分要适度,不要为了拆分而拆分,过度拆分容易造成高内聚业务无法开展,如用户-角色-菜单模块开发,通常需要sql连表搞定需求,建议把用户-角色-菜单等系统相关板块都做到用户服务中

(4)通常来说,软件系统都有管理员后台管理端和普通用户门户端,我这里统一规定团队内部黑话:admin代表管理员后台管理端,front代表普通用户门户端

(5)admin和front从lib层开始独立编写,不要把dao都隔离开,工作量太大了,架构时在开发工作量和解耦度之间要有取舍

(6)耦合方案:x-pay模块中存储了userId(支付者的id),若是账单列表页面中需要呈现account(支付者的账户),编写思路应该是在x-biz-pay中调用pay服务 -> 从数组中提取userId数组 -> 调用user服务获取对应的user数组 -> 提取user.account形成PayVO返回出去

补充下:上面提到了 x-biz,biz 是 Business 的缩写,这是微服务架构下的应用聚合层(领域驱动设计中的应用服务层,可以结合 DDD领域驱动设计中的应用服务层理解),就是一个舞台,拉几个微服务过来表演。这样一来,biz层不存在自己的dao也是非常合理的

x-common 核心子项目设计

同样以阿里云OSS团队为例,com.aliyun.oss.common

common

核心类
com.aliyun.oss.common.enumeration ErrorCodeEnum、IErrorCode
com.aliyun.oss.common.exception BaseException、DaoException、GlobalExceptionHandler、ManagerException、ServiceException、ValidateException
com.aliyun.oss.common.model.dto.result ObjectResult、TableResult
com.aliyun.oss.common.base BaseConstants、BaseController、BaseEntity、BaseService、BaseServiceImpl、BaseServiceMockImpl、BaseResult
com.aliyun.oss.common.util PageBeanUtil、SpringUtil
com.aliyun.oss.common.util.tree TreeNode、TreeUtil
com.aliyun.oss.common.util.serializer LocalDateTimestampSerializer
com.aliyun.oss.common.validator LengthValidator、NotNullValidator、SizeValidator

转载请注明来源。 欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。 可以在下面评论区评论,也可以邮件至 sharlot2050@foxmail.com。

文章标题:JAVA项目设计(一):程序结构设计

字数:2.2k

本文作者:夏来风

发布时间:2021-04-19, 00:28:36

原始链接:http://www.demo1024.com/blog/java-project-design-01/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。