IDEA2022搭建Spring Cloud多模块项目

这篇具有很好参考价值的文章主要介绍了IDEA2022搭建Spring Cloud多模块项目。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Springboot多模块项目搭建

创建maven父工程

注意:创建父模块选用Spring Initializr的方式创建,让父模块继承springboot的maven配置,之后的所有子模块都通过maven的方式创建,子模块继承父模块就会间接继承springboot相关的配置,web,api模块再另外添加spring-boot-starter-web,spring-boot-starter-tomcat相关的依赖。网上有很多教程父模块都是通过maven的方式创建的,然后子模块是通过Spring Initalizr方式创建,这种方式父模块无法管理子模块的依赖仲裁,需要每个子模块自行管理,就失去了父模块的用处了。

  1. idea -> file -> new -> project,选择Spring Initializr,填写相关的Group,Artifact,Package name 等信息,点击Next;
    JDK版本可以根据需要选择高一些的版本,我是由于需要兼容线上的老版本系统,所以沿用JDK1.8的版本
    IDEA2022搭建Spring Cloud多模块项目

  2. 根据需要选取初始化需要加载的依赖,我添加了Cloud Bootstrap,可以自动生成Spring Cloud依赖管理包,直接点解Create
    IDEA2022搭建Spring Cloud多模块项目

  3. 删除生成后的src目录,pom.xml中添加pom属性
    IDEA2022搭建Spring Cloud多模块项目
    刚才创建时选择的Cloud Bootstrap 会在pom文件中自动生成spring-cloud 相关的依赖配置,spring-cloud-dependencies 是一个依赖管理器的pom文件,是对spring cloud版本的依赖管理
    IDEA2022搭建Spring Cloud多模块项目

创建子模块

使用maven方式创建api,biz,core,dao,integration,common,model 相关模块,创建内部依赖模块是使用maven的方式创建,便于总模块管理子模块的依赖仲裁;

点击项目根目录,右键 new -> module,选用maven的方式新建模块,Archetype可以选择quickstart,分别添加api,biz,core,dao,integration,common,model 这些模块。直接点击Create
IDEA2022搭建Spring Cloud多模块项目

创建web模块

web模块可以采用Spring Initializr的方式创建,可以自动初始化web相关的pom包和springboot的启动类,之后再修改web模块的pom文件的标签为当前父工程的配置即可;

  1. 点击项目根目录,右键 new -> module,选用Spring Initializr的方式新建web模块,点击Next
    IDEA2022搭建Spring Cloud多模块项目

  2. 根据自己的需要勾选所需的依赖,我选择了Spring Boot DevTools 和 Spring Web,点击Create
    IDEA2022搭建Spring Cloud多模块项目

  3. 修改web模块的pom文件的,将spring-boot-starter-parent 替换为父工程的pom配置
    IDEA2022搭建Spring Cloud多模块项目

  4. 在父工程的pom文件中新增web模块的module依赖
    IDEA2022搭建Spring Cloud多模块项目

创建完之后的工程目录结构如图:
IDEA2022搭建Spring Cloud多模块项目

添加模块依赖关系

创建完所有模块之后,自行在各个模块的pom 文件中添加模块依赖配置,推荐模块依赖关系如下图:
IDEA2022搭建Spring Cloud多模块项目

模块职责&关系说明

  • web模块:
    HTTP,HTTPS请求入口层,只负责对访问控制进行转发、参数转换,不编写复杂的业务逻辑,返回的结果数据用XxxVO模型封装,最终返回给前端的数据用BizResult封装;
  • biz模块:
    负责业务逻辑处理,biz层通常提供业务具体处理流程相关的服务;
  • core模块:
    负责对dao层返回的DO或integration层返回的外部系统模型进行转换、解析、业务逻辑处理。core层通常提供的是通用的服务;
  • api模块:
    负责对其它微服务系统提供接口,不允许抛异常,返回的结果统一使用BizResult封装;
  • dao模块:
    只负责MySQL数据库的对接操作,返回XxxDO对象;
  • integration模块:
    负责外部系统的对接,如其他内部微服务应用、微信接入、支付宝接入等,直接返回外部系统的领域模型,上层自行绝对是否需要再做进一步封装;
  • common模块:
    存放项目里面所有模块公用的组件,有些组件如果只是某个模块里面自己使用不要放在common下面,可以在本模块下建立utils包,例如:ResponseUtil之类只有web层才会使用到的工具类;
  • model模块:
    存放项目的数据模型,如常量、枚举、业务数据模型等;

