微服务架构设计规范

  • Post author:
  • Post category:其他




一、项目系统服务约定



1、项目工作空间(项目集)

项目工作空间系统源码根目录,一般以项目名称做为工作空间,例如:

iToken

注:项目按前后端分离设置,项目工作空间可以进一步划分,后端项目工作空间以项目名称,前端项目工作空间以项目名称-web。

示例:

iToken:项目工作空间
|__itoken:后端项目工作空间
|__itoken-web:前端项目工作空间



2、后端项目服务规划



2.1、服务命名

xx-xx/xx-xx-xx

项目名-模块名/项目名-模块名-二级模块名

大小写:全部小写,单词间使用-连接



2.2、项目服务划分

项目服务划分一般包含,统一的依赖管理、分布式配置中心、分布式链路追踪、分布式路由网关、分布式系统监控、单点登录服务提供者、数据缓存服务提供者、文件上传服务提供者、短信服务提供者、邮件服务提供者、业务模块服务提供者等等。


  • xx-dependencies

    :统一的依赖管理,命名规则,项目名-dependencies

  • xx-eureka

    :服务注册与发现,命名规则,项目名-eureka

  • xx-config

    :分布式配置中心,命名规则,项目名-config

  • xx-zipkin

    :分布式链路追踪,命名规则,项目名-zipkin

  • xx-gateway

    :分布式路由网关,命名规则,项目名-gateway

  • xx-admin

    :分布式系统监控,命名规则,项目名-admin
  • xx-service-sso:单点登录服务提供者,命名规则,项目名-service-sso
  • xx-service-redis:数据缓存服务提供者,命名规则,项目名-service-redis
  • xx-service-upload:文件上传服务提供者,命名规则,项目名-service-upload
  • xx-service-admin:管理员服务提供者,命名规则,项目名-service-模块名称
  • itoken-web-admin:管理员服务消费者,命名规则,项目名-web-模块名称

详细命名规则参考

李卫民-iToken 项目简介



二、项目结构约定



1、先看看阿里是怎么约定的

我印象中,以前在看《阿里巴巴Java开发手册》时,好像有关于工程结构和应用分层相关的内容,于是我回翻了一下,果然有:

img

它这里面讲的内容大概就是:关于一个正常的企业项目里一种

通用的项目结构和代码层级划分

的指导意见。

按这本书上说的,一般分为如下几层:

  • 开放接口层
  • 终端显示层
  • Web 层
  • Service 层
  • Manager 层
  • DAO 层
  • 外部接口或第三方平台

由于书中的篇幅关系,它这地方讲得比较笼统了,估计初学者看了还是会懵,所以接下来

结合实际项目代码结构

,来唠一唠具体的项目结构和代码分层。




2、通常的项目结构


首先说在前面的是

:这东西并没有一套通用的标准,不同公司或者团队的使用习惯和规范也不尽相同。

我们就以当下非常火热的Spring Boot典型项目结构为例,创建出来的项目应该总体分为三大层:

img


  • 项目根目录/src/main/java

    :放置项目Java源代码


  • 项目根目录/src/main/resources

    :放置项目静态资源和配置文件


  • 项目根目录/src/test/java

    :放置项目测试用例代码


  • 项目根目录/src/test/resources

    :放置项目测试静态资源和配置文件


  • pom.xml

    :项目对象模型,源代码、配置文件、开发者的信息和角色、问题追踪系统、组织信息、项目授权、项目的url、项目的依赖关系等等。


  • README.md

    :服务说明介绍,MarkDown文本格式,用户系统介绍,版本更变更说明等等


  • .gitattributes

    :Git的

    gitattributes

    文件是一个文本文件,文件中的一行定义一个路径的若干属性。以行为单位设置一个路径下所有文件的属性。

    要匹配的文件模式 属性1 属性2

    参考:https://www.jianshu.com/p/bcdb8fff1687


  • .gitignore

    :Git提交过滤规则配置文件

    参考:

    李卫民-Git 过滤文件配置

而位于

/src/main/java

目录下的Java源代码的组织结构大家比较关心,这地方也只能给出一个通常典型的结构,毕竟不同项目和团队实践不一样,稍许有区别,但整体安排应该差不多。而且如果是

多模块

的项目的话,下面的结构应该只对应其中一个模块,其他模块的代码组织也大致差不多。

img

各个目录详细介绍:

|__annotation:放置项目自定义注解
|__aspect:放置切面代码
|__config:放置配置类
|__constant:放置常量、枚举等定义
   |__consist:存放常量定义
   |__enums:存放枚举定义
|__controller:放置控制器代码
|__filter:放置一些过滤、拦截相关的代码
|__mapper:放置数据访问层代码接口
|__model:放置数据模型代码
   |__entity:放置数据库实体对象定义
   |__dto:存放数据传输对象定义
   |__vo:存放显示层对象定义
|__service:放置具体的业务逻辑代码(接口和实现分离)
   |__intf:存放业务逻辑接口定义
   |__impl:存放业务逻辑实际实现
|__utils:放置工具类和辅助代码

然后接下来

/src/main/resources

目录,里面主要存放静态配置文件和页面静态资源等东西:

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

当然,这地方估计有一个

很多人都会纠结的

关于

DTO/VO/DO



数据模型定义

的区分。

