Spring Boot教程(一) 开发环境搭建

1. 使用向导创建项目

本文使用 IntelliJ IDEA来构建 Spring Boot基础开发环境

  1. File -> new -> Project
    选择 jdk和自动生成目录结构的站点, 点击下一步
    idea创建 spring boot项目 - 1

  2. 添加本地项目的坐标, 构建工具, 构建语言, 打包方式, 项目描述, 项目名称, 项目主包名, 点击下一步
    添加 maven项目坐标

  3. 选择需要的组件, 选择的组件会自动导入相关依赖, 忘记勾选也没有关系, 需要的时候手动在 pom.xml 中添加即可. 选择好之后点击下一步.
    这里只选择了几个基础的组件:
    lombok: 使用注解对 bean快速生成 setter, getter, toString, hashcode等方法, 推荐使用
    web: spring mvc
    thymeleaf: spring默认使用的模板引擎
    freemarker: 另一个使用比较广泛的模板引擎, 使用 Java语言实现
    mysql: mysql 数据库
    mybatis: 半自动的 orm框架
    选中要添加的组件
    这里是自动生成的 pom文件

    <?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">
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>cn.com.dom4j</groupId>
    <artifactId>spring_boot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    
    <name>spring_boot</name>
    <description>Demo project for Spring Boot</description>
    
    <!--
      可以通过继承spring-boot-starter-parent项目来获得一些合理的默认配置。
    -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>
    
    <dependencies>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
    
        <!-- 当添加此依赖时, 默认就启用了数据库连接池 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
    
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
    
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
    <build>
    
        <!--
          maven打包的时候会将非 .java文件过滤掉, 这样 mybatis mapper就不能创建成功
          通过如下配置, 可以将 将 src下的 mapper.xml一同打入 jar包
        -->
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
        <plugins>
            <!-- maven打包插件,可以打成 jar包或 war包 -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    </project>
    
  4. 这里是自动生好成的 spring boot项目, 使用 git管理的话, 记得配置一下 .gitignore文件, 这里使用的是 gitignore插件.
    至此一个基础的 spring boot骨架搭建完成. 接下来需要进行的就是相关整合配置.
    自动生成的 spring boot目录结构

2. spring boot与 mybatis集成

2.1 添加组件

pom.xml文件中 dependencies 中添加与 mybatis相关的组件
如果在前面通过 spring initializr 生成项目时勾选了 mybatis组件, 则不用再次添加了, 所有的组件同理.

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.0</version>
</dependency>

<!-- 
  spring-boot-starter-jdbc 主要给我们提供了 3个功能: 
    1. 对数据源的装配
    2. 提供一个 JdbcTemplate简化我们的使用
    3. 事务支持
  当添加此依赖时, 默认就启用了数据库连接池 
  spring boot 2.0 版本默认使用的连接池是 hikari
-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

<!-- 添加 mysql jdbc驱动, 其他数据库的话, 请添加对应驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

2.2 配置数据源

将自动生成的 application.properties 配置文件后缀改为 .yml
参考: YAML最最基础语法

application.yml中做如下配置
spring boot 的 jdbc模块会加载以下参数, 并且根据 url可以识别并自动加载 mysql驱动, 自动创建数据库实例, 自动实现连接池.

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/youdbname
    username: youusername
    password: youpassword

2.3 配置 mybatis

application.yml 中对 mybatis 进行配置

mybatis 相关配置的前缀为 mybatis
mapper-locations: 指定 mapper文件的位置, /**/ 表示任意目录
type-aliases-package: 指定要配置别名的类所在的包

mybatis:
  mapper-locations: classpath*:cn/com/dom4j/**/*Mapper.xml
  type-aliases-package: cn.com.dom4j.spring_boot.entity

2.4 编写基础的 crud进行测试

2.4.1 建库建表

create database spring_boot;
use spring_boot;

drop table if exists student;
create table student(
  id int primary key auto_increment,
  name varchar(100) not null comment '姓名',
  age int(3) comment '年龄',
  grade varchar(30) comment '班级',
  number varchar(100) not null comment '学号'
) engine=InnoDB auto_increment=1 default charset=utf8;

