SpringBoot是搭建应用的手脚架,由Spring公司的核心团队在2013年开始研发、2014年4月发布第一个版本的全新开源的轻量级框架。它基于Spring4.0设计,不仅继承了Spring框架原有的优秀特性,而且还通过简化配置来进一步简化了Spring应用的整个搭建和开发过程。另外SpringBoot通过集成大量的框架使得依赖包的版本冲突等问题得到了很好的解决。
官方学习参考文档:
https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/
SpringBoot的核心思想:【约定优于配置】
Spring应用开发时的两个不好的地方:
复杂的配置
项目各种配置其实是开发时的损耗, 因为在思考 Spring 特性配置和解决业务问题之间需要进行思维切换,所以写配置挤占了写应用程序逻辑的时间。
一个混乱的依赖管理
项目的依赖管理也是件吃力不讨好的事情。决定项目里要用哪些库就已经够让人头痛的了,还要知道这些库的哪个版本和其他库不会有冲突,这难题实在太棘手。并且,依赖管理也是一种损耗,添加依赖不是写应用程序代码。一旦选错了依赖的版本,随之而来的不兼容问题毫无疑问会是生产力杀手。
然而SpringBoot让这一切成为过去!Spring Boot 简化了基于Spring的应用开发,只需要“run”就能创建一个独立的、生产级别的Spring应用。Spring Boot为Spring平台及第三方库提供开箱即用的设置(提供默认设置,存放默认配置的包就是启动器starter),这样就可以简单的开始。多数Spring Boot应用只需要很少的Spring配置。
可以使用SpringBoot创建java应用,并使用java –jar 启动它,就能得到一个生产级别的web工程。
快速创建独立的Spring应用。
提供固定的启动器依赖(启动器即Spring Boot提供的一个jar包)去简化组件配置,通过自己设置参数(.properties或.yml的配置文件),实现开箱即用(即快速使用)的效果。
自动配置Spring和其它有需要的第三方依赖。
提供了一些大型项目中常见的非功能性特性,如内嵌服务器(如tomcat、jetty、undertow)、安全、指标,健康检测、外部化配置等。
无需 XML 配置。
创建步骤:
配置pom.xml(重点)
<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.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.1.6.RELEASEversion>
parent>
<groupId>com.xxxgroupId>
<artifactId>springboot-demoartifactId>
<version>1.0-SNAPSHOTversion>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
dependencies>
project>
启动类就是带 @SpringBootApplication 注解的普通Java类【是运行SpringBoot项目的入口类】
核心代码:
/** SpringBoot启动类 */
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args){
// 运行Spring应用 (一个run方法就可以运行web项目)
SpringApplication.run(DemoApplication.class, args);
}
}
核心代码:
@RestController
public class QuickController {
@GetMapping("/quick")
public String quick(){
return "SpringBoot 从入门到精通!!";
}
}
方式一:
/** SpringBoot启动类 */
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args){
// 运行Spring应用 (一个run方法就可以运行web项目)
//SpringApplication.run(DemoApplication.class, args);
SpringApplication springApplication = new SpringApplication(DemoApplication.class);
// 设置banner为关闭模式
springApplication.setBannerMode(Banner.Mode.OFF);
springApplication.run(args);
}
}
方式二:
需要在resource目录下,提供application.properties属性文件,spring boot默认加载
# 设置banner模式为关闭
spring.main.banner-mode=off
可在resource目录下,创建banner.txt (默认加载)
${AnsiColor.BRIGHT_YELLOW}
/
// _ooOoo_ //
// o8888888o //
// 88" . "88 //
// (| ^_^ |) //
// O\ = /O //
// ____/`---'\____ //
// .' \\| |// `. //
// / \\||| : |||// \ //
// / _||||| -:- |||||- \ //
// | | \\\ - /// | | //
// | \_| ''\---/'' | | //
// \ .-\__ `-` ___/-. / //
// ___`. .' /--.--\ `. . ___ //
// ."" '< `.___\_<|>_/___.' >'"". //
// | | : `- \`.;`\ _ /`;.`/ - ` : | | //
// \ \ `-. \_ __\ /__ _/ .-` / / //
// ========`-.____`-.___\_____/___.-`____.-'======== //
// `=---=' //
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
// 佛祖保佑 永不宕机 永无BUG //
/
${AnsiColor.BRIGHT_GREEN}
Spring Boot Version: ${spring-boot.version}${spring-boot.formatted-version}
也在resource目录下,创建banner.jpg或banner.png (默认加载)
引入热部署依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
dependency>
热部署的作用:改了代码自动重启。
依赖过程:
继承spring-boot-starter-parent父级的作用:
使用SpringBoot之后,整合SpringMVC的WEB工程开发,变的无比简单,那些繁杂的配置都消失不见了
@SpringBootConfiguration 【作用: 定义配置类】
EnableAutoConfiguration 【作用: 启用自动配置】
注解
@EnableAutoConfiguration
,告诉SpringBoot基于所添加的依赖,去“猜测”想要如何配置Spring。比如引入了spring-boot-starter-web
,而这个启动器中帮我们添加了tomcat
、SpringMVC
的依赖。此时自动配置就知道是要开发一个web应用,所以就完成了web及SpringMVC的默认配置了
@ComponentScan 【作用: 组件扫描】
配置组件扫描的指令。提供了类似与
标签的作用
通过basePackageClasses或者basePackages属性来指定要扫描的包。如果没有指定这些属性,那么将从声明这个注解的类所在的包开始,扫描包及子包
自动配置实现流程
Spring Boot为所有的启动器提供了默认的属性配置,如果需要修改就必须要知道哪些属性是属于哪些启动器的默认配置。
配置步骤:
Spring Boot自动配置原理:
Spring Boot开发两个重点:
核心配置:
修改resources目录下的application.properties属性文件:
# 设置tomcat端口号
server.port=9001
# 设置项目的访问路径
server.servlet.context-path=/
yaml文件介绍:
核心配置:
在resources目录下,新建application.yml:
# 注意: 冒号后面必须有空格
# 覆盖自动配置类的默认属性
server:
port: 9002
servlet:
contextPath: /
# 定义自已项目中需要的属性
# 标量类型
my:
host: 127.0.0.1
port: 3306
# 对象类型
user:
name: 小明
age: 18
sex: 男
# 数组类型
address:
- 南城
- 东城
- 莞城
# 对象数组类型
users:
- name: 小红
age: 18
sex: 女
- name: 小明
age: 20
sex: 男
注意:
当application.properties与application.yml两个文件同时存在时,当属性名相同时application.properties中的属性会 覆盖 application.yml中的属性。
@ConfigurationProperties: java语言中的全部数据类型(PropController1.java)
/** 第一种方式: 注入属性 */
@RestController
@ConfigurationProperties(prefix = "my")
public class PropController1 {
private String host;
private int port;
private User user;
private String[] address;
private List<User> users;
@GetMapping("/test1")
public String test1(){
System.out.println("======test1=======");
System.out.println("host = " + host);
System.out.println("port = " + port);
System.out.println("user = " + user);
System.out.println("address = " + Arrays.toString(address));
System.out.println("users = " + users);
return "test1方法,访问成功!";
}
/** 注入的属性必须提供setter方法 */
public void setHost(String host) {
this.host = host;
}
public void setPort(int port) {
this.port = port;
}
public void setUser(User user) {
this.user = user;
}
public void setAddress(String[] address) {
this.address = address;
}
public void setUsers(List<User> users) {
this.users = users;
}
}
定义User.java实体类:
public class User {
private String name;
private int age;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
}
注意:
@Value: 基本数据类型和String (PropController2.java)
/** 第二种方式: 注入属性 */
@RestController
@ConfigurationProperties(prefix = "my")
public class PropController2 {
@Value("${my.host}")
private String host;
@Value("${my.port}")
private int port;
private User user;
private String[] address;
private List<User> users;
@GetMapping("/test2")
public String test2(){
System.out.println("======test2=======");
System.out.println("host = " + host);
System.out.println("port = " + port);
System.out.println("user = " + user);
System.out.println("address = " + Arrays.toString(address));
System.out.println("users = " + users);
return "test2方法,访问成功!";
}
public void setUser(User user) {
this.user = user;
}
public void setAddress(String[] address) {
this.address = address;
}
public void setUsers(List<User> users) {
this.users = users;
}
}
注意:
将需要注入的属性定义成一个属性类,当用到的时候需要 启用配置属性。这样做属性类就可以重复使用。
定义属性类:
@ConfigurationProperties(prefix = "my")
public class UserProperties {
private String host;
private int port;
private User user;
private String[] address;
private List<User> users;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String[] getAddress() {
return address;
}
public void setAddress(String[] address) {
this.address = address;
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
}
启用配置属性:
/** 第三种方式: 注入属性 */
@RestController
@EnableConfigurationProperties(UserProperties.class)
public class PropController3 {
@Autowired(required = false)
private UserProperties userProperties;
@GetMapping("/test3")
public String test3(){
System.out.println("======test3======");
System.out.println(userProperties.getHost());
System.out.println(userProperties.getPort());
System.out.println(userProperties.getUser());
System.out.println(userProperties.getAddress());
System.out.println(userProperties.getUsers());
return "test3方法,访问成功!";
}
}
注意:
第二步: 引入lombok依赖
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<scope>providedscope>
dependency>
第三步: lombok注解介绍
第四步: 在实体类上加注解
@ToString // toString
@Data // getter、setter、toString、equals、hashCode
@AllArgsConstructor // 全参构造器
@NoArgsConstructor // 无参构造器
public class User {
private String name;
private int age;
private String sex;
}
整合SpringMVC只需要引入: spring-boot-starter-web启动器依赖。
说明: 虽然默认配置已经可以使用SpringMVC,不过有时候需要进行自定义配置。
# 配置日志
logging:
level:
com.xxx: debug
org.springframework: debug
说明:
控制器中加入日志:
@RestController
@Slf4j // 日志注解
public class LogController {
@GetMapping("/log")
public String log(){
log.debug("====debug====");
log.info("====info====");
log.warn("====warn====");
log.error("====error====");
return "log....";
}
}
操作步骤:
第一步: 先找到资源属性类(ResourceProperties.java),它有默认的静态资源存储路径。
默认的静态资源访问路径有四个:
说明: 只要静态资源放在这些目录中任何一个,SpringMVC都会帮我们处理。
参考官方文档:
如果你想要保持Spring Boot 的一些默认MVC特征,同时又想自定义一些MVC配置(包括:拦截器、格式化器、视图控制器、消息转换器 等等),你应该让一个类实现
WebMvcConfigurer
,并且添加@Configuration
注解,但是千万不要加@EnableWebMvc
注解。如果你想要自定义HandlerMapping
、HandlerAdapter
、ExceptionResolver
等组件,你可以创建一个WebMvcRegistrationsAdapter
实例 来提供以上组件。如果你想要完全自定义SpringMVC,不保留SpringBoot提供的一切特征,你可以自己定义类并且添加
@Configuration
注解和@EnableWebMvc
注解
通过实现WebMvcConfigurer
接口,添加@Configuration
注解来实现自定义SpringMvc相关配置。
实现步骤:
第一步: 自定义拦截器实现HandlerInterceptor接口
/** 定义拦截器 */
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
/** 前置处理 */
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
log.debug("== preHandle 方法执行! ==");
return true;
}
/** 后置处理 */
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {
log.debug("== postHandle 方法执行! ==");
}
/** 视图渲染之后 */
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler, Exception ex) throws Exception {
log.debug("== afterCompletion 方法执行! ==");
}
}
第二步: 自定义配置类实现WebMvcConfigurer接口,注册拦截器
@Configuration
public class MvcConfiguration implements WebMvcConfigurer {
/** 重写接口中的addInterceptors方法,添加自定义拦截器 */
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 添加拦截器,通过addPathPatterns来添加拦截路径
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**");
}
}
起步依赖:
<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.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.1.6.RELEASEversion>
parent>
<groupId>com.xxxgroupId>
<artifactId>springbootartifactId>
<version>1.0-SNAPSHOTversion>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<scope>providedscope>
dependency>
dependencies>
project>
创建启动类:
/** 启动类 */
@SpringBootApplication
public class HighApplication {
public static void main(String[] args){
// 运行spring应用
SpringApplication.run(HighApplication.class, args);
}
}
整合步骤:
引入依赖【jdbc启动器 与 数据库驱动】
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jdbcartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.47version>
dependency>
SpringBoot项目是通过注解来控制事务,是@Transactional
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/springboot_db
username: root
password: root
SpringBoot官方并没有提供Mybatis的启动器,不过Mybatis自己实现了。
引入mybatis启动器依赖(它依赖了jdbc启动器,jdbc启动器可以删除)
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>2.1.0version>
dependency>
mybatis:
# 配置类型别名包扫描
type-aliases-package: com.xxx.springboot.pojo
# sql语句映射文件路径
mapper-locations:
- classpath:mappers/*.xml
# 驼峰映射
configuration:
map-underscore-to-camel-case: true
# 配置日志
logging:
level:
com.xxx: debug
用户实体(User)
@Data
public class User{
// 用户id
private Long id;
// 用户名
private String userName;
// 密码
private String password;
// 姓名
private String name;
// 年龄
private Integer age;
// 性别 1: 男 2: 女
private Short sex;
// 出生日期
private Date birthday;
// 备注
private String note;
// 创建时间
private Date created;
// 修改时间
private Date updated;
}
数据访问接口(UserMapper)
方式一 (@Mapper注解)
@Mapper // 声明数据访问接口,产生代理对象
public interface UserMapper {
// 查询全部用户
List<User> findAll();
}
方式二 (@MapperScan注解)
public interface UserMapper {
// 查询全部用户
List<User> findAll();
}
在启动类上添加数据访问接口包扫描:
/** 启动类 */
@SpringBootApplication
// 数据访问接口包扫描
@MapperScan(basePackages = {"com.xxx.springboot.mapper"})
public class HighApplication {
public static void main(String[] args){
// 运行spring应用
SpringApplication.run(HighApplication.class, args);
}
}
说明:这种方式的好处是,不用给每一个Mapper都添加注解。采用@MapperScan包扫描方式只需要添加一次注解。
定义SQL语句(UserMapper.xml)
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xxx.springboot.mapper.UserMapper">
<select id="findAll" resultType="User">
SELECT * FROM tb_user
select>
mapper>
业务层 (UserService)
@Service
@Transactional
public class UserService {
@Autowired(required = false)
private UserMapper userMapper;
// 查询全部用户
public List<User> findAll(){
return userMapper.findAll();
}
}
控制器 (UserController)
@RestController
public class UserController {
@Autowired
private UserService userService;
// 查询全部用户
@GetMapping("/findAll")
public List<User> findAll(){
return userService.findAll();
}
}
通用Mapper简化了单表的CRUD,对于单表CRUD,不用写SQL语句,完全面向对象方式操作数据库,通用Mapper也为自己的插件编写了Spring Boot启动器。
引入通用Mapper启动器依赖(它依集成了mybatis,mybatis启动器可以删除)
<dependency>
<groupId>tk.mybatisgroupId>
<artifactId>mapper-spring-boot-starterartifactId>
<version>2.1.5version>
dependency>
注意: 引入了通用Mapper的启动器,它已包含了Mybatis官方启动器的功能,因此需要删除对官方Mybatis启动器的依赖。
在实体类上加JPA注解 (User)
@Data
@Table(name = "tb_user")
public class User{
// 用户id
@Id // 主键
@KeySql(useGeneratedKeys = true) // 开启自增主键返回功能
private Long id;
// 用户名
private String userName;
// 密码
private String password;
// 姓名
private String name;
// 年龄
private Integer age;
// 性别 1: 男 2: 女
private Short sex;
// 出生日期
private Date birthday;
// 备注
private String note;
// 创建时间
private Date created;
// 修改时间
private Date updated;
}
数据访问接口需要继承Mapper接口 (UserMapper)
//@Mapper // 声明数据访问接口,产生代理对象
public interface UserMapper extends Mapper<User> {
}
修改业务层 (UserService)
@Service
@Transactional
public class UserService {
@Autowired(required = false)
private UserMapper userMapper;
// 查询全部用户
public List<User> findAll(){
return userMapper.selectAll();
}
}
引入test启动器依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
编写测试类 (UserServiceTest)
// 运行主类
@RunWith(SpringRunner.class)
// 如果测试类在启动类的同级目录或者子目录下可以省略指定启动类
//@SpringBootTest(classes = {HighApplication.class})
@SpringBootTest
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void findAll(){
List<User> users = userService.findAll();
System.out.println(users);
}
}
引入Redis启动器依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
# 配置Redis
spring:
redis:
host: localhost # 主机
port: 6379 # 端口
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTemplateTest {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void redisTest(){
// 设置值
redisTemplate.opsForValue().set("name", "admin");
// 获取值
Object name = redisTemplate.opsForValue().get("name");
System.out.println("name = " + name);
// 删除值
redisTemplate.delete("name");
}
}
package
;操作步骤
第一步: 引入Spring Boot打包插件
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
第二步: 执行命令
# 清理、打包
mvn clean package
# 清理、打包 跳过测试
mvn clean package -Dmaven.test.skip=true
第三步: 运行
java -jar xxx.jar
第四步: 浏览器访问 http://localhost:8080/findAll
操作步骤
第一步: 修改pom.xml
<packaging>warpackaging>
第二步: 排除springboot自带的tomcat
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-tomcatartifactId>
<scope>providedscope>
dependency>
注意: spring-boot-starter-tomcat 是原来被传递过来的依赖,默认会打到包里,所以需要配置tomcat启动器,这样就会排除spring-boot-starter-web中依赖过来的tomcat启动器,并指定依赖范围为provided,这样tomcat相关的jar就不会打包到war里了。
目的: 用自己tomcat,不用它内嵌的tomcat,这样内嵌的tomcat相关jar包就不需要。
第三步: 自定义Web应用入口类继承SpringBootServletInitializer(相当于web.xml)
/** web应用入口 */
public class WebServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
// 设置启动类
builder.sources(HighApplication.class);
// 返回spring应用构建对象
return builder;
}
}
第四步: 在pom.xml修改工程的名称为ROOT
<build>
<finalName>ROOTfinalName>
build>
说明: ROOT是tomcat的默认工程名,也是唯一一个不需要加工程访问的目录,所以打包的时候用finalName指定的名字打包就直接生成的WAR包就是ROOT.war
第五步: 部署项目ROOT.war
安装JDK1.8环境
安装Tomcat 把 ROOT.war部署到webapps下即可
启动Tomcat,bin/startup.bat
即可,会自动解压ROOT.war
访问 http://localhost:8080/findAll