SpringBoot project specification notes. 2021

I'm afraid I lost the SpringBoot project specification sorted out a year ago. After all, I wrote it carefully at that time, and now it's posted on the blog.

1. Application division specification

During the development of application system, the back-end service needs to consider dividing multiple SpringBoot modules according to the division principle of module / micro service, so as to facilitate the reconstruction of micro service in the future. Application Division specifications / principles are as follows:

  • Horizontal split: split according to different business domains, such as order, marketing, risk control, integral resources, etc. Form an independent business domain micro service cluster.
  • Vertical split: split different modules or components in a business function. For example, public components are divided into independent atomic services, which sink to the bottom to form a relatively independent atomic service layer. In this way, the service-oriented splitting of business can be realized.

To do a good job in the layering of micro services, we need to sort out and extract core services and public applications, sink to the core and public capability layer as independent services, and gradually form a stable service center, so that the front-end applications can respond to the changing market demand more quickly. Is the service split as small as possible? The size and size of microservices are relative. For example, in the initial stage, we split the transaction into a micro service, but with the increase of business volume, a trading system may have gradually become large, and the concurrent flow is not small. In order to support more transaction volume, we will split the trading system into order service, bidding service, transfer service, etc. Therefore, the splitting of services needs to be combined with specific businesses. The general principle is high cohesion within services and low coupling between services.

2. Project creation specification

At least one SpringBoot project and multiple SpringBoot modules will be created in an application system according to the situation. The following rules shall be followed when creating the project:

  • GroupID format: com {company / BU} Business line [. Sub business line].

    Note: {company / BU} for example: BU level I such as alibaba/taobao/tmall/aliexpress; Sub business lines are optional.

    Positive example: com taobao. Jstorm or com alibaba. dubbo. register

  • ArtifactID format: product line name - module name. There is no repetition or omission of semantics. Go to the central warehouse to check it first.

    Positive example: Dubbo client / fastjson API / jstorm tool

  • Version format

    Naming method of version number of second-party Library: main version number Minor version number revision number

    1) Major version number: product direction changes, or large-scale API incompatibility, or architecture incompatibility upgrade.

    2) Minor version number: maintain relative compatibility, add main functional features, and modify the incompatibility of API with minimal impact.

    3) Revision number: maintain full compatibility, repair bugs, add secondary features, etc.

    Note: note that the starting version number must be: 1.0.0, not 0.0.1.

2.1. Parent module creation specification

One or more Spring Boot projects will be created in an application system. During the creation of each Spring Boot project (New - > project), the following specifications shall be followed:

namestandard
Project typeSpring Initializr
GroupFollow the java package name specification to the company layer
Artifact< project / business center abbreviation > - service, etc
TypeMaven Project
LanguageJava
PackagingPOM
Java VersionKeep default
NameProject name, same as Artifact
Package<Group>.< Project / business center abbreviation >
VersionYou can select a stable version with a newer current time, such as the release version

The naming method of Version number: major Version number Minor Version number revision number

  1. Major version number: product direction changes, or large-scale API incompatibility, or architecture incompatibility upgrade.
  2. Minor version number: maintain relative compatibility, add main functional features, and modify the incompatibility of API with minimal impact.
  3. Revision number: maintain full compatibility, repair bugs, add secondary features, etc.

Note: the starting version number must be: 1.0.0, not 0.0.1.

3. POM specification

3.1. Parent module POM specification

Parent module (TL service) POM file reference:

<?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.4.5</version>
        <relativePath/>
    </parent>
    <groupId>com.df.tl</groupId>
    <artifactId>tl-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>tl-service</name>
    <description>tl Parent module of the project</description>
    <!--    attribute-->
    <properties>
        <java.version>1.8</java.version>
        <spring-parent.version>2.4.5</spring-parent.version>
        <lombok.version>1.18.0</lombok.version>
        <mybatis.version>1.3.2</mybatis.version>
        <mysql.version>8.0.16</mysql.version>
        <druid.version>1.1.13</druid.version>
    </properties>
    <!--    Submodule, declaration-->
    <modules>
        <module>tl-api</module>
        <module>tl-project-service</module>
        <module>tl-task-service</module>
    </modules>
    <!--    Packaging method pom-->
    <packaging>pom</packaging>

    <!--    dependencyManagement Administration-->
    <dependencyManagement>
        <dependencies>
            <!--            spring web-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <version>${spring-parent.version}</version>
            </dependency>
            <!--            spring test-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <version>${spring-parent.version}</version>
            </dependency>
            <!--            lombok-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>
            <!--            mybatis-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.version}</version>
            </dependency>
            <!--            mysql-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <!--            druid data source-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>${druid.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <!--        pluginManagement Administration-->
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

</project>

The points needing attention are as follows:

  • properties: except Java In addition to version, you can customize attributes (non mandatory), such as the version number maven depends on.
  • Modules: all sub modules need to be declared.
  • packaging: the parent module uses pom. This tag has three attributes: pom/jar/war, but the function of the parent module is usually packaged, so pom can be used.
  • Dependency management: it is recommended that the parent module use dependency management to manage dependencies, which is more flexible than dependencies and will not lead to unnecessary dependencies in the sub module. You can query the data by yourself and compare the differences between dependency management and dependencies.
  • pluginManagement: the parent module recommends using the pluginManagement management plug-in, which is more flexible than plugins. You can query the information by yourself and compare the differences between pluginManagement and plugins.

3.2. Sub module POM specification

Sub module (TL project service) POM file reference:

<?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>com.df.tl</groupId>
        <artifactId>tl-service</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>com.df.tl</groupId>
    <artifactId>tl-project-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>tl-project-service</name>
    <description>Project management module</description>
    <!--    Packaging method jar-->
    <packaging>jar</packaging>

    <dependencies>
        <!--        spring web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--        spring test-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <!--            lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

The points needing attention are as follows:

  • Parent: inherits the parent module.
  • packaging: the sub module uses jar.
  • Dependencies: whether the parent module uses dependency management or dependencies, all child modules use dependencies. If it is the former, it is necessary to declare repeated dependency, but the version number can be omitted; If it is the latter, there is no need for repeated dependency.
  • Plugins: whether the parent module uses plugins management or plugins, all child modules use plugins. In case of the former, it is necessary to declare repeated dependency, but the version number and configuration details can be omitted; If it is the latter, there is no need for repeated dependency.

4. Layered specification

  • Open interface layer: it can directly encapsulate Service methods and expose them into RPC interfaces; Encapsulated into http interface through Web; Gateway control layer, etc.
  • Terminal display layer: the layer where the template at each end renders and performs display. At present, it mainly includes velocity rendering, JS rendering, JSP rendering, mobile display, etc.
  • Web layer: it is mainly used to forward access control, verify various basic parameters, or simply handle non reusable services.
  • Service layer: a relatively specific business logic service layer.
  • Manager layer: general business processing layer, which has the following characteristics:
    1) For the layer encapsulated by the third-party platform, preprocess the returned results and transform exception information.

    2) Sinking of the general capabilities of the Service layer, such as caching scheme and middleware general processing.

    3) Interact with the DAO layer and reuse the combination of multiple Daos.

  • DAO layer: data access layer, which interacts with underlying MySQL, Oracle, Hbase, OB, etc.
  • External interface or third-party platform: including RPC open interface of other departments, basic platform and HTTP interface of other companies.

Here is also an example of structural layering of a single project:

.
├── java
│   └── com
│       └── df
│           └── learn
│               └── exampleapi
│                   ├── ExampleApiApplication.java
│                   ├── config
│                   │   └── ThreadPoolConfig.java
│                   ├── constant
│                   │   └── ThreadConstant.java
│                   ├── controller
│                   │   └── DemoController.java
│                   ├── manager
│                   │   └── UserManager.java
│                   ├── mapper
│                   │   └── HrUserMapper.java
│                   ├── pojo
│                   │   ├── bo
│                   │   │   └── EmailInfoBO.java
│                   │   ├── dto
│                   │   │   └── UserInfoDTO.java
│                   │   └── po
│                   │       └── HrUserPO.java
│                   ├── service
│                   │   ├── DemoService.java
│                   │   └── impl
│                   │       └── DemoServiceImpl.java
│                   └── util
│                       └── EmailUtil.java
└── resources
    ├── application-dev.yml
    ├── application-prod.yml
    ├── application-uat.yml
    ├── application.yml
    ├── ehcache.xml
    ├── logback-spring.xml
    ├── mapper
    │   └── HrUserMapper.xml
    ├── static
    └── templates