2.4.2 实体类

这里使用了 lombok来为我们生成 setter, getter, constructor, toString等
具体用法请参考 Lombok介绍

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Student {
    private int id;
    private String name;
    private int age;
    private String grade;
    private String number;
}

2.4.3 mapper.java

import cn.com.dom4j.spring_boot.entity.Student;
import org.springframework.stereotype.Repository;

@Repository
public interface StudentMapper {
    int addStudent(Student student);
    Student getStudentById(int id);
    int deleteStudentById(int id);
    int updateStudent(Student student);
}

2.4.4 mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >

<mapper namespace="cn.com.dom4j.spring_boot.dao.mapper.StudentMapper">

    <resultMap id="student_result_map" type="cn.com.dom4j.spring_boot.entity.Student">
        <id property="id" column="id" />
        <result property="name" column="name" />
        <result property="age" column="age" />
        <result property="grade" column="grade" />
        <result property="number" column="number" />
    </resultMap>

    <sql id="all_field">
        id, name, age, grade, number
    </sql>

    <insert id="addStudent" parameterType="Student">
        insert into student
          (name, age, grade, number)
        VALUE
          (#{name}, #{age}, #{grade}, #{number})
    </insert>

    <delete id="deleteStudentById" parameterType="int">
        delete from student where id = #{id}
    </delete>

    <update id="updateStudent" parameterType="Student">
        update
          student
        set
          <if test="name != null and name.length > 0">
            name = #{name},
          </if>
          <if test="age != null and age > 0">
            age = #{age},
          </if>
          <if test="grade != null and grade.length > 0">
            grade = #{grade},
          </if>
          <if test="number != null and number.length > 0">
            number = #{number},
          </if>
        where
          id = #{id}
    </update>

    <select id="getStudentById" parameterType="int" resultMap="student_result_map">
        select
          <include refid="all_field" />
        from
          student
        where
          id = #{id}
    </select>

</mapper>

2.4.5 dao实现类

import cn.com.dom4j.spring_boot.dao.mapper.StudentMapper;
import cn.com.dom4j.spring_boot.entity.Student;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;

@Repository
public class StudentDao {

    @Resource
    private StudentMapper mapper;

    public int addStudent(Student student) {
        return mapper.addStudent(student);
    }

    public Student getStudentById(int id) {
        return mapper.getStudentById(id);
    }

    public int deleteStudentById(int id) {
        return mapper.deleteStudentById(id);
    }

    public int updateStudent(Student student) {
        return mapper.updateStudent(student);
    }

}

2.4.6 service接口

import cn.com.dom4j.spring_boot.entity.Student;

public interface IStudentService {
    int addStudent(Student student);
    Student getStudentById(int id);
    int deleteStudentById(int id);
    int updateStudent(Student student);
}

2.4.7 service实现类

import cn.com.dom4j.spring_boot.dao.StudentDao;
import cn.com.dom4j.spring_boot.entity.Student;
import cn.com.dom4j.spring_boot.service.IStudentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Slf4j
@Service
public class StudentService implements IStudentService {

    @Resource
    private StudentDao studentDao;

    @Override
    public int addStudent(Student student) {
        int res = -1;
        try {
            res = studentDao.addStudent(student);
        } catch (Exception e) {
            log.error("addStudent error: ", e);
        }
        return res;
    }

    @Override
    public Student getStudentById(int id) {
        Student student = null;
        try {
            student = studentDao.getStudentById(id);
        } catch (Exception e) {
            log.error("getStudentById error: ", e);
        }
        return student;
    }

    @Override
    public int deleteStudentById(int id) {
        int res = -1;
        try {
            res = studentDao.deleteStudentById(id);
        } catch (Exception e) {
            log.error("deleteStudentById error: ", e);
        }
        return res;
    }

    @Override
    public int updateStudent(Student student) {
        int res = -1;
        try {
            res = studentDao.updateStudent(student);
        } catch (Exception e) {
            log.error("updateStudent error: ", e);
        }
        return res;
    }
}

2.4.8 编写测试用例

import cn.com.dom4j.spring_boot.entity.Student;
import cn.com.dom4j.spring_boot.service.IStudentService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;


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

    @Resource
    private IStudentService studentService;

    @Test
    public void addStudent() {
        Student student = new Student(4, "王二", 19, "大二", "2014304706");
        int res = studentService.addStudent(student);
        assert res == 1;
    }

    @Test
    public void getStudentById() {
        Student student = studentService.getStudentById(1);
        System.out.println(student);
        assert student != null;
    }
}

