Spring Boot教程(一) 开发环境搭建
1. 使用向导创建项目
本文使用 IntelliJ IDEA
来构建 Spring Boot
基础开发环境
File -> new -> Project
选择 jdk和自动生成目录结构的站点, 点击下一步
添加本地项目的坐标, 构建工具, 构建语言, 打包方式, 项目描述, 项目名称, 项目主包名, 点击下一步
选择需要的组件, 选择的组件会自动导入相关依赖, 忘记勾选也没有关系, 需要的时候手动在
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>
这里是自动生好成的 spring boot项目, 使用
git
管理的话, 记得配置一下.gitignore
文件, 这里使用的是gitignore
插件.
至此一个基础的 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
查看 DataSourceAutoConfiguration.java得知:
spring boot 2.0支持的连接池有: HikariCP
, tomcat-jdbc
, commons-dbcp2
, Generic
经测试, commons-dbcp
, tomcat-dbcp
已不再支持
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
Ctrl + Shift +Alt + /
, 选择 Registry
, 勾上 Compiler autoMake allow when app running
至此, 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&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