这在《阿里巴巴Java开发手册》中倒是做了一个所谓的严格区分,那本书上是这样去定义的:


  • DO(Data Object)

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

  • DTO(Data Transfer Object)

    :数据传输对象,Service或Manager向外传输的对象。

  • BO(Business Object)

    :业务对象。由Service层输出的封装业务逻辑的对象。

  • AO(Application Object)

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

  • VO(View Object)

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

  • Query

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

老实讲,看到这么多对象的定义,我也是很蒙的。实际项目开发时,我觉得没有必要刻意照搬去定义这么多层对象,这样后续做对象转换工作都能烦skr人。

出于简单起见,我个人觉得,只要保证业务逻辑层

Service

和数据库

DAO

层的操作对象严格划分出来,确保互相不渗透,不混用,问题应该就不大。

比如在我上面举例的这个项目的代码结构中,

Service

层处理的对象都定义在了

dto

包里,而

DAO

层处理的对象都放在了

entity

包里了。




3、项目结构划分总结

如果从一个用户访问一个网站的情况来看,对应着上面的项目代码结构来分析,可以贯穿整个代码分层:

img

对应代码目录的流转逻辑就是:

img

我想,应该看得比较清楚了吧。


所以,以后每当我们拿到一个新的项目到手时,只要按照这个思路去看别人项目的代码,应该基本都是能理得顺的




4、一些注意事项


  1. Contorller

    层参数传递建议不要使用

    HashMap

    ,建议使用数据模型定义

  2. Controller

    层里可以做参数校验、异常抛出等操作,但建议不要放太多业务逻辑,业务逻辑尽量放到

    Service

    层代码中去做

  3. Service

    层做实际业务逻辑,可以按照功能模块做好定义和区分,相互可以调用
  4. 功能模块

    Service

    之间引用时,建议不要渗透到

    DAO

    层(或者

    mapper

    层),基于

    Service

    层进行调用和复用比较合理
  5. 业务逻辑层

    Service

    和数据库

    DAO

    层的操作对象不要混用。

    Controller

    层的数据对象不要直接渗透到

    DAO

    层(或者

    mapper

    层);同理数据表实体对象

    Entity

    也不要直接传到

    Controller

    层进行输出或展示。



三、Spring Boot项目创建



1、创建项目创建

项目创建分两种情况,Git托管项目,非Git托管项目。

创建项目群组以及子项目



2、IntelliJ IDEA 初始化项目



2.1、打开项目群组(项目工作空间)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p8CoRQze-1590543000895)(IntelliJ IDEA 手工创建 Spring Boot 微服务项目集.assets/clipboard.png)]



2.2、设置项目运行环境JDK版本

img

img



2.3、初始化项目根目录
  1. 创建子项目根目录


    • 项目根目录/src/main/java

      :放置项目Java源代码

    • 项目根目录/src/main/resources

      :放置项目静态资源和配置文件

    • 项目根目录/src/test/java

      :放置项目测试用例代码

    • 项目根目录/src/test/resources

      :放置项目测试静态资源和配置文件

    img

    img

  2. 设置项目根目录属性


    • /src/main/java

      :设置源目录

    • /src/main/resources

      :设置资源目录

    • /src/test/java

      :设置测试源目录

    • /src/test/resources

      :设置测试资源目录

    img



2.4、初始化pom.xml
  1. 初始化pom配置

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.3.0.RELEASE</version>
            <relativePath /> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.tangsm</groupId>
        <artifactId>boot-mail-demo</artifactId>
        <version>1.0.0-SNAPSHOT</version>
        <packaging>jar</packaging>
        <name>boot-mail-demo</name>
        <description>Mail Demo 示例</description>
    
        <properties>
            <java.version>1.8</java.version>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        </properties>
    
        <dependencies>
            <!-- spring boot Begin -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <!-- spring boot End -->
    
            <!-- spring boot devtools 热构建 Begin -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <scope>runtime</scope>
                <optional>true</optional>
            </dependency>
            <!-- spring boot devtools End -->
    
            <!-- thymeleaf 非前后端分离选择 Begin -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
            <dependency>
                <groupId>net.sourceforge.nekohtml</groupId>
                <artifactId>nekohtml</artifactId>
            </dependency>
            <!-- thymeleaf End-->
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <!-- 配置启动类,可以不写,建议加上 -->
                        <mainClass>com.tangsm.boot.mail.demo.BootShiroDemoApplication</mainClass>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>
    
  2. 添加为Maven项目

    img

    img



2.5、添加项目源码包路径

源码包路径:com.公司名称.子项目名称(子项目名称中的 “-” 转换成 “.” )

img

img



2.6、添加Spring Boot启动类

启动类名称 = 项目名称 + Application

img

package com.tangsm.boot.mail.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class BootMailDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(BootMailDemoApplication.class, args);
    }
}


2.7、添加Spring Boot 资源配置

application.yml

文件

img

img

server:
  port: 8080 # 端口
  servlet:
    context-path: /mail # 系统上下文路径

spring:
  thymeleaf:
    cache: false # 开发时关闭缓存,不然没法看到实时页面
    mode: HTML # 用非严格的 HTML
    encoding: UTF-8
    servlet:
      content-type: text/html



四、其他设置



1、Spring Boot 启动类统一管理

img



2、修改重构快捷键

Ctrk + S

原始

保存全部

快捷键为

Ctrk + S

调整为

Ctrk + Shift + S

img



五、参考文档



版权声明:本文为tangyb828原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。