2.4.9 完整的项目结构

完整的项目结构

3. mybatis个性化配置

3.1 切换数据库连接池

3.1.1 测试当前使用的连接池

import cn.com.dom4j.spring_boot.entity.Student;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.List;

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

    @Resource
    private DataSource dataSource;

    @Resource
    private JdbcTemplate jdbcTemplate;

    @Test
    public void DBPoolTest() {
        System.out.println("dataSource  -->  " +  dataSource.getClass().getName());
        // output:  dataSource  -->  com.zaxxer.hikari.HikariDataSource
    }

    @Test
    public void jdbcTemplateTest() {

        DataSource dataSource = jdbcTemplate.getDataSource();
        System.out.println("dataSource  ->  " + dataSource.getClass().getName());

        List<Student> list = jdbcTemplate.query("select * from student", new Object[]{},
                (rs, rowNum) -> new Student(
                        rs.getInt("id"),
                        rs.getString("name"),
                        rs.getInt("age"),
                        rs.getString("grade"),
                        rs.getString("number")
                ));
        /* output: 
           [ 
             Student(id=1, name=小明, age=18, grade=大一, number=2014304706), 
             Student(id=2, name=小明, age=18, grade=大一, number=2014304706), 
             Student(id=3, name=小方, age=19, grade=大二, number=2014304706), 
             Student(id=4, name=王二, age=19, grade=大二, number=2014304706)
           ]
        */

    }
}

3.1.2 查看默认支持的连接池 (内嵌)

注意: spring boot 1.x版本默认使用的连接池是 tomcat-jdbc, 2.x版本中换成了 HikariCP

spring boot 2.0版本默认数据库连接池


查看 DataSourceAutoConfiguration.java得知:
spring boot 2.0支持的连接池有: HikariCP, tomcat-jdbc, commons-dbcp2, Generic
经测试, commons-dbcp, tomcat-dbcp已不再支持

spring boot 2.0默认支持的数据源

3.1.3 切换连接池

第一种方式: 加入连接池依赖, 并在 application.yml 中指定, 这里以 commons-dbcp2为例
推荐使用第一种方式, 简洁明了.

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-dbcp2</artifactId>
</dependency>
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/spring_boot
    username: root
    password: dom4j

    type: org.apache.commons.dbcp2.BasicDataSource

第二种方式: 排除 spring-boot-starter-jdbc中的 HikariCP依赖, 并引入自己需要的连接池依赖, 这里以 tomcat-jdbc为例

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
    <!-- 移除 HikariCP依赖 -->
    <exclusions>
        <exclusion>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<!-- 添加 tomcat-jdbc 连接池 -->
<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-jdbc</artifactId>
</dependency>

<!-- 
  同样支持 commons-dbcp2连接池, 但 tomcat-jdbc拥有更高的优先级
  经测试, 当 dbcp2 和 tomcat-jdbc同时存在时, 会选用 tomcat-jdbc, 与 pom文件中配置的顺序无关
-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-dbcp2</artifactId>
</dependency>

4. spring boot与 spring mvc集成

4.1 使用 thymeleaf模板引擎

4.2 使用 freemarker模板引擎

4.3 spring mvc个性化配置

5. spring boot 日志管理

5.1 日志配置

application.yml 中日志配置以 logging为前缀

  level: 指定日志级别, 可以配置到包级别, 有如下级别 trace, debug, info, warn, error
  path: 指定日志文件所在路径
  file: 指定日志文件名称, 默认是相对于当前目录 (配置了 file, path就不再生效)
  pattern: 指定日志的输出格式, 可以分别配置控制台和文件中的日志格式.

