Java应用工程结构

java

Java应用工程结构

Posted on

2022-04-12 16:37 

CN.programmer.Luxh 

阅读(0) 

评论(0) 

编辑 

收藏 

举报

分层的本质是关注点分离,隔离对下层的变化,可以简化复杂性,使得层次结构更加清晰。

1. 主流分层结构介绍

目前业界存在两种主流的应用工程结构:一种是阿里推出的《Java开发手册》中推荐的,另外一种是基于DDD(领域驱动设计)推荐的。

1.1 基于阿里《Java开发手册》的分层结构

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

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

动端展示等。

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

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

• Manager 层:通用业务处理层,它有如下特征:

1) 对第三方平台封装的层,预处理返回结果及转化异常信息,适配上层接口。

2) 对 Service 层通用能力的下沉,如缓存方案、中间件通用处理。 3) 与 DAO 层交互,对多个 DAO 的组合复用。

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

• 第三方服务:包括其它部门 RPC 服务接口,基础平台,其它公司的 HTTP 接口,如淘宝开放平台、支

付宝付款服务、高德地图服务等。

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

1.2 基于DDD(领域驱动设计)的分层结构

• 领域层:体现业务逻辑。

• 应用层:依赖领域层,根据业务对下层领域进行聚合和编排。

• 基础设施层:为其他提供技术支持。

• 用户接口层:为外部用户访问底层系统提供交互界面和数据表示。

2. 自己的工程结构

基于上述两种工程结构,设计一个适合自己的Java项目分层结构。

example

└─src

├─main

│ ├─java

│ │ └─com

│ │ └─example

│ │ ├─application --应用层(聚合多个领域)

│ │ ├─domain --领域层

│ │ │ ├─order --订单域

│ │ │ │ ├─bo --业务对象

│ │ │ │ ├─constant --领域内局部常量

│ │ │ │ ├─controller --控制器

│ │ │ │ ├─dto --数据传输对象

│ │ │ │ ├─event --事件

│ │ │ │ │ ├─publish --发布

│ │ │ │ │ └─subscribe --订阅

│ │ │ │ ├─manager --通用逻辑处理

│ │ │ │ ├─repository --存储

│ │ │ │ │ ├─entity --实体,对应数据库中的字段

│ │ │ │ │ └─mapper --mybatis mapper

│ │ │ │ └─service --业务层处理

│ │ │ │ └─impl --业务接口实现

│ │ │ └─user --用户域

│ │ │ ├─bo

│ │ │ ├─constant

│ │ │ ├─controller

│ │ │ ├─dto

│ │ │ ├─event

│ │ │ │ ├─publish

│ │ │ │ └─subscribe

│ │ │ ├─manager

│ │ │ ├─repository

│ │ │ │ ├─entity

│ │ │ │ └─mapper

│ │ │ └─service

│ │ │ └─impl

│ │ └─infrastructure --基础设施层

│ │ ├─config --配置

│ │ ├─constant --全局常量

│ │ ├─handler --处理器

│ │ ├─interceptor --拦截器

│ │ ├─thirdparty --第三方

│ │ └─utils --工具类

│ └─resources

│ ├─mapper

│ │ ├─order

│ │ └─user

└─test

└─java

└─com

└─example

  • 接收参数和响应报文,请求以Req为后缀,响应以Resp为后缀,代码写在dto包中,比如创建订单请求和响应

/**

* 创建订单请求

*/

@Data

public class OrderCreateReq {

/**

* 用户id

*/

private String userId;

/**

* 订单金额

*/

private BigDecimal amount;

/**

* 下单的商品集合

*/

private List<OrderDetailReq> orderDetailReqList;

@Data

public static class OrderDetailReq {

/**

* 商品id

*/

private Long goodsId;

/**

* 商品数量

*/

private Integer goodsNum;

}

}

/**

* 创建订单响应

*/

@Data

public class OrderCreateResp {

/**

* 订单id

*/

private String orderId;

}

  • DAO层代码放在repository中

  • 业务层代码放在service和manager中,比如创建订单因为涉及到订单表和订单明细表,需要在一个事务中,所以将事务代码下沉到manager。

@Service

public class OrderServiceImpl implements OrderService {

@Resource

private OrderManager orderManager;

@Override

public OrderCreateResp create(OrderCreateReq req) {

Order order = buildOrder(req);

List<OrderDetail> orderDetailList = buildOrderDetailList(order.getOrderId(), req);

orderManager.createOrder(order, orderDetailList);

OrderCreateResp resp = new OrderCreateResp();

resp.setOrderId(order.getOrderId());

return resp;

}

private Order buildOrder(OrderCreateReq req) {

Order order = new Order();

order.setOrderId(UUID.randomUUID().toString());

order.setUserId(req.getUserId());

order.setAmount(req.getAmount());

return order;

}

private List<OrderDetail> buildOrderDetailList(String orderId, OrderCreateReq req) {

List<OrderDetail> orderDetailList = new ArrayList<>();

for (OrderCreateReq.OrderDetailReq orderDetailReq : req.getOrderDetailReqList()) {

OrderDetail orderDetail = new OrderDetail();

orderDetail.setOrderId(orderId);

orderDetail.setGoodsId(orderDetailReq.getGoodsId());

orderDetail.setGoodsNum(orderDetailReq.getGoodsNum());

orderDetailList.add(orderDetail);

}

return orderDetailList;

}

}

@Component

public class OrderManager {

@Resource

private OrderMapper orderMapper;

@Resource

private OrderDetailMapper orderDetailMapper;

@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)

public void createOrder(Order order, List<OrderDetail> orderDetailList) {

orderMapper.insert(order);

for (OrderDetail orderDetail : orderDetailList) {

orderDetailMapper.insert(orderDetail);

}

}

}

  • 业务对象存放在bo包中,比如查询用户信息,不需要返回密码字段,则可以定义一个UserBO。

@Data

public class UserBO {

private String userId;

private String username;

private String nickname;

}

  • application层做聚合编排,比如下单,既要保存订单信息,又要扣减库存,就需要对订单域和库存域进行聚合编排。

以上是 Java应用工程结构 的全部内容, 来源链接: utcz.com/z/395088.html

回到顶部