SpringBoot实战系列之多模块工程搭建

2020-04-13  本文已影响0人  程序员小白成长记

做服务时,比较考虑到工程的模块化和可扩展化,下面以一个完整的demo为例,来看一下如何进行模块化

一、首先看一下整个工程的重要的目录结构

1.1 工程结构概览图

image.png

1.2 结构模式图

image.png

1.3 工程结构详细图

.
├── course-demo    //启动模块
│   ├── deploy
│   │   ├── start.sh    //启动脚本
│   │   └── stop.sh    //停止脚本
│   ├── src
│   │   └── main
│   │       ├── java
│   │       │   └── com
│   │       │       └── sun
│   │       │           └── course
│   │       │               └── coursedemo
│   │       │                   └── CourseDemoApp.java    //启动类
│   │       └── resources
│   │           └── application.properties    //配置文件
│   ├── pom.xml    //启动模块的pom
│   ├── course-demo.iml
│   └── target
│       ├── classes
│       │   ├── application.properties
│       │   └── com
│       │       └── sun
│       │           └── course
│       │               └── coursedemo
│       │                   └── CourseDemoApp.class
│       ├── course-demo-version.jar    //总jar包,包含依赖和主类
│       └── course-demo-version.jar.original    //不包含依赖和主类
├── course-demo-controller    //controller模块
│   ├── src
│   │   └── main
│   │       └── java
│   │           └── com
│   │               └── sun
│   │                   └── course
│   │                       └── coursedemo
│   │                           ├── controller
│   │                           │   └── StudentController.java
│   │                           ├── model
│   │                           │   └── Student.java
│   │                           └── util
│   ├── course-demo-controller.iml
│   ├── pom.xml    //controller模块的pom
│   └── target
│       └── course-demo-controller-version.jar    //controller模块的jar包
├── course-demo-service
│   ├── src
│   │   ├── main
│   │   │   ├── java
│   │   │   │   └── com
│   │   │   │       └── sun
│   │   │   │           └── course
│   │   │   │               └── coursedemo
│   │   │   │                   ├── mapper
│   │   │   │                   │   ├── MapperConfiguration.java    //配置扫描类,一种扫描的写法
│   │   │   │                   │   └── StudentMapper.java
│   │   │   │                   ├── model
│   │   │   │                   │   └── Student.java
│   │   │   │                   ├── service
│   │   │   │                   │   ├── StudentSerivce.java
│   │   │   │                   │   └── impl
│   │   │   │                   │       └── StudentSerivceImpl.java
│   │   │   │                   └── util
│   │   │   └── resources
│   │   │       └── application.properties    //为了service层的单测的配置文件
│   │   └── test
│   │       └── java
│   │           └── com
│   │               └── sun
│   │                   └── course
│   │                       └── coursedemo
│   │                           ├── CourseDemoApplicationTests.java
│   │                           └── service
│   │                               └── impl
│   │                                   └── StudentSerivceImplTest.java
│   ├── course-demo-service.iml
│   ├── pom.xml    //service模块的pom
│   └── target
│       └── course-demo-service-version.jar    //service模块的jar包
├── .gitignore
├── README.md
├── build.sh    //编译脚本
├── course-demo-root.iml
└── pom.xml    //总工程pom

1.4 工程结构说明

1)可以看到一共分为三个模块
启动模块:1,启动服务。2,停止服务。3,设置配置文件;
controller模块: 1,接收前端请求。2,调用service层服务
service模块:1,与数据库交互。2,mapper文件编写。3,service层编写单测
2)每一个模块都需要一个pom文件,每一个模块都是一个module(可以单独打包,作为一个服务,供其他模块调用)
3)模块间有依赖关系,通过pom文件来配置(注意:不要出现循环依赖)
4)配置文件,配置文件是application.properties,由于Springboot的思想是“习惯大于配置”,所以命名为application.properties和application.yml的文件都会自动加载,共有两处需要配置文件。(一处为启动模块,用于打包部署;一处为service模块,用于单测)

二、关键模块说明

image.png

2.1 course-demo (启动类模块)

1)start.sh

#!/bin/sh
APPLICATION=course-demo.jar
SPRING_CONFIG_FILE=../conf/application.properties
MAX_MEMORY=2048M
MAX_PERM_MEMORY=512M

nohup java -Dspring.config.location=$SPRING_CONFIG_FILE -Dfile.encoding=UTF-8 \
-Xmx$MAX_MEMORY -XX:MaxPermSize=$MAX_PERM_MEMORY -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps \
-Xloggc:gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=20M -jar $APPLICATION > /dev/null 2>&1 &

2)stop.sh

#!/bin/sh
ps ux | grep "course-demo" | grep -v grep | grep -v stop.sh | cut -c 9-15 | xargs kill -s 9

echo "kill $@ done"

3)CourseDemoApp.java

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

4)application.properties

server.port = 8088
#=================== logging config ===================#
logging.level.com.sun.course: debug
org.mybatis: trace
org.springframework.boot: debug
#=========================== database =========================#
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://XXX.XXX.XXX.XXX:3306/DBName?useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=123456