编码规范

包名命名规范

web
 |- com.xxx.web.interceptor
 |- com.xxx.web.controller
 |- com.xxx.web.websocket
 |- com.xxx.web.vo
biz
 |- com.xxx.biz.manager
 |- com.xxx.biz.processor
 |- com.xxx.biz.job
core
 |- com.xxx.core.service
 |- com.xxx.core.service.impl
 |- com.xxx.core.handler
model
 |- com.xxx.model.biz
 |- com.xxx.model.core
 |- com.xxx.model.common
 |- com.xxx.model.integration
 |- com.xxx.model.dto
 |- com.xxx.model.vo
 |- com.xxx.model.exception
 |- com.xxx.model.constants
 |- com.xxx.model.enums
dao
 |- com.xxx.dao.dao
 |- com.xxx.dao.dataobject
 |- com.xxx.dao.mapper
integration
 |- com.xxx.integration.client
 |- com.xxx.integration.client.impl
common
 |- com.xxx.common.utils

方法命名

  1. 获取单个对象的方法,web/service层用get做前缀,dao层用select做前缀;
  2. 获取多个对象的方法,web/service层用list做前缀,dao层用select做前缀;
  3. 获取统计数据的方法都用count做前缀;
  4. 插入的方法web/service层用save/add/create做前缀,dao层用insert做前缀;
  5. 删除的方法web/service层用remove做前缀,dao层用delete做前缀;
  6. 修改的方法都用update做前缀;

领域模型命名

  1. 数据对象:XxxDO,xxx为数据库表名,每张表都要创建一个DO模型;
  2. 领域模型:Xxx,Xxx即为该领域模型的名称。所有领域模型对象之间的互相转换都禁止使用org.springframework.beans.BeanUtils,必须挨个属性进行设置,防止领域模型数据结构发生变更无法互相感知。
    表示状态信息的字段必须用枚举类或者常亮定义具体的属性值,禁止在代码中硬编码写死;
  3. 业务传输参数(集成领域模型对象,或者由多个领域模型对象组装成的对象):XxxDTO,Xxx为业务领域相关的名称。仅在biz和web层中使用。
  4. 展示对象:web层返回给前端的数据一律使用XxxVO封装,禁止使用Map。
  5. 查询参数:biz和core层使用XxxQuery,dao层使用XxxDAOQuery,入参超过三个,就要用对象封装起来;

spring事务规范
声明式事务和编程式事务的比较:

  1. 声明式事务是接口维度的,使用简单是要加上@Transactional的注解即可,但整个接口的代码都会进入数据库的事务中;
  2. 编程式事务比较灵活,可以自己指定加事务的代码块,细化事务的代码块,提升数据库事务的效率,降低发生死锁的可能性,但对代码有一定的侵入性,可以封装一个事务模板用于统一处理;
  3. 事务嵌套时编程式事务可制定事务的传播行为,来定制化事务的提交;
    场景:A类调用B类,B类调用C类,如果C类处理失败,要不能影响A类和B类的事务提交。声明式事务只要有一环的处理失败,所有数据都会回滚,使用编程式事务就能定制事务的事务的传播行为来完成该要求。该场景的需求一般较少会遇到,通常使用事务都是要求所有的数据要保持一致性;

总结:不推荐使用声明式事务,建议统一使用编程式事务。并且事务中只能包含数据库数据操作相关的代码,不能包含较多的业务处理逻辑,外部系统调用等耗时较长的代码;

事务模板代码实现:
Templates

