A preface.

Hello, everyone. Following on from the previous article, please, stop writing ancestral code and continue to talk about architecture and code design.

I believe you must have encountered in the process of development

  1. Maven dependency Conflicts
  2. Utility classes are defined repeatedly
  3. Repeated configuration classes are defined repeatedly in different projects
  4. Package hierarchy is not consistent in different projects
  5. .

This article will introduce you to a small and medium-sized company development of micro services when a more appropriate architecture model, if there is wrong, welcome to point out, common progress ~

Maven dependency management

Most small companies, and even some medium-sized ones, don’t have a dedicated infrastructure department. The use of various frameworks [maven introduction] is also a mess in the development of various lines of business. The company the blogger works for has high requirements for engineering dependent security management, and has a special security testing department to conduct security tests on jar packages deployed in production environment. One of the core security test points of concern is whether vulnerable Maven dependencies have been introduced.

Like fastjson, the most popular Ali-serialization framework on the market, serious vulnerabilities were frequently exposed, and security testers required that all jar packages in our production environment must be upgraded to secure versions or removed. Given the amount of code changes that removing tools might introduce, version upgrades were the natural solution. The trouble with this approach, however, is that it requires package by package changes. If other security vulnerability dependencies are found, they also need to be modified. Although it is not a difficult and thorny problem, but one project after another modification, the work is very repetitive, I have this time, touch the fish for a while, he does not smell good.

Therefore, it is particularly important to establish a unified version dependency system.

2.1. Maven dependency priorities

Shortest path first

A project, Demo, relies on two JAR packages, a-B-C-X (1.0) and A-D-X(2.0). Since the X(2.0) path is the shortest, the project uses X(2.0).

Pom claims precedence in order

What if a-b-x (1.0) and A-C-x (2.0) have the same length? In this case, Maven loads poM files in the order in which they are declared. If B is declared first and C is declared later, the last dependency will be X(1.0).Copy the code

2.2. Version control

Version control in Maven depends on the dependencyManagement tag

For example,

<dependencyManagement> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> < version > 1.1.43 < / version > < / dependency > < / dependencyManagement >Copy the code

This allows you to ignore the version number definition when used in the actual Dependencies tag

<dependencies>
	<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
		</dependency>
</dependencies>
Copy the code

2.3. Highest parent version project

2.3.1. Single project global versioning

Father pom

<? The 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" > < the parent > <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version> 2.3.10.release </version> <relativePath/> </parent> <groupId>com.baiyan</groupId> <artifactId>demo</artifactId> The < version > 0.0.1 - the SNAPSHOT < / version > < name > demo < / name > < packaging > pom < / packaging > < modelVersion > 4.0.0 < / modelVersion > <description>Demo</description> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> < Java version > 1.8 < / Java version > < spring - cloud. Version > Hoxton. SR8 < / spring - cloud. Version > < spring - the cloud - alibaba - dependencies. Version > 2.2.3. RELEASE < / spring -- cloud - alibaba - dependencies. Version > < / properties > <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId>  </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${spring-cloud-alibaba-dependencies.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project>Copy the code

Pom dependencies in submodules are used directly

<? The 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 http://maven.apache.org/xsd/maven-4.0.0.xsd" > < the parent > < the groupId > com. Baiyan < / groupId > < artifactId > demo < / artifactId > < version > 0.0.1 - the SNAPSHOT < / version > < / parent > The < modelVersion > 4.0.0 < / modelVersion > < artifactId > demo - start < / artifactId > < dependencies > < the dependency > <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> </dependency>  <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>Copy the code

Through the knowledge of 2.1 and 2.2, we combine the multi-module application. DependencyManagement can be defined in the parent POM and directly introduced in the child POM where dependencies are needed. Global versioning is done within individual projects.

2.3.2. Multi-project global management

OK, here we still don’t see how to manage all project common dependencies uniformly.

Take a look at the denpendcies reference to the spring-boot-starter-Web module in the parent POM and do not write the version number. Found in the

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> < version > 2.3.10. RELEASE < / version > < relativePath / > < / parent >Copy the code

Various Spring-related or common versioning definitions are defined internally.

With this in mind, let’s also create an empty project that will manage the Maven version

├ ─ ─ pom. XML └ ─ ─ baiyan - common - dependency. On imlCopy the code

Specific operation

1. The parent POM relies on Spring-boot

2. Some generic Maven dependency versions are defined in poM

3. Push the project to the central warehouse

4. The service application changes the parent POM from spring-boot to Baiyan-common-dependency

Such as some of the springboot version, fastjson version of the more general nature of the dependency definition can be placed in a separate dependency management project, in the event of a dependency security problem, as long as one place can be changed.


You don’t have to worry about that either:

For example, you might want to use springBoot version 2.3.8.RELEASE, but in the dependency project version has been changed to 2.3.10. So according to the shortest path dependency priority you just specify the corresponding SpringBoot version in the business Project management version, flexibility is also port to port.

Three. Module division

There is no strict industry standard for business module partitioning. It doesn’t say exactly how it should be designed. Under the microservice architecture system, with openFeign as the application of RPC framework, I suggest that the package be divided into the following modules

  • API: Defines the interface definition of the microservice provider, including openFeign related interface definitions, required interaction entities, enumerations, and so on
  • Base: business-neutral utility classes and general configuration management
  • RPC: API package openFeign definition implementation, here if bother API package and RPC package can be combined, I used to separate, interface structure more clear
  • Service: business processing. This package is larger and contains more logic
  • Interaction: user interaction layer, Controller, MqListener, openFeign interface implementation and other methods defined for the application to interact with the external
  • Start: global processing configuration definitions such as startup package, configuration file definition, log management definition

The structure of the module is relatively clear after this division, but the Service module is still a large package. The division within the Service module continues, with the principle of a single schema function in a folder, such as all configuration-related definitions, in the Config package.

4. Tool/configuration classes are stripped

After point 3, your project structure should be fairly clear. But you should still get a sense of the utility classes, mybatis-plus paging configuration, Swagger configuration, etc. This configuration is repeatedly defined in various projects.

As always, go ahead and create a new Common project, divided according to the modules in point 3. Define common utility classes and common configuration classes in the Common project. The generic configuration provides the starter function through the Spring-SPI mechanism. Then, the corresponding service applications can reference the corresponding Common module respectively, simplifying the repeated definition of tool classes and configuration classes.

In live.

The final dependency becomes that business applications depend on the Common package POM and configuration, and the common package POM depends on common-dependency

Source code acquisition

The demo code for the Common project has been placed on my Github.

If you are interested, you can take a look down:Github.com/louyanfeng2…

Seven. Contact me

If you think the article is well written, you can like it and comment + follow it

Nailing: louyanfeng25

WeChat: baiyan_lou