logging:
  level:
    cn.com.dom4j.spring_boot: trace
  path: /home/bobo
  file: log/spring_boot.log
  pattern:
    console: '%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n'
    file: '%d{yyyy-MM-dd} --> [%thread] %-5level %logger{50} - %msg%n'

日志输出格式

%d: 表示日期时间
%thread: 表示线程名
%level: 表示日志级别    %-5level表示级别从左显示5个字符宽度
%logger: 表示 logger名称,    %logger{50}: 表示 logger名称最长 50个字符, 否则按照句点分割
%msg: 日志信息
%n: 换行符        

日志输出
日志输出

5.2 自定义日志配置文件

使用 logback.xml 作为配置文件

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

<!-- 
根节点 configuration, 包含下面 3个属性
  scan: 当此属性为 true时, 配置文件如果发生改变, 将会被重新加载, 默认值为 true
  scanPeriod: 设置检测配置文件是否有修改的时间间隔, 如果没有给出时间单位, 默认是毫秒.
    当scan为 true时, 此属性生效. 默认的时间间隔为 1分钟
  debug: 当此属性为 true时, 将打印出 logback内部日志信息, 实时查看 logback运行状态. 默认为 false
 -->
<configuration scan="true" scanPeriod="60 seconds" debug="false">

    <!--
      contextName: 用来设置上下文名称, 每个 logger都关联到 logger上下文. 默认上下文名称为 default
        但可以使用 contextName设置成其他名字, 用于区分不同应用程序的记录. 一旦设置, 不能修改
     -->
    <contextName>myAppName</contextName>

    <!--
      property: 用来定义变量值, 它有两个属性 name和 value
        通过 property定义的值会被插入到 logger上下文中, 可以通过 '${}'来使用变量
    -->
    <property name="appName" value="myAppName"/>

    <!--
      timestamp: 获取日期时间戳, 它有两个属性: key和 datePattern
        key: 设置此 timestamp的名称
        datePattern: 设置当前时间(解析配置文件的时间)转换为字符串的模式, 遵循 java.txt.SimpleDateFormat的格式
    -->
    <timestamp key="bySecond" datePattern="yyyy-MM-dd HH:mm:ss" />

    <!--
      appender: 负责写日志的组件, 它有两个必要属性 name和 class
        name: 指定 appender的名称
        class: 指定 appender的全限定名
    -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!--
          ConsoleAppender: 把日志输出到控制台, 有以下子节点
            encoder: 对日志进行格式化
            target: 字符串 System.out(默认)或者 System.err
        -->
        <!--
          格式化输出: %d表示日期, %thread表示线程名, %-5level: 级别从左显示5个字符宽度(用于对齐), %msg: 日志消息, %n: 换行符
        -->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
        </encoder>
    </appender>

    <!--
      FileAppender: 把日志添加到文件, 有以下子节点
        file: 被写入的文件名, 可以是相对路径, 也可以是绝对路径, 如果上级目录不存在则会自动创建, 没有默认值
        append: 如果是 true, 日志被追加到文件末尾, 如果是 false则覆盖文件, 默认是 true
        encoder: 对记录事件进行格式化
        product: 如果是 true, 日志会被安全的写入文件, 即使其他的 FileAppender也在向此文件做写入操作, 效率低, 默认是 false
    -->
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>testFile.log</file>
        <append>true</append>
        <encoder>
            <pattern>~</pattern>
        </encoder>
    </appender>

    <!--
      RollingFileAppender: 滚动记录文件, 现将日志记录到指定文件, 当符合某个条件时, 将日志记录到其他文件. 有以下子节点
        file: ~
        append: ~
        rollingPolicy: 当发生滚动时, 决定 RollingFileAppender的行为, 涉及文件名移动和重命名. 属性 class定义具体的滚动策略类
          滚动策略:
            TimeBasedRollingPolicy: 最常用的滚动策略, 它根据时间来指定滚动策略, 既负责滚动也负责触发滚动, 有以下子节点
              fileNamePattern: 必要节点, 包含文件名及 '%d'转换符, '%d'可以包含一个 java.text.SimpleDateFormat指定的日期格式, 如:
                %d{yyyy-MM}, 如果直接使用 %d, 默认格式是 yyyy-MM-dd. RollingFileAppender的 file子节点可有可无, 通过设置 file,
                可以为活动文件和归档文件指定不同位置, 当前日志记录到 file指定的文件(活动文件), 活动文件的名字不会改变;
                如果没有设置 file, 活动文件的名字会根据 fileNamePattern的值, 每隔一段时间改变一次. '/'或 '\'会被当做目录分隔符
              maxHistory: 可选节点, 控制保留的归档文件的最大数量, 超过数量就删除文件. 假设设置每个月滚动, 且 maxHistory是 6,
                则只保留最近6个月的文件, 删除之前的旧文件. 注意: 删除旧文件时, 那些为了归档而创建的目录也会被删除

            SizeBasedTriggeringPolicy: 查看当前活动文件的大小, 如果超过指定大小会告知 RollingFileAppender触发当前活动文件滚动
                只有一个子节点:
              maxFileSize: 活动文件的大小, 默认是 10M

            FixedWindowRollingPolicy: 根据固定窗口算法重命名文件的滚动策略. 有以下子节点
              minIndex: 窗口索引最小值
              maxIndex: 窗口索引最大值, 当用于指定窗口过大时, 会自动将窗口设置为 12
              fileNamePattern: 必须包含 '%i', 例如: 假设最小值和最大值分别为 1和 2, 命名模式为 myLog%i.log, 会产生归档文件
                myLog1.log和 myLog2.log, 还可以指定文件压缩选项, 例如: myLog%i.log.gz或者 myLog%i.log.zip

    -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <append>true</append>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>~</pattern>
        </encoder>
    </appender>

    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>test.log</file>

        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
            <fileNamePattern>tests.%i.log.zip</fileNamePattern>
            <minIndex>1</minIndex>
            <maxIndex>3</maxIndex>
        </rollingPolicy>

        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <maxFileSize>5MB</maxFileSize>
        </triggeringPolicy>

        <!--
          encoder: 对记录事件进行格式化.负责两件事, 一是把日志信息转换成字节数组, 二是把字节数组写入到输出流
            PatternLayoutEncoder: 是唯一有用且是默认的 encoder, 有一个 pattern节点, 用来设置日志的输入格式.
              使用 '%'加转换符的方式, 如果要输出 '%', 则必须用 '\'对 '%'进行转义
        -->
        <encoder>
            <pattern>~</pattern>
        </encoder>
    </appender>

    <!--
      除了上面说的之外, 还有 SocketAppender, SMTPAppender, DBAppender, SyslogAppender, SiftingAppender, 不过这些并不常用
    -->

    <!--
      logger: 用来设置某一个包或者某一个类的日志打印机别, 以及指定 appender.
            logger仅有一个 name属性, 一个可选的 level和一个宽的 addtivity属性,
            可以包含零个或多个 appender-ref元素, 标识这个 appender将会添加到这个 logger
        name: 用来指定受此 logger约束的一个包或者具体的某一个类
        level: 用来设置打印级别, 大小写无关: trace, debug, info, warn, error, all 和 off,
            还有一个特殊值 inherited或者同义词 null, 代表强制执行行上级的级别. 如果未设置此属性, name当前 logger将会继承上级的级别

        addtivity: 是否向上级 logger传递打印信息. 默认是 true.
          同 logger一样, 可以包含零个或多个 append-ref, 标识这个 appender将会添加到这个 logger

    -->

    <!--
      root: 它也是 logger元素, 但是它是根 logger, 是所有 logger的上级.
            只有一个 level属性, 因为 name已经被命名为 root, 且已经是最上级了
        level: 用来设置打印级别, 大小写无关, trace, debug, info, warn, error, all 和 off, 不能设置为 inherited或者同义词 null
          默认是 debug
    -->