import com.insigma.traffic.road.detection.model.exception.BizSystemException;
import com.insigma.traffic.road.detection.model.exception.ExceptionEnum;
import com.insigma.traffic.road.detection.model.result.BizResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 服务模版,可执行事务和非事务处理。
 * 该模板会吃掉所有异常,不会往外抛异常,需要调用方根据返回结果作相应的处理
 * 事务处理需要在参数中指定事务模版类型 {@link TxType}
 * <p>
 * 事务模板使用样例:
 * BizResult<String> result = Templates.execute(TxType.CVP, () -> {
 * // do checker
 * }, () -> {
 * // do execute
 * return "return result";
 * }, LOGGER);
 *
 * @author wangzhongxing
 * @version $Id: Templates.java, v 0.1 2019年08月27日 13:28 PM wangzhongxing Exp $
 */
@Component
public class Templates implements ApplicationContextAware {

    /**
     * 默认日志
     */
    private static final Logger DEFAULT_LOGGER = LoggerFactory.getLogger(Templates.class);

    /**
     * 事务模板
     */
    private static final Map<String, TransactionTemplate> TEMPLATES = new ConcurrentHashMap<>();

    /**
     * Disable construct.
     */
    private Templates() {
    }

    /**
     * @see ApplicationContextAware#setApplicationContext(ApplicationContext)
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        // init transaction templates
        String name;
        for (TxType txType : TxType.values()) {
            name = txType.getBeanName();
            TEMPLATES.put(name, applicationContext.getBean(name, TransactionTemplate.class));
        }
    }

    /**
     * 执行模板操作,不带数据库事务
     *
     * @param logger   自定义日志
     * @param executor 业务执行器
     * @param <T>      返回结果类型
     * @return biz result
     */
    public static <T> BizResult<T> execute(SupplyFunction<T> executor, Logger logger) {
        return execute(null, null, executor, logger);
    }

    /**
     * 执行模板操作,不带数据库事务
     *
     * @param logger   自定义日志
     * @param checker  前置业务检查器
     * @param executor 业务执行器
     * @param <T>      返回结果类型
     * @return biz result
     */
    public static <T> BizResult<T> execute(ActionFunction checker, SupplyFunction<T> executor,
                                           Logger logger) {
        return execute(null, checker, executor, logger);
    }

    /**
     * 执行模板操作,带数据库事务
     *
     * @param txType   事务类型
     * @param logger   自定义日志
     * @param executor 业务执行器
     * @param <T>      返回结果类型
     * @return biz result
     */
    public static <T> BizResult<T> execute(TxType txType, SupplyFunction<T> executor, Logger logger) {
        return execute(txType, null, executor, logger);
    }

    /**
     * 执行模板操作,带数据库事务
     *
     * @param txType   事务类型
     * @param logger   自定义日志
     * @param checker  前置业务检查器
     * @param executor 业务执行器
     * @param <T>      返回结果类型
     * @return biz result
     */
    public static <T> BizResult<T> execute(TxType txType, ActionFunction checker,
                                           SupplyFunction<T> executor, Logger logger) {

        BizResult<T> result;
        try {
            if (logger == null) {
                logger = DEFAULT_LOGGER;
            }

            // decide run mode
            TransactionTemplate transactionTemplate = null;
            if (null != txType) {
                transactionTemplate = TEMPLATES.get(txType.getBeanName());
                logger.debug("Run with transaction mode, TEMPLATES={}", TEMPLATES);
                if (transactionTemplate == null) {
                    logger.error("Get transaction template by name[{}] error.", txType.getBeanName());
                }
            }

            // biz check
            if (checker != null) {
                checker.apply();
            }

            // biz execute
            if (executor == null) {
                throw new BizSystemException(ExceptionEnum.SYSTEM_ERROR);
            }

            T data;
            if (transactionTemplate != null) {
                data = transactionTemplate.execute(status -> executor.apply());
            } else {
                data = executor.apply();
            }

            result = new BizResult<>(data);
        } catch (BizSystemException e) {
            result = new BizResult<>(e.getErrorCode(), e.getMessage());
            logger.error("Tamplates execute BizSystemException!errorCode={},errorMsg={}",
                    e.getErrorCode(), e.getErrorMsg());
        } catch (Exception e) {
            result = new BizResult<>(ExceptionEnum.SYSTEM_ERROR);
            logger.error("Tamplates execute Exception!", e);
        }

        return result;
    }

