1. Spring Boot概述
目标:了解Spring Boot是什么,有什么作用
小结:
Spring Boot是一个便捷搭建 基于spring工程的脚手架;作用是帮助开发人员快速搭建大型的spring 项目。简化工程的配置,依赖管理;实现开发人员把时间都集中在业务开发上。
2. Spring Boot入门
目标:能够使用Spring Boot搭建项目
分析:
需求:可以在浏览器中访问http://localhost:8080/hello输出一串字符
实现步骤:
- 创建工程;
- 添加依赖(启动器依赖,spring-boot-starter-web);
- 创建启动类;
- 创建处理器Controller;
- 测试
小结:
Spring Boot工程可以通过添加启动器依赖和创建启动引导类实现快速创建web工程。
spring-boot-starter-web默认的应用服务器端口是8080
步骤1:创建maven工程加入依赖
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
</parent>
<groupId>com.lovelves</groupId>
<artifactId>hello</artifactId>
<version>1.0-SNAPSHOT</version>
<repositories>
<repository>
<id>aliyun</id>
<name>aliyun</name>
<url>http://maven.aliyun.com/repository/public</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
步骤2:创建启动类
package com.lovelves;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class app {
public static void main(String[] args) {
SpringApplication.run(app.class,args);
}
}
步骤3:创建处理器Controller
package com.lovelves.controlller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.sql.DataSource;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(){
return "hello world";
}
}
步骤4: 测试
3. Java代码方式配置
目标:可以使用@Value获取配置文件配置项并结合@Bean注册组件到Spring
分析:
需求:使用Java代码配置数据库连接池,并可以在处理器中注入并使用
步骤:
- 添加依赖;
- 创建数据库;
- 创建数据库连接参数的配置文件jdbc.properties;
- 创建配置类;
- 改造处理器类注入数据源并使用
步骤1: 添加阿里的数据源依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.6</version>
</dependency>
步骤2: 把数据库连接参数写入到配置文件jdbc.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://192.168.99.128:3306/tensquare_article
jdbc.username=root
jdbc.password=root
步骤3:创建配置类
package com.lovelves.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import javax.sql.DataSource;
@Configuration
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig {
@Value("${jdbc.url}")
String url;
@Value("${jdbc.driverClassName}")
String driverClassName;
@Value(("${jdbc.username}"))
String username;
@Value("${jdbc.password}")
String password;
@Bean
public DataSource db(){
DruidDataSource d = new DruidDataSource();
d.setUsername(username);
d.setDriverClassName(driverClassName);
d.setUrl(url);
d.setPassword(password);
return d;
}
}
步骤4: 测试数据源是否注入成功
解读:
@Configuration :声明我们 JdbcConfig 是一个配置类
@PropertySource :指定属性文件的路径是: classpath:jdbc.properties
通过 @Value 为属性注入值
通过@Bean将 dataSource() 方法声明为一个注册Bean的方法,Spring会自动调用该方法,将方法的返回值
加入Spring容器中。
然后我们就可以在任意位置通过 @Autowired 注入DataSource了!
4.Spring Boot属性注入方式
目标:能够使用@ConfigurationProperties实现Spring Boot配置文件配置项读取和应用
分析:
需求:将配置文件中的配置项读取到一个对象中;
实现:可以使用Spring Boot提供的注解@ConfigurationProperties,该注解可以将Spring Boot的配置文件(默认必须为application.properties或application.yml)中的配置项读取到一个对象中。
实现步骤:
- 创建配置项类JdbcProperties类,在该类名上面添加@ConfigurationProperties;
- 将jdbc.properties修改名称为application.properties;
- 将JdbcProperties对象注入到JdbcConfig;
- 测试
小结:
- 使用@ConfigurationProperties编写配置项类将配置文件中的配置项设置到对象中
步骤1:创建配置实体类 JdbcProperties类
package com.lovelves.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "jdbc")
public class JdbcProperties {
private String url;
private String driverClassName;
private String username;
private String password;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getDriverClassName() {
return driverClassName;
}
public void setDriverClassName(String driverClassName) {
this.driverClassName = driverClassName;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
在类上通过@ConfigurationProperties注解声明当前类为属性读取类prefix=“jdbc” 读取属性文件中,前缀为jdbc的值。
在类上定义各个属性,名称必须与属性文件中 jdbc. 后面部分一致
如果出现报错 要加入依赖
<dependency>
<groupId> org.springframework.boot </groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<!--不传递依赖-->
<optional>true</optional>
</dependency>
步骤2:创建application.properties 必须是这个名字
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://192.168.99.128:3306/tensquare_article
jdbc.username=root
jdbc.password=root
步骤3: 配置实体类导入配置类
package com.lovelves.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
@EnableConfigurationProperties(JdbcProperties.class)
public class JdbcConfig {
@Bean
public DataSource db(JdbcProperties jdbc){
DruidDataSource d = new DruidDataSource();
d.setUsername(jdbc.getUsername());
d.setDriverClassName(jdbc.getDriverClassName());
d.setUrl(jdbc.getUrl());
d.setPassword(jdbc.getPassword());
return d;
}
}
通过 @EnableConfigurationProperties(JdbcProperties.class) 来声明要使用 JdbcProperties 这个类的
对象
步骤4:测试是否成功
package com.lovelves.controlller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.sql.DataSource;
@RestController
public class HelloController {
@Autowired
private DataSource db;
@GetMapping("/hello")
public String hello(){
System.out.println(db);
return "hello world";
}
}
测试是否注入成功
5.更优雅的注入方式
事实上,如果一段属性只有一个Bean需要使用,我们无需将其注入到一个类(JdbcProperties,将该类上的所有注
解去掉)中。而是直接在需要的地方声明即可;再次修改 JdbcConfig 类为如下代码:
package com.lovelves.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
public class JdbcConfig {
@Bean
@ConfigurationProperties(prefix = "jdbc")
public DataSource db(){
return new DruidDataSource();
}
}
我们直接把@ConfigurationProperties(prefix = “jdbc”)声明在需要使用的@Bean的方法上,然后Spring Boot就会自动调用这个Bean(此处是DataSource)的set方法,然后完成注入。使用的前提是:该类必须有对应属 性的set方法!
6.Yaml配置文件
配置文件除了可以使用application.properties类型,还可以使用后缀名为:.yml或者.yaml的类型,也就是:
application.yml或者application.yaml
yaml与properties配置文件除了展示形式不相同以外,其它功能和作用都是一样的;在项目中原路的读取方式不需要改变。
1)yml配置文件的特征:
- 树状层级结构展示配置项;
- 配置项之间如果有关系的话需要分行空两格;
- 配置项如果有值的话,那么需要在
:
之后空一格再写配置项值;
将application.properties配置文件修改为application.yml的话:
jdbc:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.99.128:3306/tensquare_article
username: root
password: root
如果配置值是多个 也是list 的 格式:
jdbc:
abc: hhh
def:
- g
- h
- j
多个yml配置文件;在spring boot中是被允许的。这些配置文件的名称必须为application-***.yml,并且这些配置文件必须要在application.yml配置文件中激活之后才可以使用。
application-a.yml
jdbc:
aa: dddd
application-b.yml
jdbc:
bb: cccc
在多个配置文件时,需要将这些文件在application.yml文件中进行激活:
application.yml
spring:
profiles:
active: a,b
如果properties和yml配置文件同时存在在spring boot项目中;那么这两类配置文件都有效。在两个配置文件中如果存在同名的配置项的话会以properties文件的为主。
7.自动配置原理
目标:了解Spring Boot项目的配置加载流程
小结:
-
在
META-INF\spring.fatories
文件中定义了很多自动配置类;可以根据在pom.xml文件中添加的 启动器依赖自动配置组件 -
通过如下流程可以去修改application配置文件,改变自动配置的组件默认参数
SpringBoot为我们提供了默认配置,而默认配置生效的步骤:
@EnableAutoConfiguration注解会去寻找 META-INF/spring.factories 文件,读取其中以 EnableAutoConfiguration 为key的所有类的名称,这些类就是提前写好的自动配置类
这些类都声明了 @Configuration 注解,并且通过 @Bean 注解提前配置了我们所需要的一切实例 但是,这些配置不一定生效,因为有 @ConditionalOn 注解,满足一定条件才会生效。比如条件之一:
类要存在,我们只需要引入了相关依赖(启动器),依赖有了条件成立,自动配置生效。 如果我们自己配置了相关Bean,那么会覆盖默认的自动配置的Bean 我们还可以通过配置application.yml文件,来覆盖自动配置中的属性
1)启动器 所以,我们如果不想配置,只需要引入依赖即可,而依赖版本我们也不用操心,因为只要引入了SpringBoot提供的
stater(启动器),就会自动管理依赖及版本了。
因此,玩SpringBoot的第一件事情,就是找启动器,SpringBoot提供了大量的默认启动器
2)全局配置
另外,SpringBoot的默认配置,都会读取默认属性,而这些属性可以通过自定义 application.properties 文件来 进行覆盖。这样虽然使用的还是默认配置,但是配置中的值改成了我们自定义的。
因此,玩SpringBoot的第二件事情,就是通过 application.properties 来覆盖默认属性值,形成自定义配置。我 们需要知道SpringBoot的默认属性key,非常多,可以再idea中自动提示
8. springboot实战
接下来,我们来看看如何用SpringBoot来整合SSM,在数据库中引入一张用户表tb_user和实体类User。
tb_user表:详见 资料\tb_user.sql 文件,将该文件导入数据库中。
8.1 lombok
我们编写pojo时,经常需要编写构造函数和getter、setter方法,属性多的时候,就非常浪费时间,使用lombok插件
可以解决这个问题:
在IDEA中安装lombok插件;不安装插件在IDEA中使用lombok的注解虽然编译能通过,但是源码会报错。所以为了 让IDEA更好的辨别lombok注解则才安装插件。
引入依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
编写实体类对应数据库
package com.lovelves.pojo;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
@Data
@Slf4j
public class User {
private Long id;
private String userName;
private String password;
private String name;
private Integer age;
private Integer sex;
private Date birthday;
private String note;
private Date created;
private Date updated;
}
然后可以在Bean上使用:
@Data :自动提供getter和setter、hashCode、equals、toString等方法 @Getter:自动提供getter方法
@Setter:自动提供setter方法 @Slf4j:自动在bean中提供log变量,其实用的是slf4j的日志功能。
例如;在javabean上加@Data,那么就可以省去getter和setter等方法的编写,lombok插件会自动生成。
8.2 整合springMvc
虽然默认配置已经可以使用SpringMVC了,不过我们有时候需要进行自定义配置。
可以在 application.yml 文件中配置日志级别控制:
logging:
level:
com.lovelves: debug
org.springframework: info
8.21 修改端口
server:
port: 80
8.22访问静态资源
现在,我们的项目是一个jar工程,那么就没有webapp,我们的静态资源该放哪里呢?
回顾我们在上面看的源码,有一个叫做ResourceProperties的类,里面就定义了静态资源的默认查找路径:
@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties {
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/META-INF/resources/", "classpath:/resources/",
"classpath:/static/", "classpath:/public/" };
/**
* Locations of static resources. Defaults to classpath:[/META-INF/resources/,
* /resources/, /static/, /public/].
*/
private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
/**
* Whether to enable default resource handling.
*/
private boolean addMappings = true;
private final Chain chain = new Chain();
默认的静态资源路径为:
classpath:/META-INF/resources/
classpath:/resources/
classpath:/static/
classpath:/public
只要静态资源放在这些目录中任何一个,SpringMVC都会帮我们处理。
8.23 Mvc拦截器
通过实现 WebMvcConfigurer 并添加 @Configuration 注解来实现自定义部分SpringMvc配置。
编写拦截器
package com.lovelves.interceptor;
import lombok.extern.slf4j.Slf4j;
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 MyInterceptor 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");
}
}
编写config类实现webMvcConfigurer 重写 addInterceptors
package com.lovelves.config;
import com.lovelves.interceptor.MyInterceptor;
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;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Bean
public MyInterceptor myInterceptor(){
return new MyInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor()).addPathPatterns("/*");
}
}
显示结果
2020-12-27 20:42:58.082 INFO 942 --- [p-nio-80-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 10 ms
2020-12-27 20:42:58.102 DEBUG 942 --- [p-nio-80-exec-1] com.lovelves.interceptor.MyInterceptor : preHandle
{
CreateTime:"2020-12-27 20:42:38",
ActiveCount:0,
PoolingCount:0,
CreateCount:0,
DestroyCount:0,
CloseCount:0,
ConnectCount:0,
Connections:[
]
}
2020-12-27 20:42:58.145 DEBUG 942 --- [p-nio-80-exec-1] com.lovelves.interceptor.MyInterceptor : postHandle
2020-12-27 20:42:58.145 DEBUG 942 --- [p-nio-80-exec-1] com.lovelves.interceptor.MyInterceptor : afterCompletion
8.24整合jdbc和事务
spring中的jdbc连接和事务是配置中的重要一环,在SpringBoot中该如何处理呢?
答案是不需要处理,我们只要找到SpringBoot提供的启动器即可,在 pom.xml 文件中添加如下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
当然,不要忘了数据库驱动,SpringBoot并不知道我们用的什么数据库,这里我们选择MySQL;同样的在 pom.xml 文件中添加如下依赖:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
至于事务,SpringBoot中通过注解来控制。就是我们熟知的@Transactional 使用的时候设置在对应的类或方法上 即可。
8.25 连接池
在配置文件中加入连接池信息
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.99.128:3306/hello
username: root
password: root
8.26 整合mybatis
目标:配置Mybatis在Spring Boot工程中的整合包,设置mybatis的实体类别名,输出执行sql语句配置项
分析:
- 添加启动器依赖;
- 配置Mybatis:实体类别名包,日志,映射文件等;
- 配置MapperScan
小结:
- 添加mybatis官方对于spring boot的一个启动器
添加依赖
<!--mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
配置mybatis
mybatis:
#实体类别名路径
type-aliases-package: com.lovelves.pojo
#控制台输出sql
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
配置MapperScan
package com.lovelves;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.lovelves.mapper")
public class app {
public static void main(String[] args) {
SpringApplication.run(app.class,args);
}
}
8.27 国人开发的通用mapper
目标:配置通用Mapper组件到Spring Boot项目中并使用Mapper接口
分析:
通用Mapper:可以实现自动拼接sql语句;所有的mapper都不需要编写任何方法也就是不用编写sql语句。可以提高开发效率。
-
添加启动器依赖;
<dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper-spring-boot-starter</artifactId> <version>2.1.5</version> </dependency>
-
改造UserMapper继承Mapper;
package com.lovelves.mapper; import com.lovelves.pojo.User; import tk.mybatis.mapper.common.Mapper; public interface UserMapper extends Mapper<User> { }
-
修改启动引导类Application中的Mapper扫描注解;
package com.lovelves; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import tk.mybatis.spring.annotation.MapperScan; @SpringBootApplication @MapperScan("com.lovelves.mapper") public class app { public static void main(String[] args) { SpringApplication.run(app.class,args); } }
-
修改User实体类添加jpa注解;
package com.lovelves.pojo; import lombok.Data; import tk.mybatis.mapper.annotation.KeySql; import javax.persistence.Id; import javax.persistence.Table; import java.util.Date; @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实现业务功能;
package com.lovelves.service; import com.lovelves.mapper.UserMapper; import com.lovelves.pojo.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class UserService { @Autowired private UserMapper userMapper; public User queryById(long id){ return userMapper.selectByPrimaryKey(id); } @Transactional public void saveuser(User user){ System.out.println("new user"); userMapper.insertSelective(user); } }
-
测试
package com.lovelves.controlller; import com.lovelves.pojo.User; import com.lovelves.service.UserService; 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 javax.sql.DataSource; @RestController public class HelloController { @Autowired private UserService userService; @GetMapping("/user/{id}") public User getByid(@PathVariable Long id){ return userService.queryById(id); } }
-
结果
小结:
在启动引导类上面的mapper扫描注解 一定要修改为 通用mapper的扫描注解