</configuration>

6. spring boot 热部署

使用 spring-boot-devtools 模块来实现热部署

devtools可以实现页面热部署, 即页面修改后会立刻生效, 这个可以在 application.yml文件中配置 spring.thymeleaf.cache = false来实现.
实现类文件热部署 (类文件修改后不会立即生效, 有 1~2秒的延迟)
实现对属性文件的热部署, 即 devtools会监听 classpath下的文件变化, 并且会立刻重启 (发生在文件保存时机, 建议开发时将 devtools关闭, 脑补 idea无限重启, 无限卡顿 …) , 注意因为其采用 虚拟机机制, 该项重启是很快的.

配置了后, 在修改 java文件后也就支持了热启动, 不过这种方式是属于项目重启 (速度比较快的项目重启), 会清空 session的值, 也就是不过有用户登录的话, 项目重启后需要重新登录.

默认情况下, /MATA-INF/maven, /MATA-INF/resources, /static, /templates, /public这些文件夹的修改不会使项目重启, 但是会重新加载 (devtools内嵌了一个 LiveReload, 当资源发生改变时, 浏览器刷新)

6.1 引入模块

添加如下依赖

<!-- 使用 devtools 实现热部署 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency>

<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>
    <scope>test</scope>
</dependency>

配置 maven-plugin

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <!-- 配置实现热部署 -->
    <configuration>
        <fork>true</fork>
    </configuration>
