1.数据源的自动配置
1.1 导入 JDBC 场景
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
导入了 JDBC 场景,官方没有导入数据库驱动。因为官方不知道我们接下来要操作什么数据库。所以我们要导入数据库驱动。
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
注意,SpringBoot 对 mysql 进行了版本仲裁,所以可以不输入版本号。但是要注意驱动版本要与本地数据库版本对应。
修改数据库驱动版本方法
- 直接引入具体版本(Maven 就近依赖原则)
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
- 重新声明版本(Maven 属性的就近优先原则)
<properties>
<mysql.version>8.0.26</mysql.version>
</properties>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
1.2 分析自动配置
自动配置的类
1、DataSourceAutoConfiguration 数据源相关的配置
- 修改数据源相关的配置只需要修改 【spring.datasource】相关的配置,它与 DataSourceProperties 类绑定。
- 自己在容器中没有 DataSource 时,才会自动配置数据库连接池。
@Configuration(proxyBeanMethods = false)
@Conditional(PooledDataSourceCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class }) //表示容器中没有配置数据源时,才会生效
@Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,
DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.OracleUcp.class,
DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class })
protected static class PooledDataSourceConfiguration {
}
- 底层配置好的数据源是 HikariDataSource
2、DataSourceTransactionManagerAutoConfiguration 事务管理器的自动配置
3、JdbcTemplateAutoConfiguration JdbcTemplate的自动配置,可以用来对数据库进行 CRUD
- 可以修改【spring.jdbc】相关的配置项(与 JdbcProperties 类型绑定),来修改 JdbcTemplate。
- 容器中有 JdbcTemplate,我们可以自动注入来使用它。
4、JndiDataSourceAutoConfiguration Jndi的自动配置
5、XADataSourceAutoConfiguration 分布式事务相关的自动配置
1.3 修改数据源相关配置项
spring:
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
1.4 测试
@Slf4j
@SpringBootTest
class Boot05Web01ApplicationTests {
@Autowired
JdbcTemplate jdbcTemplate;
@Test
void contextLoads() {
Long count = jdbcTemplate.queryForObject("select count(*) from tb_account", Long.class);
log.info("记录总数:{}", count);
}
}
2.使用 Druid 数据源
将第三方技术整合进 SpringBoot 的两种方式: 自定义、 找 starter
2.1 自定义方式
引入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
配置 Durid 数据源
@Configuration
public class MyDataSourceConfig {
@ConfigurationProperties("spring.datasource") //将 DruidDataSource 的属性于配置文件绑定
@Bean
public DataSource dataSource() throws SQLException {
DruidDataSource druidDataSource = new DruidDataSource();
// 不需要写死,采用 @ConfigurationProperties 与配置文件绑定
// druidDataSource.setUrl();
// druidDataSource.setUsername();
// druidDataSource.setPassword();
return druidDataSource;
}
}
跟多配置项参考官方文档
配置 Durid 数据源的监控页面:
- Druid 内置提供了一个 StatViewServlet 用于展示 Durid 的统计信息。配置_StatViewServlet配置
- 需要配置 StatFilter ,用于统计监控信息。配置_StatFilter
- WebStatFilter用于采集web-jdbc关联监控的数据。配置WebStatFilter
- Druid提供了
WallFilter
,它是基于SQL语义分析来实现防御SQL注入攻击的。配置_wallfilter
@Configuration
public class MyDataSourceConfig {
@ConfigurationProperties("spring.datasource") //将 DruidDataSource 的属性于配置文件绑定
@Bean
public DataSource dataSource() throws SQLException {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setFilters("stat,wall"); //stat:启动 SQL 监控功能 ;wall启动防火墙
return druidDataSource;
}
/**
* 配置 Druid 的监控页功能
* @return
*/
@Bean
public ServletRegistrationBean statViewServlet() {
StatViewServlet statViewServlet = new StatViewServlet();
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(statViewServlet, "/druid/*");
servletRegistrationBean.addInitParameter("loginUsername","admin");
servletRegistrationBean.addInitParameter("loginPassword","admin");
return servletRegistrationBean;
}
/**
* 配置druid:用于采集 web-jdbc 关联监控的数据
* @return
*/
@Bean
public FilterRegistrationBean webStatFilter() {
WebStatFilter webStatFilter = new WebStatFilter();
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(webStatFilter);
filterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));
filterRegistrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
return filterRegistrationBean;
}
}
2.2 starter 方式
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.17</version>
</dependency>
分析自动配置
@Configuration
@ConditionalOnClass({DruidDataSource.class})
@AutoConfigureBefore({DataSourceAutoConfiguration.class})
@EnableConfigurationProperties({DruidStatProperties.class, DataSourceProperties.class})
@Import({DruidSpringAopConfiguration.class, DruidStatViewServletConfiguration.class, DruidWebStatFilterConfiguration.class, DruidFilterConfiguration.class})
public class DruidDataSourceAutoConfigure {
}
- 扩展配置项 spring.datasource.druid ,它对应的类型是 DruidStatProperties
- DruidSpringAopConfiguration :用来监控 SpringBean 的配置项
- DruidStatViewServletConfiguration :监控页的配置,默认开启【spring.datasource.druid.stat-view-servlet】
- DruidWebStatFilterConfiguration :Web 监控的配置,默认开启 【spring.datasource.druid.web-stat-filter】
- DruidFilterConfiguration.class :配置所有 Druid 自己 filter 的配置项。
// 所有的 filters
private static final String FILTER_STAT_PREFIX = "spring.datasource.druid.filter.stat";
private static final String FILTER_CONFIG_PREFIX = "spring.datasource.druid.filter.config";
private static final String FILTER_ENCODING_PREFIX = "spring.datasource.druid.filter.encoding";
private static final String FILTER_SLF4J_PREFIX = "spring.datasource.druid.filter.slf4j";
private static final String FILTER_LOG4J_PREFIX = "spring.datasource.druid.filter.log4j";
private static final String FILTER_LOG4J2_PREFIX = "spring.datasource.druid.filter.log4j2";
private static final String FILTER_COMMONS_LOG_PREFIX = "spring.datasource.druid.filter.commons-log";
private static final String FILTER_WALL_PREFIX = "spring.datasource.druid.filter.wall";
private static final String FILTER_WALL_CONFIG_PREFIX = "spring.datasource.druid.filter.wall.config";
配置示例
spring:
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
druid:
filters: stat,wall #开启哪些功能组件
aop-patterns: com.cj.web.* #Spring 监控包
stat-view-servlet: #druid监控页相关配置
enabled: true
login-username: admin
login-password: password
reset-enable: false
web-stat-filter: #druid Web监控相关配置
enabled: true
url-pattern: /*
exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'
filter: #对 filters 的每个组件进行详细配置
stat:
enabled: true
slow-sql-millis: 1000
log-slow-sql: true
wall:
enabled: true
config:
drop-table-allow: false #不允许进行删除
3.整合 Mybatis 操作
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
3.1 配置模式
分析
自动配置类如下:
@Configuration
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties({MybatisProperties.class}) //Mybatis 配置类
@AutoConfigureAfter({DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class})
public class MybatisAutoConfiguration implements InitializingBean {
}
@ConfigurationProperties(
prefix = "mybatis"
)
public class MybatisProperties {
}
由上可知, 可以修改以 mybatis 开始的配置。
之前我们使用的时候是需要编写全局配置文件的,使用 SpringBoot 的 mybatis 场景会自动配置好以下组件:
- SqlSessionFactory :自动配置好
- SqlSession :自动配置了 SqlSessionTemplate,SqlSessionTemplate 内部组合了 SqlSession。
- 只要我们编写的操作 Mybatis 的接口标注了 @Mapper ,就会被自动扫码进来。【@Import({MybatisAutoConfiguration.AutoConfiguredMapperScannerRegistrar.class})】实现了此功能。
@Configuration
@Import({MybatisAutoConfiguration.AutoConfiguredMapperScannerRegistrar.class})
@ConditionalOnMissingBean({MapperFactoryBean.class, MapperScannerConfigurer.class})
public static class MapperScannerRegistrarNotFoundConfiguration implements InitializingBean {
}
实践
yml 配置文件
mybatis:
config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/mapper/*.xml
Mybatis 全局配置文件 mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
</configuration>
Bean
@Data
public class Account {
private Long id;
private String name;
private Date createTime;
}
mapper 相关
@Mapper
public interface AccountMapper {
Account selectById(Long id);
}
<!--AccountMapper.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="com.cj.web.mapper.AccountMapper">
<select id="selectById" resultType="com.cj.web.bean.Account">
select * from tb_account where id = #{id}
</select>
</mapper>
Service 层
@Service
public class AccountService {
@Autowired
AccountMapper accountMapper;
public Account getById(Long id){
return accountMapper.selectById(id);
}
}
controller 层
@Autowired
AccountService accountService;
@ResponseBody
@GetMapping(value = {"/acct"})
public Account acct(Long id) {
return accountService.getById(id);
}
注意: yml 中的 配置项 【mybatis.configuration】与 【mybatis.config-location】不能同时出现。 因为 他们都表示了全局的配置, 只不过 【mybatis.configuration】 是放在 yml 配置文件配置,而【mybatis.config-location】是在另外的全局配置文件中配置。
我们推荐使用 【mybatis.configuration】。
mybatis.configuration 的使用范例
mybatis:
# config-location: classpath:mybatis/mybatis-config.xml #使用了 configuration 就不需要使用全局配置文件了
mapper-locations: classpath:mybatis/mapper/*.xml
configuration:
map-underscore-to-camel-case: true #开启驼峰命名
3.2 注解模式+配置模式
我们修改 AccountMapper 如下,将简单的方法写在方法的注解上,负责的方法写在 mapper.xml 里。
@Mapper
public interface AccountMapper {
@Select("select * from tb_account where id = #{id}") //简单方法可以使用注解,无须在mapper.xml中编写
Account selectById(Long id);
void insert(Account account); //复杂方法在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="com.cj.web.mapper.AccountMapper">
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
insert into tb_account (name,age) values (#{name},#{age})
</insert>
</mapper>
如果觉得在每个 XxxMapper 接口都加上 @Mapper 注解觉得麻烦,可以使用 @MapperScan("packageName") 简化。 @MapperScan 增加在启动类上,Mapper接口就可以不用标注 @Mapper 注解。 但是我们推荐使用 @Mapper 注解。
4.整合 Mybatis-Plus 完成 CRUD
Mybatis-Plus(检查 MP)是一个 Mybatis 的增强工具,在 Mybatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
在开发 Mybatis-Plus 之前,推荐先安装 MybatisX 快速开发插件
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3.2</version>
</dependency>
Mybatis-Plus 自动引入了 Mybatis
4.1分析自动配置
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties({MybatisPlusProperties.class})
@AutoConfigureAfter({DataSourceAutoConfiguration.class, MybatisPlusLanguageDriverAutoConfiguration.class})
public class MybatisPlusAutoConfiguration implements InitializingBean {
- MybatisPlusAutoConfiguration 是自动配置类,MybatisPlusProperties 配置项绑定。mybatis-plus:xxx 就是对 Mybatis-Plus 的定制。
- SqlSessionFactory 自动配置。底层是容器中默认的数据源。
- mapperLocations 自动配置了默认值。 建议 xml 映射文件都放在 mapper 文件夹下。
classpath*:/mapper*.xml 是 mapperLocations 的默认值,它的意思为 任意包的类路径下的所有 mapper 文件夹下的所有 xml(包含其子文件夹中的 xml)
- 容器中也配置好了 SqlSessionTemplate。
- @Mapper 标注的接口也会被自动扫描。
优点
- 只要我们的 Mapper 接口继承 BaseMapper 方法,就可以拥有 CRUD 能力,减轻开发工作。
@Mapper
public interface AccountMapper extends BaseMapper<Account> {
}
4.2 实践
Mapper
@Mapper
public interface AccountMapper extends BaseMapper<Account> {
}
Service
public interface AccountService extends IService<Account> {
}
@Service
public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> implements AccountService {
}
接下来就可以测试CRUD接口了。
@Slf4j
@SpringBootTest
class Boot05Web01ApplicationTests {
@Autowired
AccountService accountService;
@Test
void list() {
log.info("列表:{}", accountService.list());
}
@Test
void page() {
Page<Account> page = new Page<>(1,3);
Page<Account> accountPage = accountService.page(page);
log.info("分页:{}, {}, {}", accountPage.getSize(), accountPage.getCurrent(), accountPage.getRecords());
}
@Test
void delete() {
log.info("列表:{}", accountService.removeById(1));
}
}
5.Redis
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
5.1 Redis 自动配置
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
- RedisAutoConfiguration 是自动配置类。RedisProperties 属性类 --> spring.redis 是对 redis 的配置。
- 连接工厂是准备好的。LettuceConnectionConfiguration、JedisConnectionConfiguration 。
- 自动注入了 RedisTemplate<Object, Object> (XxxTemplate)。
- 自动注入了 StringRedisTemplate。key、value 都是 String 的。
- 底层只要我们使用了 StringRedisTemplate、RedisTemplate 就可以操作 Redis。
5.2 Redis 环境搭建
自行百度安装方法。本人在本机以安装好Redis。
可在 安装目录下的 【redis.windows-service.conf】文件中查看 port 为多少,这就是redis 的端口。作者的本地端口是 6379
5.3 实践 (Lettuce 客户端)
yml 配置文件
spring:
redis:
host: 127.0.0.1
port: 6379
username: #未设置用户名
password: #未设置密码
测试代码:
@Slf4j
@SpringBootTest
class Boot05Web01ApplicationTests {
@Autowired
RedisTemplate redisTemplate;
@Test
void redis() {
ValueOperations<String, String> operations = redisTemplate.opsForValue();
operations.set("hello","world");
log.info("设置 完成");
log.info("hello 的值:{}", operations.get("hello"));
}
}
5.4 切换到 Jedis 客户端
若要使用 Jedis 客户端,则还需要引入 Jedis 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
此时,我们的底层有 Jedis、 Lettuce 这两个客户端。
此时需要在底层指定客户端类型为 Jedis。
spring:
redis:
host: 127.0.0.1
port: 6379
username: #未设置用户名
password: #未设置密码
client-type: jedis #指定客户端类型为 jedis
测试代码与 Lettuce 客户端的代码一致。