0.学习目标
- 了解SpringBoot的作用
- 掌握springboot属性注入
- 了解SpringBoot自动配置原理
- 掌握yml文件的写法
- 掌握SpringBoot的基本使用
1. 了解SpringBoot
1.1.什么是SpringBoot
SpringBoot是Spring项目中的一个子工程,与我们所熟知的Spring-framework 同属于spring的产品:
SpringBoot是一个可以帮助我们快速搭建spring项目的框架。它尽可能的帮我们减少Spring应用一切xml配置,让我们关注业务开发而非项目环境配置,所以 SpringBoot也可以说是一个服务于框架的框架。
1.2.为什么要学习SpringBoot
java一直被人诟病的一点就是臃肿、麻烦。当我们还在辛苦的搭建项目时,可能Python程序员已经把功能写好了,究其原因主要有两点:
-
复杂的配置
项目各种配置其实是开发时的损耗, 因为在思考 Spring 特性配置和解决业务问题之间需要进行思维切换,所以写配置挤占了写应用程序逻辑的时间。
-
一个是混乱的依赖管理
项目的依赖管理也是件吃力不讨好的事情。决定项目里要用哪些库就已经够让人头痛的了,你还要知道这些库的哪个版本和其他库不会有冲突,这难题实在太棘手。并且,依赖管理也是一种损耗,添加依赖不是写应用程序代码。一旦选错了依赖的版本,随之而来的不兼容问题毫无疑问会是生产力杀手。
而SpringBoot让这一切成为过去!
2.快速入门
接下来,我们就来利用SpringBoot搭建一个web工程,体会一下SpringBoot的魅力所在!
2.1.创建工程
我们先新建一个空的工程:
项目信息:
地址:
2.2.添加依赖
SpringBoot提供了一个名为spring-boot-starter-parent的工程,里面已经对各种常用依赖(并非全部)的版本进行了管理,我们的项目需要以这个项目为父工程,这样我们就不用操心依赖的版本问题了,需要什么依赖,直接引入坐标即可!
2.2.1.添加父工程坐标
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
2.2.2.添加web启动器
为了让SpringBoot帮我们完成各种自动配置,我们必须引入SpringBoot提供的自动配置依赖,我们称为启动器
。因为我们是web项目,这里我们引入web启动器:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
需要注意的是,我们并没有在这里指定版本信息。因为SpringBoot的父工程已经对版本进行了管理了。
这个时候,我们会发现项目中多出了大量的依赖:
这些都是SpringBoot根据spring-boot-starter-web这个依赖自动引入的,而且所有的版本都已经管理好,不会出现冲突。
2.2.3.管理jdk版本
如果我们想要修改SpringBoot项目的jdk版本,只需要简单的添加以下属性即可,如果没有需求,则不添加。
<properties>
<java.version>1.8</java.version>
</properties>
2.2.4.完整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.itcast.springboot</groupId>
<artifactId>hello-springboot</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
2.3.启动类
Spring Boot项目通过main函数即可启动,我们需要创建一个启动类,该类名随意,一般以Application结尾,我们这叫StartApplication.java,然后编写main函数:
@SpringBootApplication
public class StartApplication {
public static void main(String[] args) {
SpringApplication.run(StartApplication.class, args);
}
}
2.4.编写controller
接下来,我们就可以像以前那样开发SpringMVC的项目了!
我们编写一个controller:
代码:
package cn.itcast.springboot.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(){
return "hello springboot!";
}
}
2.5.启动测试
接下来,我们运行main函数,查看控制台,可以看到监听的端口信息:
- 1)监听的端口是8080
- 2)SpringMVC的映射路径是:/
- 3)
/hello
路径已经映射到了HelloController
中的hello()
方法
打开页面访问:http://localhost:8080/hello
3.SpringBoot属性注入
在入门案例中,我们没有任何的配置,就可以实现一个SpringMVC的项目了,快速、高效!
但是有些业务参数是不可避免需要配置的,比如数据库连接参数,redis服务器地址等。当我们需要在代码里使用到这些参数时,就需要注入到代码当中使用,也就是读取配置文件的属性然后注入到java对象中。
在SpringBoot中,提供了一种新的属性注入方式,支持各种java基本数据类型及复杂类型的注入。
SpringBoot启动的时候默认会读取的属性文件名为application.properties或者application.yml的配置文件。
3.1 注入方式1
如果我们需要将配置文件的数据库连接参数,读取到java对象中,可以用@Component和@ConfigurationProperties注解实现。
1)新建application.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/springboot
jdbc.username=root
jdbc.password=123456
- 新建一个类,用来进行属性绑定并注入:
@Component
@ConfigurationProperties(prefix = "jdbc")
public class JdbcProperties {
private String url;
private String driverClassName;
private String username;
private String password;
// ... 略
// getters 和 setters
}
- 在类上通过@ConfigurationProperties注解声明当前类为属性读取类,这个注解并不会初始化该类对象到IOC中
prefix="jdbc"
读取属性文件中,前缀为jdbc的值。- @Component 通过该注解将当前类JdbcProperties初始化到IOC中
- 在类上定义各个属性,名称建议与属性文件中
jdbc.
后面部分一致
3)JdbcProperties已被初始化到IOC中,我们就可以通过spring的bean注入使用了
3.2 注入方式2
比如之前的系统中需要我们配置一个数据源,它需要数据库参数,以前会这么配置。
<!-- 配置连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
在Spring3.0开始,Spring官方就已经开始推荐使用java配置来代替传统的xml配置了,而现在springboot又该怎么做呢?
接下来介绍另外一种方式,这种方式是springboot源码中用的最多的一种。就是使用@ConfigurationProperties + @EnableConfigurationProperties完成。
1)导入数据源maven坐标
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.6</version>
</dependency>
2)新建一个类,用来进行属性注入:
@ConfigurationProperties(prefix = "jdbc")
public class DataSourceProperties {
private String url;
private String driverClassName;
private String username;
private String password;
// ... 略
// getters 和 setters
}
-
在类上通过@ConfigurationProperties注解声明当前类为属性读取类,这个注解并不会初始化该类对象到IOC中
-
prefix="jdbc"
读取属性文件中,前缀为jdbc的值。 -
在类上定义各个属性,名称建议与属性文件中
jdbc.
后面部分一致
2)在DataSourceConfig中使用这个DataSourceProperties属性读取类对象:
/**
* 通过EnableConfigurationProperties声明要使用`DataSourceProperties`这个类的对象
*/
@Configuration
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceConfig {
/**
* 通过bean注解实例化DataSource对象
* @param properties
* @return
*/
@Bean
public DataSource dataSource(DataSourceProperties properties) {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setUsername(properties.getUserName());
druidDataSource.setDriverClassName(properties.getDriverClassName());
druidDataSource.setUrl(properties.getUrl());
druidDataSource.setPassword(properties.getPassword());
return druidDataSource;
}
}
-
@Configuration 标明JdbcConfig是一个配置类,被注解的类内部一般包含一个或多个被@Bean注解的方法。相当于把该类作为spring的xml配置文件中的
<beans></beans>
。 -
通过
@EnableConfigurationProperties(DataSourceProperties.class)
来声明要使用DataSourceProperties
这个类并初始化该类对象。 -
@Bean注解的方法,这些方法将会被spring进行扫描,并初始化到Spring容器,bean的id为方法名。
@Bean注解主要用在@Configuration注解的类里,也可以用在@Component注解的类里。@Bean等价于
3)测试结果:
总结:
方式1:@Component和@ConfigurationProperties注解实现。
方式2:@ConfigurationProperties + @EnableConfigurationProperties注解实现。
4.Yml配置文件
配置文件除了可以使用application.properties类型,还可以使用后缀名为:.yml或者.yaml的类型,也就是:application.yml或者application.yaml,企业中使用yml的偏多。
配置文件的作用:修改SpringBoot自动配置的默认值;SpringBoot在底层都给我们自动配置好
基本格式:k:(空格)v
表示一对键值对(空格必须有)。以空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一个层级的 ,且属性和值也是大小写敏感;如:
jdbc:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/heima
username: root
password: 123
相当于以下application.properties的写法
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/leyou
jdbc.username=root
jdbc.password=123
如果两个配置文件都有,会把两个文件的配置合并,如果有重复属性,以Properties文件中的为准。
4.1 字面量:普通值(数字/字符串/布尔)
k: v:字面直接来写,字符串默认不用加上单引号或者双引号.
“”:不会转义字符串里面的特殊字符,特殊字符会作为本身想表示的意思
如 :name: “zhangsan \n lisi”:输出;zhangsan 换行 lisi
‘’:会转义特殊字符,特殊字符最终只是一个普通的字符串数据
如:name: ‘zhangsan \n lisi’:输出;zhangsan \n lisi
4.2 对象/Map:
k: v:在下一行来写对象的属性和值的关系;注意缩进
对象还是k: v的方式
friend:
lastName: zhangsan
age: 20
行内写法:
friend: {lastName: zhangsan,age: 18}
4.3 数组/List:
用- 值表示数组中的一个元素
pets:
‐ cat
‐ dog
‐ pig
行内写法
pets: [cat,dog,pig]
4.4 案例
我们通过一个人的属性那例举所有类型的写法。
步骤:
1)在application.yml文件添加以person开头的配置:
person:
name: 小姐姐dev
age: 18
marry: false
hobby:
- 吃鸡
- 王者荣耀
- 看片
cat:
name: 小花
age: 3
sanwei: {height: 175cm ,weight: 55kg,bust: 54cm}
```
2)新建PersonProperties.java
```java
@Component
@ConfigurationProperties(prefix = "person")
public class PersonProperties {
private String name;
private Integer age;
private Boolean marry;
private Cat cat;
private List<String> hobby;//String[] 也可以
private Map sanwei;
//get set 方法 .....
}
- 简单修改HelloController后,启动调试:
可以看到,注入成功了!
5.自动配置原理(了解)
使用SpringBoot之后,一个整合了SpringMVC的WEB工程开发,变的无比简单,那些繁杂的配置都消失不见了,这是如何做到的?
我们回顾下之前搭建springmvc环境的主要操作:
1.新建web.xml,并配置前端控制器DispatchServlet
2.新建spring-mvc.xml,并配置处理器映射器RequestMappingHandlerMapping、处理器适配器RequestMappingHandlerAdapter、视图解析器InternalResourceViewResolver等。
结合springmvc实现原理及流程,我们可以得出搭建springmvc环境,其实说白了就是配置springmvc核心的4大组件,spring会初始化这4大组件对象到IOC容器中,于是乎我们就可以愉快的使用springmvc了。
但是,刚刚的入门程序中,我们并没有配置这4大核心组件,springmvc环境就运行起来了,而springmvc运行又必须要依赖这4大核心组件对象。那么这个配置动作谁替我们做了呢?答案就是springboot。接下来我们就看看springboot是如何帮我们自动配置springmvc的4大核心组件,帮我们搭建springmvc环境的。这就涉及到springboot自动配置原理了。
一切魔力的开始,都是从我们的启动类来的,所以我们来看下启动类:
我们发现特别的地方有两个:
- 注解:@SpringBootApplication
- run方法:SpringApplication.run()
结合springboot自动配置流程图,我们分别来研究这两个部分:
5.1 核心注解
点击@SpringBootApplication进入,查看源码:
发现@SpringBootApplication依赖于3个重点注解:
- @SpringBootConfiguration
- @EnableAutoConfiguration
- @ComponentScan
接下来我们一一对这3个注解的作用进行介绍。
5.1.1 @SpringBootConfiguration
@SpringBootConfiguration 注解的作用是标明当前类是一个springboot的配置类 ,它依赖@Configuration注解。而Spring会扫描到添加了@Configuration
的类,并且读取其中的配置信息。项目中只能有一个@SpringBootConfiguration注解。所以一般我们无需自己添加。
5.1.2 @EnableAutoConfiguration
@EnableAutoConfiguration 通过@import注解导入符合规则的bean定义,导的是springboot-configure-autoConfig.jar /META-INF/spring.factories中 ,以EnableAutoConfiguration 开头的bean定义。
spring.factories定义的以EnableAutoConfiguration 开头的类都是各个第三方组件(如:pringmvc,mybatis等)的自动配置类。这些配置是否生效,取决于我们是否引入了对应库所需的依赖,如果有那么默认配置就会生效。
所以,我们使用SpringBoot构建一个项目,只需要引入所需框架的依赖,配置就可以交给SpringBoot处理了。除非你不希望使用SpringBoot的默认配置,它也提供了自定义配置的入口。
5.1.3 @ComponentScan
类似与<context:component-scan>
标签的作用,它的功能其实就是自动扫描并加载符合条件的组件(比如@Component和@Repository等)或者bean定义,最终将这些bean定义加载到IoC容器中。
我们可以通过basePackages等属性来细粒度的定制@ComponentScan自动扫描的范围,如果不指定,则默认会从声明@ComponentScan类所在的package进行扫描。
注:@SpringBootApplication注解声明的类就是main函数所在的启动类,所以SpringBoot的启动类最好是放在root package下,因为默认不指定basePackages。
5.2 默认配置原理
5.2.1 spring.factories
@EnableAutoConfiguration注解通过@import注解导入AutoConfigurationImportSelector类process方法中指定规则的bean定义并初始化,其实就是springboot-configure-autoConfig.jar /META-INF/spring.factories文件中以EnableAutoConfiguration 开头的bean定义:
springboot运行的时候会调用AutoConfigurationImportSelector类的process方法:
这里可以发现会通过SpringFactoriesLoader.loadFactoryNames尝试加载一些configurations,继续跟进loadFactoryNames方法:
发现此处会先从缓存中获取内容,缓存没有,就利用类加载器加载META-INF/spring.factories`文件。我们知道,ClassLoader默认是从classpath下读取文件,因此,SpringBoot会在初始化的时候,加载所有classpath:META-INF/spring.factories文件,包括jar包当中,然后放到缓存cache中。
而在Spring的一个依赖包:spring-boot-autoconfigure中,就有这样的文件:
以后我们引入的任何第三方启动器,只要实现自动配置,也都会有类似文件。
5.2.2 默认配置类
我们打开刚才的spring.factories文件:
可以发现以EnableAutoConfiguration接口为key的一系列配置,key所对应的值,就是所有的自动配置类,可以在当前的jar包中找到这些自动配置类:
非常多,几乎涵盖了现在主流的开源框架,例如:
- redis
- jms
- amqp
- jdbc
- jackson
- mongodb
- jpa
- solr
- elasticsearch
… 等等
我们来看一个我们熟悉的,例如SpringMVC,查看mvc 的自动配置类:
打开WebMvcAutoConfiguration:
我们看到这个类上的4个注解:
-
@Configuration
:声明这个类是一个配置类 -
@ConditionalOnWebApplication(type = Type.SERVLET)
ConditionalOn,翻译就是在某个条件下,此处就是满足项目的类是是Type.SERVLET类型,也就是一个普通web工程,显然我们就是
-
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
这里的条件是OnClass,也就是满足以下类存在:Servlet、DispatcherServlet、WebMvcConfigurer,其中Servlet只要引入了tomcat依赖自然会有,后两个需要引入SpringMVC才会有。这里就是判断你是否引入了相关依赖,引入依赖后该条件成立,当前类的配置才会生效!
-
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
这个条件与上面不同,OnMissingBean,是说环境中没有指定的Bean这个才生效。其实这就是自定义配置的入口,也就是说,如果我们自己配置了一个WebMVCConfigurationSupport的类,那么这个默认配置就会失效!
接着,我们查看该类中定义了什么:
视图解析器:
处理器适配器(HandlerAdapter):
处理器映射器:
前段控制器:
我们发现WebMvcAutoConfiguration.class定义了springMVC的五大核心组件的初始化方法,之前这五大核心组件是通过xml文件由程序员手动配置的。
5.2.3 默认配置属性
另外,这些默认配置的属性来自哪里呢?
我们看到,这里通过@EnableAutoConfiguration注解引入了两个属性:WebMvcProperties和ResourceProperties。这不正是SpringBoot的属性注入玩法嘛。
我们查看这两个属性类:
找到了内部资源视图解析器的prefix和suffix属性。
ResourceProperties中主要定义了静态资源(.js,.html,.css等)的路径:
如果我们要覆盖这些默认属性,只需要在application.properties中定义与其前缀prefix和字段名一致的属性即可。
5.3.总结
SpringBoot为我们提供了默认配置,而默认配置生效的步骤:
- @EnableAutoConfiguration注解会去寻找
META-INF/spring.factories
文件,读取其中以EnableAutoConfiguration
为key的所有类的名称,这些类就是提前写好的自动配置类 - 这些类都声明了
@Configuration
注解,并且通过@Bean
注解提前配置了我们所需要的一切实例。完成自动配置 - 但是,这些配置不一定生效,因为有
@ConditionalOn
注解,满足一定条件才会生效。比如条件之一:是一些相关的类要存在 - 类要存在,我们只需要引入了相关依赖(启动器),依赖有了条件成立,自动配置生效。
- 我们还可以通过配置application.yml文件,来覆盖自动配置中的属性
springboot 启动的时候会扫描所有jar包下/META-INF/spring.factories中配置的bean定义,然后初始化各个类的对象,(包括以EnableAutoConfiguration开头的类),而自动配置类里面定义了该组件运行起来所需要的核心对象的初始化方法。也就是说自动配置类对象初始化到IoC中的同时会把几个核心组件对象初始化。而自动配置类对象是否初始化,是要相应的依赖类存在,而依赖类否存在是通过maven导入相应的jar包
所以,我们如果不想配置,只需要引入依赖即可,而依赖版本我们也不用操心,因为只要引入了SpringBoot提供的stater(启动器),就会自动管理依赖及版本了。
6.SpringBoot实践
接下来,我们来看看如何用SpringBoot来玩转以前的SSM,我们会在数据库引入一张用户表tb_user和实体类User
tb_user:
详见课前笔记中:《tb_user.sql》文件。
user实体类:
package cn.itcast.springboot.pojo;
import java.util.Date;
public class User {
/**
* id
*/
private Long id;
/**
* 用户名
*/
private String userName;
/**
* 密码
*/
private String password;
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private Integer age;
/**
* 性别,1男性,2女性
*/
private Integer sex;
/**
* 出生日期
*/
private Date birthday;
/**
* 创建时间
*/
private Date created;
/**
* 更新时间
*/
private Date updated;
/**
* 备注
*/
private String note;
}
6.1 Lombok
我们编写pojo时,经常需要编写构造函数和gettersetter方法,属性多的时候,就非常浪费时间,使用lombok插件可以解决这个问题:
在idea中安装lombok插件:
需要在maven中引入依赖:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
然后可以在Bean上使用:
@Data :自动提供getter和setter、hashCode、equals、toString等方法
@Getter:自动提供getter方法
@Setter:自动提供setter方法
@Slf4j:自动在bean中提供log变量,其实用的是slf4j的日志功能。
@AllArgsConstructor 自动提供全参构造器
@NoArgsConstructor 自动提供无参构造器
例如,我们在javabean上加@Data,那么就可以getter和setter等方法的编写,lombok插件会帮我们自动生成:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IdLXifkh-1577157008054)(assets/1559009874064.png)]
6.2 整合SpringMVC
虽然默认配置已经可以使用SpringMVC了,不过我们有时候需要进行自定义配置。
日志级别控制:
logging:
level:
cn.itcast: debug
org.springframework: debug
6.2.1 修改端口
查看SpringBoot的全局属性可知,端口通过以下方式配置:
# 映射端口
server:
port: 80
重启服务后测试:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e370w3kc-1577157008055)(assets/1559010949513.png)]
6.2.2 访问静态资源
现在,我们的项目是一个jar工程,那么就没有webapp,我们的静态资源该放哪里呢?
回顾我们上面看的源码,有一个叫做ResourceProperties的类,里面就定义了静态资源的默认查找路径:
默认的静态资源路径为:
- classpath:/META-INF/resources/
- classpath:/resources/
- classpath:/static/
- classpath:/public
只要静态资源放在这些目录中任何一个,SpringMVC都会帮我们处理。
我们习惯会把静态资源放在classpath:/static/
目录下。我们创建目录,并且添加一些静态资源:
重启项目后测试:
6.2.3 添加拦截器
拦截器也是我们经常需要使用的,在SpringBoot中该如何配置呢?
拦截器不是一个普通属性,而是一个类,所以就要用到java配置方式了。在SpringBoot官方文档中有这么一段说明:
If you want to keep Spring Boot MVC features and you want to add additional MVC configuration (interceptors, formatters, view controllers, and other features), you can add your own
@Configuration
class of typeWebMvcConfigurer
but without@EnableWebMvc
. If you wish to provide custom instances ofRequestMappingHandlerMapping
,RequestMappingHandlerAdapter
, orExceptionHandlerExceptionResolver
, you can declare aWebMvcRegistrationsAdapter
instance to provide such components.If you want to take complete control of Spring MVC, you can add your own
@Configuration
annotated with@EnableWebMvc
.
翻译:
如果你想要保持Spring Boot 的一些默认MVC特征,同时又想自定义一些MVC配置(包括:拦截器,格式化器, 视图控制器、消息转换器 等等),你应该让一个类实现
WebMvcConfigurer
,并且添加@Configuration
注解,但是千万不要加@EnableWebMvc
注解。如果你想要自定义HandlerMapping
、HandlerAdapter
、ExceptionResolver
等组件,你可以创建一个WebMvcRegistrationsAdapter
实例 来提供以上组件。如果你想要完全自定义SpringMVC,不保留SpringBoot提供的一切特征,你可以自己定义类并且添加
@Configuration
注解和@EnableWebMvc
注解
总结:通过实现WebMvcConfigurer
并添加@Configuration
注解来实现自定义部分SpringMvc配置。
首先我们定义一个拦截器:
package cn.itcast.springboot.interceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 定义拦截器
*/
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.debug(" preHandle is run !");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
log.debug(" postHandle is run !");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
log.debug(" afterCompletion is run !");
}
}
然后,我们定义配置类,注册拦截器:
package cn.itcast.springboot.config;
import cn.itcast.springboot.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Created by fangqyou on 2019/5/11.
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
/**
* 通过@Bean注解,将我们定义的拦截器注册到Spring容器
* @return
*/
@Bean
public LoginInterceptor loginInterceptor(){
return new LoginInterceptor();
}
/**
* 重写接口中的addInterceptors方法,添加自定义拦截器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 通过registry来注册拦截器,通过addPathPatterns来添加拦截路径
registry.addInterceptor(loginInterceptor()).addPathPatterns("/*");
}
}
接下来运行并查看日志:
你会发现日志中什么都没有,因为我们记录的log级别是debug,默认是显示info以上,我们需要进行配置。
SpringBoot通过logging.level.*=debug
来配置日志级别,*填写包名
# 设置com.itcast包的日志级别为debug
logging:
level:
cn.itcast: debug
再次运行查看,拦截器已经生效:
6.3 整合mybatis
6.3.1 mybatis
SpringBoot官方并没有提供Mybatis的启动器,不过Mybatis官网自己实现了:
1)添加maven坐标
<!--mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!-- mysql 数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
- 添加可选配置:
mybatis:
configuration:
#查看运行Sql
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# mybatis 别名扫描
type-aliases-package: cn.itcast.springboot.pojo
# mapper.xml文件位置,如果没有映射文件,请注释掉
mapper-locations: classpath:mappers/*.xml
- 配置数据库连接参数(可选)
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.12.128:3306/springboot
username: root
password: root
- 在resource下新建mappers文件夹,且定义UserMapper.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.itcast.springboot.mapper.UserMapper">
<select id="queryById" parameterType="long" resultType="cn.itcast.springboot.pojo.User">
SELECT id,user_name userName,password FROM tb_user WHERE id=#{id}
</select>
</mapper>
5)新建UserMapper.java
需要注意,这里没有配置mapper接口扫描包,因此我们需要给每一个Mapper接口添加@Mapper
注解,才能被识别。
@Mapper
public interface UserMapper {
User queryById(Long id);
}
或者,我们也可以不加注解,而是在启动类上添加扫描包注解(推荐):
@SpringBootApplication
@MapperScan("cn.itcast.springboot.mapper")
public class Application {
public static void main(String[] args) {
// 启动代码
SpringApplication.run(Application.class, args);
}
}
以下代码示例中,我们将采用@MapperScan扫描方式进行。
- 新建UserSerice.java
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User queryById(Long id) {
return userMapper.queryById(id);;
}
}
- 修改controller
package cn.itcast.springboot.controller;
import cn.itcast.springboot.config.PersonProperties;
import cn.itcast.springboot.pojo.User;
import cn.itcast.springboot.service.UserService;
import org.omg.CORBA.PRIVATE_MEMBER;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import sun.dc.pr.PRError;
import javax.sql.DataSource;
@RestController
public class HelloController {
@Autowired
private DataSource dataSource;
@Autowired
private PersonProperties personProperties;
@Autowired
private UserService userService;
@GetMapping("/hello")
public String hello() {
System.out.println(personProperties);
return "hello springboot!";
}
@GetMapping("/hello/{id}")
public User hello(@PathVariable Long id) {
User user = userService.queryById(id);
return user;
}
}
- 在浏览器输入<http://localhost/hello/1,返回如下:
控制台输出:
6.3.2 通用mapper
- 添加通用Mapper的maven坐标
通用Mapper的作者也为自己的插件编写了启动器,我们直接引入即可:
<!-- 通用mapper -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
注意:一旦引入了通用Mapper的启动器,会覆盖Mybatis官方启动器的功能,因此建议移除对官方Mybatis启动器的依赖。
- 修改UserMapper.java
无需任何配置就可以使用了。如果有特殊需要,可以到通用mapper官网查看:https://github.com/abel533/Mapper/wiki/3.config
public interface UserMapper extends Mapper<User>{
}
3)修改启动类
我们需要把启动类上的@MapperScan注解修改为通用mapper中自带的tk.mybatis.spring.annotation.包下的
package cn.itcast.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tk.mybatis.spring.annotation.MapperScan;
/**
* Created by fangqyou on 2019/4/30.
*/
@SpringBootApplication
@MapperScan("cn.itcast.springboot.mapper")
public class SatartApplication {
public static void main(String[] args) {
SpringApplication.run(SatartApplication.class, args);
}
}
4)在实体类User.java上加JPA注解:
@Data
@Table(name = "tb_user")
public class User{
@Id
@KeySql(useGeneratedKeys = true) // 开启自增主键回显功能
private Long id;
private String userName;
private String password;
private String name;
private Integer age;
private Integer sex;
private Date birthday;
private Date created;
private Date updated;
private String note;
}
- 修改 UserService.java 进行简单改造:
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User queryById(Long id){
//调用通用mapper的查询方法
return userMapper.selectByPrimaryKey(id);
}
}
- 启动项目,查看:
7.Profile(扩展)
在企业实际开发中,环境一般都有多个 ,如开发环境、测试环境、仿真环境、线上环境。不同环境的需要参数都是不一样的,比如数据库连接信息、redis服务器地址等,这时候就需要配置不同环境的配置。
7.1 yml多文档块方式
#默认配置,如果没有指定profiles,则默认配置生效
logging:
level:
cn.itcast: debug
org.springframework: debug
spring:
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/springboot
username: root
password: 123456
mybatis:
configuration:
#查看运行Sql
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# mapper.xml文件位置,如果没有映射文件,请注释掉
mapper-locations: classpath:mappers/*.xml
person:
name: 小姐姐2
age: 18
mary: false
birthday: 2001/03/27
hobby:
- 王者荣耀
- 吃鸡
- 看片
sanwei: {height: 177cm,weight: 50cm, bust: 65cm }
cat:
name: 小花2
age: 3
server:
port: 80
---
#dev开发环境配置
logging:
level:
cn.itcast: debug
org.springframework: debug
spring:
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/springboot
username: root
password: 123456
profiles: dev #指定属于dev开发环境
mybatis:
configuration:
#查看运行Sql
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# mapper.xml文件位置,如果没有映射文件,请注释掉
mapper-locations: classpath:mappers/*.xml
person:
name: 小姐姐1
age: 18
mary: false
birthday: 2001/03/27
hobby:
- 王者荣耀
- 吃鸡
- 看片
sanwei: {height: 177cm,weight: 50cm, bust: 65cm }
cat:
name: 小花1
age: 4
server:
port: 8081
---
#test测试环境配置
logging:
level:
cn.itcast: debug
org.springframework: debug
spring:
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/springboot
username: root
password: 123456
profiles: test #指定属于测试环境
mybatis:
configuration:
#查看运行Sql
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# mapper.xml文件位置,如果没有映射文件,请注释掉
mapper-locations: classpath:mappers/*.xml
person:
name: 小姐姐2
age: 18
mary: false
birthday: 2001/03/27
hobby:
- 王者荣耀
- 吃鸡
- 看片
sanwei: {height: 177cm,weight: 50cm, bust: 65cm }
cat:
name: 小花2
age: 3
server:
port: 8082
---
#启用环境
spring:
profiles:
active: dev
7.2 多Profile文件方式
我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties/yml
7.3 激活指定profile
1、在配置yml文件中指定 spring.profiles.active=dev
2、命令行:
java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev;
可以直接在测试的时候,配置传入命令行参数
3、虚拟机参数;
-Dspring.profiles.active=dev
王者荣耀
- 吃鸡
- 看片
sanwei: {height: 177cm,weight: 50cm, bust: 65cm }
cat:
name: 小花1
age: 4
server:
port: 8081
#test测试环境配置
logging:
level:
cn.itcast: debug
org.springframework: debug
spring:
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/springboot
username: root
password: 123456
profiles: test #指定属于测试环境
mybatis:
configuration:
#查看运行Sql
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper.xml文件位置,如果没有映射文件,请注释掉
mapper-locations: classpath:mappers/*.xml
person:
name: 小姐姐2
age: 18
mary: false
birthday: 2001/03/27
hobby:
- 王者荣耀
- 吃鸡
- 看片
sanwei: {height: 177cm,weight: 50cm, bust: 65cm }
cat:
name: 小花2
age: 3
server:
port: 8082
#启用环境
spring:
profiles:
active: dev
## 7.2 多Profile文件方式
我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties/yml
[外链图片转存中...(img-mOxtByWY-1577157008061)]
## 7.3 激活指定profile
**1、在配置yml文件中指定 spring.profiles.active=dev**
2、命令行:
java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev;
可以直接在测试的时候,配置传入命令行参数
**3、虚拟机参数;**
-Dspring.profiles.active=dev
[外链图片转存中...(img-jPy4alCV-1577157008062)]