其他分享
首页 > 其他分享> > SpringBoot应用——项目搭建指北

SpringBoot应用——项目搭建指北

作者:互联网

文章目录


一、工程结构规范

在这里插入图片描述1、数据持久层:底层 MySQL 、 Oracle 、 Hbase 等进行数据交互
2、各个层级有自己的数据封装实体类:DO、DTO、VO、query等等
3、dao层引入数据库信息,除了实体类,还包含mapper
4、从jar引入角度看
manager引入dao,service引入manager
web(controller层)引入service
对外接口api层引入service,但是建议不引入controller层
5、从调用关系看,就是如图的调用层级关系
6、common通用包
不需要引入dao层,里面包含的是各种工具、枚举或常量,直接为manager引用

二、创建springBoot项目

1、Idea中,我们可以直接使用Maven创建

2、在大的外层模块中继续创建各种子模块

在这里插入图片描述在这里插入图片描述

3、根据工程结构规范,进行包引入

<!--这是service层,由于没有manager,则需要直接引入common和dao-->
<dependencies>
    <dependency>
        <groupId>com.rj</groupId>
        <artifactId>common</artifactId>
        <version>${project.version}</version>
    </dependency>
    <dependency>
        <groupId>com.rj</groupId>
        <artifactId>dao</artifactId>
        <version>${project.version}</version>
    </dependency>
</dependencies>

<!--这是api层-->
<!--可以将项目中其他模块jar包引入,版本号与当前模块的parent一致-->
<dependency>
    <groupId>com.rj</groupId>
    <artifactId>service</artifactId>
    <version>${project.version}</version>
</dependency>

4、引入springBoot依赖,进行版本控制

<!--版本号控制-->
<properties>
    <spring-boot-parent.version>2.0.1.RELEASE</spring-boot-parent.version>
    <spring-boot-mybatis.version>2.0.0</spring-boot-mybatis.version>
    <mybatis-plus-boot-starter>3.4.2</mybatis-plus-boot-starter>
    <mybatis-plus-generator>3.4.0</mybatis-plus-generator>
    <hutool-all.version>5.6.6</hutool-all.version>
    <spring-boot-druid.version>1.1.10</spring-boot-druid.version>
    <mysql.version>5.1.29</mysql.version>
    <lombok.version>1.16.10</lombok.version>
    <junit4.version>4.12</junit4.version>
    <java.version>1.8</java.version>
    <spring-boot-maven-plugin.version>2.2.5.RELEASE</spring-boot-maven-plugin.version>
</properties>