    public static void main(String[] args) {
        ActionFunction checker = () -> {
        };
        SupplyFunction<String> executor = () -> {
            return "";
        };

        BizResult<String> result = Templates.execute(TxType.CVP, () -> {
            // do checker
            // ...
        }, () -> {
            // do execute
            // ...
            return "return result";
        }, DEFAULT_LOGGER);
    }

}

TxType

/**
 * 事务类型枚举
 *
 */
public enum TxType {

    /**
     *  默认事务模版:
     * 如果上下文中已经存在事务,那么就加入到事务中执行,如果当前上下文中不存在事务,则新建事务。
     * 简而言之,只会存在最外层的父事务模版,因此,任意嵌套层次事务模版的回滚,都会导致所有事务模版的回滚。
     * {@link TransactiontemplateConfig}
     */
    CVP("transactionTemplateRequired"),

    /**
     * 事务模版 PROPAGATION_REQUIRES_NEW:
     * 每次都会新建一个事务,并且同时将上下文中的事务挂起,当新建事务执行完成以后,上下文事务再恢复执行
     * 父事务模版和子事务模版相互隔离,回滚互不影响
     * {@link TransactiontemplateConfig}
     */
    CVP_NEW("transactionTemplateNew"),

    ;

    /** 事务模版名称 */
    private String beanName;

    /**
     * Constructor
     *
     * @param beanName  事务模版名称
     */
    TxType(String beanName) {
        this.beanName = beanName;
    }

    public String getBeanName() {
        return beanName;
    }
}

ActionFunction

/**
 * 没有入参和出参, 只执行业务动作的函数。
 *
 * @author wangzhongxing
 * @version $Id: ActionFunction.java, v 0.1 2019年08月27日 13:38 PM wangzhongxing Exp $
 */
@FunctionalInterface
public interface ActionFunction {

    /**
     * 执行方法
     */
    void apply();

}

SupplyFunction

/**
 * 没有入参, 执行业务动作并返回处理结果的函数。
 *
 * @author wangzhongxing
 * @version $Id: ActionFunction.java, v 0.1 2019年08月27日 13:38 PM wangzhongxing Exp $
 */
@FunctionalInterface
public interface SupplyFunction<T> {

    /**
     * 执行方法.
     *
     * @return  返回结果。
     */
    T apply();

}

多模块启动配置文件管理

多模块化后,想让每个模块的配置文件独立管理,整合的时候再合并各个不同的模块的配置,需要先在每个模块下面创建一个配置文件,文件的命名格式必须是application-xxx.yml,启动层模块想引用下层模块的配置时需要在配置文件中添加spring.profiles.include: xxx 或者spring.profiles.active: xxx (xxx为子模块配置文件的后缀标识名)配置项显示引用所需要的配置文件。注意启动层模块的配置文件名必须是application.yml或者application.properties,不能带上-xxx的后缀,不然导致spring.profiles.active的配置失效,从而无法加载子模块的配置。例如启动层是web层,web层的配置文件命名为application.yml,如果命名是application-web.yml会导致子模块的配置无法加载。

ConfigFileApplicationListener 子模块配置加载类源码说明如下,默认是从加载application.properties或application.yml这两个配置文件中加载其它配置文件的配置,所以启动层模块的配置文件名必须是application.properties或application.yml。文章来源地址https://www.toymoban.com/news/detail-401662.html