Now explain these engineering structures:

  • Controller: front-end control layer controller.
  • Service: data service interface layer.
  • Manager: general business processing layer manager.
  • service.impl: data service interface implementation layer Service Implements.
  • config: configure the class directory.
  • consts: constant class directory.
  • util: tool class directory.
  • Mapper (dao): dao layer directory. If it is a MyBatis project, you can use mapper.
  • pojo: contains directories such as PO/BO/VO/DTO.

POJO layering

  • POJO (Plain Ordinary Java Object): it is the general term of DO/DTO/BO/VO. POJO specifically refers to simple classes with only setter/getter/toString, including DO/DTO/BO/VO, but it is prohibited to be named xxxPOJO.
  • PO (persistent object): one-to-one correspondence with the database table structure. It is also replaced by DO (Data Object).
  • DTO (Data Transfer Object): Data Transfer Object, which is the object transmitted outward by Service or Manager, that is, the object encapsulated by Request or Response in Controller.
  • BO (Business Object): Business Object. It can be understood that in the process of Java development, some POJO s that have nothing to DO with table structure may contain one or more DOS.
  • VO (View Object): display object. Its function is to encapsulate all data of a specified page (or component). VO is uncommon because it is too similar to DTO and is basically replaced by DTO. For example, men / women are stored as 0 / 1 in the database, 0 / 1 is displayed in DTO, and men / women should be displayed in VO. But there is no need to tangle. I prefer to use DTO directly.

5. Multi environment configuration specification

YAML configuration files in multiple environments are specified as follows:

  • application.yml -- master profile
  • application-dev.yml -- development environment configuration file
  • application-uat.yml -- test environment configuration file
  • application-prod.yml -- formal environment configuration file

Examples of configuration files are as follows:

spring:
  profiles:
    active: prod
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/test
    username: root
    password: root

There are usually many sets of environments in a project, including development environment, test environment, UAT environment and production environment. The parameters of each environment are different, so we need to configure the parameters of each environment into the corresponding yml file. You can enable the current configuration file in the main configuration file, for example:

spring:
  profiles:
    active: prod

This line is configured in application In the YML file, it means that the currently effective configuration file is application-prod.yml.

6. Exception handling specification

Exception handling requirements of each layer

  • DAO layer: there are many types of exceptions that can not be caught with fine-grained exceptions. Use the catch(Exception e) method and throw new DAOException(e). There is no need to print the log, because the log must be captured and printed into the log file in the Manager/Service layer. If the same server logs again, it will waste performance and storage.
  • Service layer: when an exception occurs in the service layer, the error log must be recorded to the disk, and the parameter information should be brought as much as possible, which is equivalent to protecting the crime scene.
  • Manager layer: the manager layer and Service are deployed on the same machine, and the logging method is the same as that of DAO layer. If it is deployed separately, the processing method is the same as that of Service.
  • Web layer: the web layer should never continue to throw exceptions up, because it is already at the top level. If you realize that this exception will make the page unable to render normally, you should directly jump to the friendly error page and try to add friendly error messages. The open interface layer should handle the exception into error code and error information.

Global exception handling ideas

As mentioned earlier, exception handling is required in the Service, Manager and Controller layers. These exceptions that need to be handled can often be divided into several categories. Different types of exceptions are handled in a unified manner. For example: exceptions that need to be fed back to the user (such as account / password error), exceptions handled by the program itself (such as database lock conflict, optimistic lock CAS automatic retry), server exceptions that are not resolved (such as database downtime, network fluctuation, etc.).

For this kind of exceptions that can be handled by unified classification, it is recommended to write a global exception handling method. The specific implementation method includes the following three steps:

  1. User defined exception class: use unified exceptions or user-defined exception classes. For example, "exceptions that need to be fed back to users" can customize business exception classes and throw prompts manually.
  2. Throw exception: because of unified processing, you need to throw exceptions in a standardized way.
  3. Global exception handling: for exception handling, you can't try catch at each method. You can use the idea of aspect oriented programming to do global exception handling. Common global exception handling methods include @ ControllerAdvice, AOP, filter and interceptor. However, note that their execution order is (servletcontextlistener > Filter > interception > AOP > specific execution method > AOP > @ ControllerAdvice > interception > Filter > servletcontextlistener).

Keywords: Spring Boot

Added by mikesab on Thu, 03 Feb 2022 15:57:24 +0200