<!--这个是版本控制管理,不会引入jar包,而只是声明名称和版本,具体的引用在子模块-->
<dependencyManagement>
    <dependencies>
        <!--引入需要的springBoot组件,需要指定版本号${version}-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot-parent.version}</version>
        </dependency>
        <!--log日志,内置的是logback-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
            <version>${spring-boot-parent.version}</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${spring-boot-mybatis.version}</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis-plus-boot-starter}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
            <version>${spring-boot-parent.version}</version>
        </dependency>
        <!--自动生成domain/dao层的框架,可以不需要-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>${mybatis-plus-generator}</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>${spring-boot-parent.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>${spring-boot-druid.version}</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>${hutool-all.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit4.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

使用dependencyManagement和直接使用dependencies的最大区别,在于,前者只是声明要使用什么依赖以及对应版本号,但不会真正导入依赖,即使飘红也没关系;后者会真正导入依赖。
所以,使用前者,我们就可以在子模块中根据子模块的实际情况进行实际的jar包引入;而后者,则会在各个子模块中都会全部引入,这是很不合规范的

<!--这是api层,我们只需要引入spring-boot-starter-web的jar包-->
<dependencies>
    <!--子模块根据需要实际引入jar包-->
    <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>
	</dependency>
</dependencies>
在这里插入图片描述同理,可以在dao层引入数据库、mybatis、mybatis-plus等对应的jar包
在common可以引入日志依赖,根据传递依赖原则,在顶层的api层都有依赖进来。

5、配置文件

在web或api层的resource目录中配置yml文件,注意命名规范:application.yml

#dataSource
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/mydb3?useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
    druid:
      initial-size: 3
      min-idle: 3
      max-active: 10
      max-wait: 60000
      filter:
        stat:
          log-slow-sql: true
          slow-sql-millis: 1

  #环境:env就是pom中的环境选择标签
  profiles:
    active: ${env}

#tomcat端口号
server:
  port: 8089
  servlet:
    context-path: /rj
  tomcat:
    uri-encoding: utf-8

#mybatis
mybatis-plus:
  type-aliases-package: com.rj.domain
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations: classpath:com/rj/*/mapper/*.xml

#log日志配置
logging:
  config: classpath:logback.xml

同级位置配置对应的开发或者生成环境配置文件,注意明明规范application-dev.ymlapplication-pro.yml
并在对应的pom文件中配置环境选择

<!-- 开发环境,默认激活 -->
<profiles>
    <profile>
    	<!--id要和env中的一致-->
        <id>dev</id>
        <properties>
        	<!--这个只是针对的文件后缀,即application-后面的-->
            <env>dev</env>
        </properties>
        <!--默认环境 -->
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
    </profile>
    <!-- 生产环境 -->
    <profile>
        <id>pro</id>
        <properties>
            <env>pro</env>
        </properties>
    </profile>
</profiles>

同级位置引入我们的日志配置logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <!-- 日志路径 -->
    <property name="log_dir" value="/export/Logs/iceStatistic"/>

    <!-- 控制台 -->
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern><!--%black(控制台-)--> %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{10}) - %cyan(%msg%n)
            </pattern>
        </encoder>
    </appender>

    <!-- debug日志 -->
    <appender name="debug" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log_dir}/debug.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log_dir}/debug-%d{yyyy-MM-dd-HH}.log</fileNamePattern>
            <maxHistory>48</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %thread %X{invokeNo} %logger{40} %msg%n</pattern>
        </encoder>
    </appender>

    <!-- info日志 -->
    <appender name="info" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log_dir}/info.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log_dir}/info-%d{yyyy-MM-dd-HH}.log</fileNamePattern>
            <maxHistory>72</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %thread %X{invokeNo} %logger{40} %msg%n</pattern>
        </encoder>
    </appender>

    <!-- error日志 -->
    <appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log_dir}/error.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log_dir}/error-%d{yyyy-MM-dd-HH}.log</fileNamePattern>
            <maxHistory>72</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %thread %X{invokeNo} %logger{40} %msg%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印错误日志 -->
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <logger name="DEBUG_LOG" level="debug" additivity="false">
        <appender-ref ref="debug"/>
    </logger>

    <logger name="INFO_LOG" level="info" additivity="false">
        <appender-ref ref="info"/>
    </logger>

    <logger name="ERROR_LOG" level="error" additivity="false">
        <appender-ref ref="error"/>
    </logger>

    <logger name="com.jd.flight" level="debug" additivity="false">
        <appender-ref ref="stdout"/>
        <appender-ref ref="debug"/>
    </logger>
    <root level="info">
        <appender-ref ref="stdout"/>
        <appender-ref ref="info"/>
        <appender-ref ref="error"/>
    </root>
</configuration>

6、springBoot启动类

在web或api层的java/com/rj/下创建启动类

@SpringBootApplication
@MapperScan("com.rj.*.mapper")
public class AppStart {
    public static void main(String[] args) {
        SpringApplication.run(AppStart.class,args);
    }
}

springBootApplication是自动装配,MapperScan是对mapper文件的扫描

由于springBoot内置tomcat,直接启动这个类,就可以将项目起来

springBoot的测试类

@SpringBootTest(classes = AppStart.class)
@RunWith(SpringRunner.class)
@Slf4j
public class StudentTest {
	
	//这个是在yml文件中配置的,虽然yml是冒号分隔,但是这里还是需要使用“.”来调用
    @Value("${vipuser.name}")
    private String name;

    @Test
    public void testStudent() {
        log.error("name = {}", name);
    }
}

7、在web或api层,pom中需要配置打包build

<!--build-->
<!-- Package as an executable jar -->
<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
            <!--可以访问的资源文件路径-->
            <includes>
                <include>application.yml</include>
                <include>application-${env}.yml</include>
                <include>*.txt</include>
                <include>**/*.xml</include>
                <include>**/messages*.properties</include>
                <include>**/*.csv</include>
                <include>**/*.zip</include>
                <include>**/*.ftl</include>
                <include>*.properties</include>
            </includes>
        </resource>
    </resources>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>${spring-boot-maven-plugin.version}</version>
            <configuration>
                <executable>true</executable>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>${java.version}</source>
                <target>${java.version}</target>
            </configuration>
        </plugin>
    </plugins>
</build>

spring-boot-maven-plugin.versionjava.version版本也可以在父pom中控制

8、排包

这项操作非常重要,由于包冲突,导致项目启动失败,这里推荐使用插件Maven Helper进行包冲突排除,建议将低版本的jar包排除掉

9、mybatis自动生成工具类

(选用) 根据数据库表自动生成domain、mapper、mapper.xml、service和controller

//需要引入`mybatis-plus-generator`和`spring-boot-starter-freemarker`

package codegenerate;

import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * 根据数据库表自动生成domain/mapper/service/controller
 */
@RunWith(JUnit4.class)
public class CodeGenerator {

    /**
     * 运行测试生成
     */
    @Test
    public void doGenerator() {
        generator("user",  "student");
    }

    /**
     * 自动生成的方法
     * @param nodeName 业务模块的名称,比如用户user、商品good...,同名会追加类
     * @param tables 表名,可多个,建议单个生成
     */
    @SuppressWarnings("all")
    private static void generator(String nodeName, String... tables) {
        final String fNodeName = StringUtils.isEmpty(nodeName) ? "test" : nodeName;

        //代码生成器
        AutoGenerator mpg = new AutoGenerator();

        //局配置
        GlobalConfig gc = new GlobalConfig();
        
        //获取工程的绝对路径
        final String parentPath = "D:\\Java\\ProjectJ\\springBootTest";
        gc.setAuthor("rj");
        gc.setOpen(false);
        gc.setSwagger2(false);
        mpg.setGlobalConfig(gc);

        //数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/mydb3?useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true");
        dsc.setDriverName("com.mysql.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("root");
        mpg.setDataSource(dsc);

        //包配置: src\main\java\com\rj\domain
        PackageConfig pc = new PackageConfig();

        //生成文件夹
        Map<String, String> configPathInfo = new HashMap(8) {
            {
                put(ConstVal.XML_PATH, parentPath + "\\dao\\src\\main\\java\\com\\rj\\"+fNodeName+"\\mapper");
                put(ConstVal.MAPPER_PATH, parentPath + "\\dao\\src\\main\\java\\com\\rj\\"+fNodeName+"\\mapper");
                put(ConstVal.ENTITY_PATH, parentPath + "\\dao\\src\\main\\java\\com\\rj\\domain\\"+fNodeName+"\\entity");
                put(ConstVal.SERVICE_PATH, parentPath + "\\service\\src\\main\\java\\com\\rj\\"+fNodeName+"\\service");
                put(ConstVal.SERVICE_IMPL_PATH, parentPath + "\\service\\src\\main\\java\\com\\rj\\"+fNodeName+"\\service\\impl");
                put(ConstVal.CONTROLLER_PATH, parentPath + "\\api\\src\\main\\java\\com\\rj\\"+fNodeName+"\\controller");
            }
        };

        //生成对应的类
        pc.setPathInfo(configPathInfo);
        pc.setParent("com.rj");
        pc.setXml(fNodeName+".mapper");
        pc.setMapper(fNodeName+".mapper");
        pc.setEntity("domain."+fNodeName+".entity");
        pc.setService(fNodeName+".service");
        pc.setServiceImpl(fNodeName+".service.impl");
        pc.setController(fNodeName+".controller");
        mpg.setPackageInfo(pc);

        //策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true);
        strategy.setInclude(tables);

        //表前缀,根据具体情况修改
        strategy.setTablePrefix("");
        mpg.setStrategy(strategy);
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
    }
}

10、关于@Configuration@Bean

//@Configuration 创建自己的线程池,并交给spring管理
@Configuration
public class MyThreadExecutorConfig {

    /**
     * 核心线程数
     */
    private static final int CORE_POOL_SIZE = 5;

    /**
     * 最大线程数
     */
    private static final int MAX_POOL_SIZE = 8;

    /**
     * 最大等待时间
     */
    private static final long KEE_PALIVE = 60L;

    /**
     * 线程队列
     */
    private static final int QUEUE_SIZE = 5;

    /**
     * 方法上打上@Bean注解,并指定方法名id,就可以使用方法名直接调用
     */
    @Bean("threadpool")
    public ThreadPoolExecutor getExecutor() {
        return new ThreadPoolExecutor(
                CORE_POOL_SIZE,
                MAX_POOL_SIZE,
                KEE_PALIVE,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(QUEUE_SIZE),
                new ThreadPoolExecutor.AbortPolicy());
    }
}

//我们也可以使用yml配置文件注入参数
/**
 * 核心线程数
 */
@Value("${mythread.core.size}")
private int CORE_POOL_SIZE;

//调用线程池:这里使用的是@Autowired,所以会根据类名去找,而与我们指定的bean名称id无关
//如果我们使用@Resource,则必须将这个类的名字与我们指定的@Bean的名称id一致
@Autowired
private ThreadPoolExecutor threadpool1324251;
@Resource
private ThreadPoolExecutor threadpool;

//这样就可以直接使用线程池了

标签:指北,SpringBoot,spring,boot,version,log,com,rj,搭建
来源: https://blog.csdn.net/qq_45337431/article/details/117616243