</plugin>

6.2 devtools配置

spring:
  devtools:
    restart:
      # 热部署生效
      enabled: true
      # 设置要重启的目录
      additional-paths: src/main/java
      # classpath目录下的 WEB-INF文件夹下的内容修改不重启
      exclude: WEB-INF/**

6.3 idea 配置

当我们修改了 java类后, idea默认是不自动编译的, 而 spring-boot-devtools又是监听 classpath下的文件发生变化时才会重启应用, 所以需要设置 idea的自动编译

File -> Setting -> Build, Execution, Deployment -> Compiler -> 勾选 Build Project autoautomatically
idea配置热部署 - 1

Ctrl + Shift +Alt + / , 选择 Registry, 勾上 Compiler autoMake allow when app running
idea配置热部署 - 2

至此, spring boot的热部署就配置完毕了.

7. spring boot 其他设置

7.1 profile多环境支持

profile是 spring对不同环境提供不同配置功能的支持, 可通过激活, 指定参数等方式快速切换环境

原理是建立多个配置, 然后指定要生效的配置

第一种方式:
  多个配置放在不同的配置文件中, 主配置文件是 application.yml, 其他环境配置文件为 application-{profile}.yml, 放在同一级目录下.

|-- application.yml
|-- application-dev.yml
|-- application-beta.yml
|-- application-prod.yml

application.yml
spring:
  profiles:
    # 指定要使用的配置文件是 application-dev.yml
    active: dev

application-dev.yml
server:
  port: 9091

第二种方式
  将配置所有配置写到同一个配置文件中, yml文件支持多文档块, 通过 --- 来分隔配置, 将主要配置放在最前面, 为每个配置指定名称后, 在主配置中引用即可.

server:
  port: 80

spring:

  profiles:
    active: prod

  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/youdbname?useUnicode=true&amp;characterEncoding=UTF-8
    username: youusername
    password: youpassword

  devtools:
    restart:
      enabled: true
      additional-paths: src/main/java
      exclude: WEB-INF/**

  thymeleaf:
    cache: false

mybatis:
  mapper-locations: classpath*:cn/com/dom4j/**/*Mapper.xml
  type-aliases-package: cn.com.dom4j.spring_boot.entity

---

server:
  port: 8081

spring:
  # 指定该配置块的名称
  profiles: dev

---

server:
  port: 8082
spring:
  profiles: beta

---

server:
  port: 8083
spring:
  profiles: prod

8. 参考

SpringBoot配置devtools实现热部署

posted @ 2018-06-17 20:11  九月清晨-_-  阅读(76)  评论(0编辑  收藏  举报