5)pom.xml

<?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.sun.course</groupId>
        <artifactId>course-demo-root</artifactId>
        <version>${course-demo-root-version}</version>
    </parent>
    <groupId>com.sun.course</groupId>
    <artifactId>course-demo</artifactId>

    <dependencies>
        <!--controller模块的依赖-->
        <dependency>
            <groupId>com.sun.course</groupId>
            <artifactId>course-demo-controller</artifactId>
            <version>${course-demo-root-version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <!--使用springboot的maven插件-->
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <!--设置主类-->
                    <mainClass>com.sun.course.coursedemo.CourseDemoApp</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

2.2 course-controller模块

image.png

pom.xml

<?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.sun.course</groupId>
        <artifactId>course-demo-root</artifactId>
        <version>${course-demo-root-version}</version>
    </parent>
    <groupId>com.sun.course</groupId>
    <artifactId>course-demo-controller</artifactId>


    <dependencies>

        <!--service模块的依赖-->
        <dependency>
            <groupId>com.sun.course</groupId>
            <artifactId>course-demo-service</artifactId>
            <version>${course-demo-root-version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

    </dependencies>
    
</project>

2.3 course-service模块

image.png

1)MapperConfiguration.java (可以扫描该目录下的mapper文件)

@Configuration
@MapperScan(basePackageClasses = MapperConfiguration.class)
public class MapperConfiguration {
}

2)application.properties

server.port = 0
#=================== logging config ===================#
logging.level.com.sun.course: debug
org.mybatis: trace
org.springframework.boot: debug
#=========================== database =========================#
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://XXX.XXX.XXX.XXX:3306/DBName?useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=123456

3)CourseDemoApplicationTests.java

package com.sun.course.coursedemo;


import com.sun.course.coursedemo.model.Student;
import com.sun.course.coursedemo.service.StudentSerivce;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class CourseDemoApplicationTests {

    @Autowired
    private StudentSerivce studentSerivce;

    @Test
    public void getStudentByName(){
        String name = "Tom";
        Student student = studentSerivce.getStudentByName(name);
        System.out.println(student);
    }

}

4)pom.xml

<?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.sun.course</groupId>
        <artifactId>course-demo-root</artifactId>
        <version>${course-demo-root-version}</version>
    </parent>

    <groupId>com.sun.course</groupId>
    <artifactId>course-demo-service</artifactId>

    <dependencies>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.1.tmp</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.44</version>
        </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>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>

        <!--部署的时候注释,否则报循环引用; 单测的时候打开-->

        <!--<dependency>
            <groupId>com.sun.course</groupId>
            <artifactId>course-demo</artifactId>
            <version>version</version>
            <scope>test</scope>
        </dependency>-->

    </dependencies>

</project>

2.4 父工程

1)pom.xml

<?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.2.6.RELEASE</version>
    </parent>

    <groupId>com.sun.course</groupId>
    <artifactId>course-demo-root</artifactId>
    <version>${course-demo-root-version}</version>
    <packaging>pom</packaging>

    <properties>
        <java.version>1.8</java.version>
        <course-demo-root-version>version</course-demo-root-version>
    </properties>

    <modules>
        <module>course-demo</module>
        <module>course-demo-controller</module>
        <module>course-demo-service</module>
    </modules>

</project>

2)build.sh

if [ $# -eq 0 ] ; then
  mvn -Dspring.profiles.active=test -Dmaven.javadoc.skip=true clean package -U
else
  if [ $1 = "-q" ] ; then
    mvn -Dmaven.test.skip=true -Dmaven.javadoc.skip=true clean package -U
  else
    echo "build.sh [-q]"
    exit 0
  fi
fi

if [ $? -ne 0 ] ; then
  echo "mvn package error"
  exit -1
fi

rm -rf output
mkdir output

mkdir -p output/bin
mkdir -p output/conf

cp course-demo/target/course-demo-version.jar output/bin/course-demo.jar
cp course-demo/deploy/start.sh output/bin
cp course-demo/deploy/stop.sh output/bin
cp -rf course-demo/src/main/resources/* output/conf

三、编译执行

  1. 在根目录执行sh build.sh -q会生成一个output文件夹
    image.png
    2.cd output , sh start.sh 执行
    image.png
  2. 在浏览器访问
    http://localhost:8088/student/tom

四、github地址

github地址

五、参考

9、@SpringBootApplication用法
项目配置spring-boot-maven-plugin插件无法生效的问题
**之后又一个工程因为没有加repackge,spring-boot-maven-plugin不生效

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>2.2.6.RELEASE</version>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

坑一:在idea中,子模块总是跳出父模块

示例:
父模块:course-manage-system,子模块:course-demo
发现curse-demo在course-manage-system内部有一个,在course-manage-system外部也有一个。
解决办法:如下图所示,将右侧红色部分删除即可。


image.png
上一篇下一篇

猜你喜欢

热点阅读