后端工程架构系列篇(一):单应用多模块(按业务拆分)

后端工程架构系列篇(一):单应用多模块(按业务拆分),第1张

后端工程架构系列篇(一):单应用多模块(按业务拆分)

maven多模块,按业务拆分 ,适合中小团队
  • 目录
    • 简单聊聊
    • 适用对象
    • 正式开始
    • 注意事项
    • 源代码
    • 下一篇:后端工程架构系列篇(二):微服务

,适合中小团队)

目录 简单聊聊

单体应用 VS 微服务,如何选?务必要根据公司开发人员数量和系统业务宽度来进行选择,如果你是为了简历好看或者学习,另当别论。微服务就是拆散了技术成熟的单体应用,然后又借助外部工具重新把他们粘起来,如通信、事务、部署、日志等,下一篇就会涉及,到时候我们就用阿里工具箱来演示,如dubbo、nacos、seata等。。本期介绍一个折中的选择,单应用多模块架构方式,后期想做微服务也会非常方便,无需推翻。

适用对象

绝大多数公司采用单应用多模块架构来开发足矣

  1. 中小团队(百人以内)
  2. 高内聚系统
  3. 分组分模块开发
正式开始

环境组件:以springboot2+hibernate为基础,java:11,开发工具:idea,数据库:mysql5
演示业务:创建订单(公共接口)->扣除商品库存(公共接口)->增加商品销量(私有接口),如果库存不足就进行事务回滚。订单和商品是2个模块。包含service级的基础校验@Validated

  1. 完整的项目工程结构

  2. 创建根项目
    根项目使用spring的脚手架,其他子模块就选择Maven

  1. 创建common模块
    new->module
    直接next


common模块的结构,公共接口、公共出参、公共入参等

  1. 创建web模块
    new->module
    直接next

web模块结构图,包含:控制器、过滤器、拦截器,配置文件yml,启动类等,以及权限校验、swagger文档等,类似网关的作用,
注意:web模块为启动类,在pom.xml添加以下代码,可以在根项目里复制过来,并且需要把根项目这段代码去掉


        
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    
                        
                            org.projectlombok
                            lombok
                        
                    
                
            
        
    

这是OrderController类,可以一个服务对应一个controller

package com.mmyk.scli.web.controller;

import com.mmyk.scli.common.request.CreateOrderRequest;
import com.mmyk.scli.common.service.OrderCommonService;
import com.mmyk.scli.web.vo.ResponseVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@Tag(name = "订单")
@RestController
public class OrderController {

    @Autowired
    private OrderCommonService orderCommonService;

    @Operation(summary = "创建订单")
    @PostMapping("/order.create")
    public Object prod(@RequestBody CreateOrderRequest param) {
        return ResponseVO.ok(orderCommonService.createOrder(param));
    }
}

  1. 创建service模块
    new->module
    直接next


    service模块结构图,作为所有业务模块的父模块

    service模块下: 创建商品子模块,该模块可以建立自己的yml
    注意Parent,选择service模块


该实现有2个接口,一个为common模块下公共接口,一个为本模块内的接口,第二个只供本模块内部使用。

这是订单子模块的 orderServiceImpl,创建订单

package com.mmyk.slic.service.order.service.impl;

import com.mmyk.scli.common.request.CreateOrderRequest;
import com.mmyk.scli.common.request.DeductStockRequest;
import com.mmyk.scli.common.response.CreateOrderResponse;
import com.mmyk.scli.common.response.DeductStockResponse;
import com.mmyk.scli.common.service.OrderCommonService;
import com.mmyk.scli.common.service.ProductCommonService;
import com.mmyk.slic.service.order.dao.OrderDao;
import com.mmyk.slic.service.order.entiy.Order;
import com.mmyk.slic.service.order.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

@Slf4j
@Validated
@Service
public class OrderServiceImpl implements OrderCommonService, OrderService {
    @Autowired
    private OrderDao orderDao;

    @Autowired
    private ProductCommonService productCommonService;

    @Transactional
    @Override
    public CreateOrderResponse createOrder(CreateOrderRequest request) {
        log.info("OrderServiceImpl.createOrder() ok");
        Long count = orderDao.count();
        log.info("当前order表总行数:{}", count);

        Order order = new Order();
        order.setOrderNumber("100001");
        order.setProductId(request.getProductId());
        order = orderDao.save(order);
        CreateOrderResponse createOrderResponse = new CreateOrderResponse();
        createOrderResponse.setOrderId(order.getOrderId());

        DeductStockRequest deductStockRequest = new DeductStockRequest();
        deductStockRequest.setProductId(request.getProductId());
        deductStockRequest.setQuantity(request.getQuantity());
        DeductStockResponse deductStockResponse = productCommonService.deductStock(deductStockRequest);

        return createOrderResponse;
    }
}

注意事项
  1. 业务模块之间是单向依赖,不能相互依赖。类似spring要求service不能相互引用。
  2. 启动类要加上各类bean的扫描
  3. A子模块调用B子模块,需要A在本模块的pom.xml内再引入B,后期如果微服务化,如基于rpc调用就无需引入,只用在service模块引入common模块即可
  4. web模块pom.xml增加启动类配置,去掉根项目pom.xml启动配置
源代码

gitee

下一篇:后端工程架构系列篇(二):微服务

基于阿里工具箱,dubbo、nacos、seata,全部为当前最新版本来演示

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/zaji/5692355.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-17
下一篇2022-12-17

发表评论

登录后才能评论

评论列表(0条)

    保存