springboot2.3.4多模块pom类型项目搭建踩坑最全手册

文章详细介绍了如何配置Maven工程的pom.xml,避免使用SpringBoot的打包插件,而采用Maven的资源插件。对于不同类型的模块,有不同的资源配置。对于包含启动类的模块,需要指定mainClass,并配置相关资源和SpringBoot插件。同时,文章展示了如何在同一个应用中配置多个数据源,包括DruidDataSource的详细设置和Mapper的扫描。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.最外层pom工程pom.xml配置时,务必用maven的打包插件,不要用springboot的插件,如下:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <version>2.4.3</version>
        </plugin>
    </plugins>
</build>

2.打包package时,一定走最外层的pom工程打包,有mainClass的子模块的target目录下都能找到可用的jar包了

3.对于不是启动类所在的模块,只是给其他模块引用的子模块,一般都不需要resources目录:

        子模块中如果没有静态配置文件,pom.xml中就不需要<build></build>了,如果有静态文件,比如有mybatis写sql的*.xml文件,则需要在该模块的pom.xml中配置打包需要的插件:

<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
            </includes>
        </resource>
    </resources>
</build>

4.对于是启动类所在的模块,需要resources目录及目录下相关的配置文件,若启动类为

com.example.app.WarApplication,则pom.xml中需要配置插件:
<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.*</include>
            </includes>
        </resource>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
            </includes>
        </resource>
    </resources>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <mainClass>com.example.app.WarApplication</mainClass>
            </configuration>
        </plugin>
    </plugins>
</build>

5.对于是启动类所在的模块,若启动类为

com.example.app.WarApplication,则需要在类WarApplication.java上面加上注解:
@ComponentScan(basePackages = {"com.example.app","com.example.pub", "com.example.manage", "com.example.analysis"})
其中basePackages的几个值对应四个子模块的项目路径,app引用了pub\manage\analysis几个模块的代码。

6.对于拦截器,AOP,swagger,过滤器,全局异常,多数据源等都配置在有启动入口类的子模块中,比如我们任然在上述叫app的子模块中配置多数据源(ds1和ds2):

多数据源1(主库):

package com.example.app.common.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

@Configuration
@MapperScan(basePackages = {
        Ds1DataSourceConfig.PACKAGE1,Ds1DataSourceConfig.PACKAGE2},
        sqlSessionFactoryRef = "ds1SqlSessionFactory")
public class Ds1DataSourceConfig {
    
    static final String PACKAGE1 = "com.example.pub.*.mapper";
    static final String PACKAGE2 = "com.example.manage.*.mapper";
    private static final String MAPPER_LOCATION1 = "classpath:com/example/pub/*/mapper/*.xml";
    private static final String MAPPER_LOCATION2 = "classpath:com/example/manage/*/mapper/*.xml";

    @Value("${ds1.url}")
    private String url;

    @Value("${ds1.username}")
    private String user;

    @Value("${ds1.password}")
    private String password;

    @Value("${ds1.driver-class-name}")
    private String driverClass;

    @Bean(name = "ds1DataSource")
    @Primary
    public DataSource ds1DataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverClass);
        dataSource.setUrl(url);
        dataSource.setUsername(user);
        dataSource.setPassword(password);
        dataSource.setInitialSize(50);
        dataSource.setMaxActive(500);
        dataSource.setMaxWait(5000L);
        dataSource.setMinIdle(50);
        dataSource.setQueryTimeout(60);
        return dataSource;
    }

    @Bean(name = "ds1TransactionManager")
    @Primary
    public DataSourceTransactionManager ds1TransactionManager() {
        return new DataSourceTransactionManager(ds1DataSource());
    }

    @Bean(name = "ds1SqlSessionFactory")
    @Primary
    public SqlSessionFactory ds1SqlSessionFactory(@Qualifier("ds1DataSource") DataSource ds1DataSource)
            throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(ds1DataSource);
        Resource[] resources1 = new PathMatchingResourcePatternResolver()
                .getResources(Ds1DataSourceConfig.MAPPER_LOCATION1);
        Resource[] resources2 = new PathMatchingResourcePatternResolver()
                .getResources(Ds1DataSourceConfig.MAPPER_LOCATION2);
        Resource[] resources = new Resource[resources1.length + resources2.length];
        for (int i = 0; i <  resources1.length + resources2.length; i++) {
            if(i < resources2.length) {
                resources[i] = resources1[i];
            }
            if(i >= resources1.length && i < resources1.length + resources2.length) {
                resources[i] = resources2[i - resources1.length];
            }
        }
        sessionFactory.setMapperLocations(resources);
        return sessionFactory.getObject();
    }
}

多数据源2:

package com.example.app.common.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

@Configuration
// 扫描 Mapper 接口并容器管理
@MapperScan(basePackages = Ds2DataSourceConfig.PACKAGE, sqlSessionFactoryRef = "ds2SqlSessionFactory")
public class Ds2DataSourceConfig {

    // 精确到 demo 目录,以便跟其他数据源隔离
    static final String PACKAGE = "com.example.analysis.*.mapper";
    private static final String MAPPER_LOCATION = "classpath:com/example/analysis/*/mapper/*.xml";

    @Value("${ds2.url}")
    private String url;

    @Value("${ds2.username}")
    private String user;

    @Value("${ds2.password}")
    private String password;

    @Value("${ds2.driver-class-name}")
    private String driverClass;

    @Bean(name = "ds2DataSource")
    public DataSource ds2DataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverClass);
        dataSource.setUrl(url);
        dataSource.setUsername(user);
        dataSource.setPassword(password);
        dataSource.setInitialSize(100);
        dataSource.setMaxActive(1000);
        dataSource.setMinIdle(50);
        dataSource.setMaxWait(5000L);
        dataSource.setQueryTimeout(60);
        return dataSource;
    }

    @Bean(name = "ds2TransactionManager")
    public DataSourceTransactionManager ds2TransactionManager() {
        return new DataSourceTransactionManager(ds2DataSource());
    }

    @Bean(name = "ds2SqlSessionFactory")
    public SqlSessionFactory ds2SqlSessionFactory(@Qualifier("ds2DataSource") DataSource ds2DataSource)
            throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(ds2DataSource);
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources(Ds2DataSourceConfig.MAPPER_LOCATION));
        return sessionFactory.getObject();
    }
}

7.待续~~~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值