到了这里,关于IDEA2022搭建Spring Cloud多模块项目的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 工程项目管理系统源码+功能清单+项目模块+spring cloud +spring boot em

    ​   工程项目管理软件(工程项目管理系统)对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营,全过程、全方位的对项目进行综合管理    工程项目各模块及其功能点清单 一、系统管理     1、数据字典:实现对数据字典

    2024年02月12日
    浏览(40)
  • springboot整合spring cloud gateway搭建网关服务

    spring cloud netflix zuul、spring cloud gateway是最常见的微服务网关,通过网关,我们可以在请求到达后端指定服务之前/后端服务处理完业务响应数据之后对响应进行对请求/响应进行处理。 比如常见的参数校验、接口鉴权等等,在后端服务的拦截器和过滤器能做的事在网关都可以做

    2024年02月07日
    浏览(38)
  • Java版企业工程项目管理系统源码+java版本+项目模块功能清单+spring cloud +spring boot

          工程项目各模块及其功能点清单 一、系统管理     1、数据字典:实现对数据字典标签的增删改查操作     2、编码管理:实现对系统编码的增删改查操作     3、用户管理:管理和查看用户角色     4、菜单管理:实现对系统菜单的增删改查操作     5、角色管理:

    2024年02月16日
    浏览(35)
  • Spring Cloud + Spring Boot 项目搭建结构层次示例讲解

    以下是我搭建Spring cloud项目架构的经验,我将以图片的形式和大家进行分享;至于Spring Boot的搭建经验,我会在图后以文字描述的方式和大家分享,请往下看: Spring Boot的搭建经验,我会以文字描述的方式和大家分享,请往下看: Controller 层 :Controller 层负责处理客户端的请

    2024年02月11日
    浏览(32)
  • IDEA 搭建 Maven模块化项目

    目录 1.前言 2. 软硬件环境 3.项目搭建 3.1.创建 SpringBoot 父项目 3.2. 构建子项目centerdao 3.3. 构建子项目centerweb 4. 建立父子 Module 依赖 4.1 删除不必要文件 4.2.修改 Parent 项目 packaging 4.3.修改子项目pom.xml 信息 4.4.补充说明 5. 项目继承关系 6. 验证项目 7.异常处理  8.结语 鸣谢    

    2024年02月04日
    浏览(35)
  • Java 版 spring cloud + spring boot 工程系统管理 工程项目管理系统源码 工程项目各模块及其功能点清单

           工程项目各模块及其功能点清单 一、系统管理     1、数据字典:实现对数据字典标签的增删改查操作     2、编码管理:实现对系统编码的增删改查操作     3、用户管理:管理和查看用户角色     4、菜单管理:实现对系统菜单的增删改查操作     5、角色管理:

    2024年02月14日
    浏览(40)
  • 告诉老默我想学Spring Cloud了(新手篇):从0到1搭建Spring Cloud项目(实际项目开发的浓缩精华版)

         Spring官方网址:https://spring.io/     电视剧《狂飙》有多火,看我博客的标题就知道了,哈哈,蹭了个热度。同样也是系列博客,后面还会有更多这个系列的博客发布。 这篇博客主要介绍如何从0到1搭建一个Spring Cloud项目,版本如何选型,项目结构如何搭建,适合新

    2023年04月09日
    浏览(55)
  • Java 版 spring cloud 工程系统管理 工程项目管理系统源码 工程项目各模块及其功能点清单

          工程项目各模块及其功能点清单 一、系统管理     1、数据字典:实现对数据字典标签的增删改查操作     2、编码管理:实现对系统编码的增删改查操作     3、用户管理:管理和查看用户角色     4、菜单管理:实现对系统菜单的增删改查操作     5、角色管理:

    2024年02月15日
    浏览(37)
  • 从0到1搭建spring cloud alibaba +springboot+nacos+dubbo微服务

      由以上版本对应关系:         springboot版本:2.3.2.RELEASE         spring cloud 版本选择:Hoxton.SR9         spring cloud alibaba版本选择:2.2.6.RELEASE 父工程的父工程:()  版本依赖关系:            其他业务模块依赖: 使用nacos做配置中心和注册中心+dubbo做RPC调用 配置文

    2024年02月11日
    浏览(29)
  • spring cloud、gradle、父子项目、微服务框架搭建---spring secuity oauth2、mysql 授权(九)

    https://preparedata.blog.csdn.net/article/details/120062997 新建两个服务 1.授权服务 端口号:11007 2.资源服务 端口号:11004 资源服务可以是订单服务、用户服务、商品服务等等 当然这两个服务也可以合并到一起, 依次顺序AuthorizationServerConfiguration、ResourceServerConfig、WebSecurityConfiguration;

    2024年02月10日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包