数据库场景的自动配置分析与整合测试

导入JDBC场景

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>

在这个场景里面帮助我们导入了以下内容

接着导入数据库驱动包(MySQL为例)
为什么导入JDBC场景,官方不给我们导入驱动呢?因为官方不知道接下来要操作什么类型的数据库。
数据库版本和驱动版本对应

默认版本:<mysql.version>8.0.22</mysql.version><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId>
<!--            <version>5.1.49</version>--></dependency>
想要修改版本
1、直接依赖引入具体版本(maven的就近依赖原则)
2、重新声明版本(maven的属性的就近优先原则)<properties><java.version>1.8</java.version><mysql.version>5.1.49</mysql.version></properties>

分析自动配置

1、自动配置的类

DataSourceAutoConfiguration :数据源的自动配置

  • 修改数据源相关的配置: spring.datasource
  • 数据库连接池的配置,是自己容器中没有DataSource才自动配置的
  • 底层配置好的连接池是: HikariDataSource
@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

DataSourceTransactionManagerAutoConfiguration: 事务管理器的自动配置
JdbcTemplateAutoConfiguration: JdbcTemplate的自动配置, 可以来对数据库进行crud

  • 可以修改这个配置项@ConfigurationProperties(prefix = “spring.jdbc”)来修改JdbcTemplate
  • @Bean@Primary JdbcTemplate; 容器中有这个组件

JndiDataSourceAutoConfiguration: jndi的自动配置
XADataSourceAutoConfiguration: 分布式事务相关的

修改配置项

application.yml文件

spring:datasource:url: jdbc:mysql://localhost:3306/db_accountusername: rootpassword: rootdriver-class-name: com.mysql.jdbc.Driver

如果是mysql8版本的,需要配置时区

spring:datasource:url: jdbc:mysql://localhost:3306/db_account?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2b8&allowPublicKeyRetrieval=trueusername: rootpassword: rootdriver-class-name: com.mysql.jdbc.Driverjdbc:template:# 查询超时时间设置为3squery-timeout: 3

测试

@Slf4j
@SpringBootTest# 标题class Boot05WebAdminApplicationTests {// @Bean@Primary    JdbcTemplate; 容器中有这个组件,可以自动注入进来@AutowiredJdbcTemplate jdbcTemplate;@Testvoid contextLoads() {Long along=jdbcTemplate.queryForObject("select count(*) from account_tbl",Long.class);log.info("记录总数:{}",along);}}

2.使用Druid数据源

1.druid官方github地址

https://github.com/alibaba/druid
整合第三方技术的两种方式
自定义
找starter

2.自定义方式

1、创建数据源

引入数据源

<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.17</version>
</dependency>
@Configuration
public class MyDataSourceConfig {//默认的自动配置判断容器中没有才会配@ConditionalOnMissingBean(DataSource.class)@Bean@ConfigurationProperties("spring.datasource")//复用配置文件的数据源配置public DataSource dataSource(){DruidDataSource druidDataSource = new DruidDataSource();//所有属性可以从配置文件中获取
//        druidDataSource.setUrl();
//        druidDataSource.setUsername();
//        druidDataSource.setPassword();return druidDataSource;}
}
@Slf4j
@SpringBootTest
class Boot05WebAdminApplicationTests {// @Bean@Primary    JdbcTemplate; 容器中有这个组件,可以自动注入进来@AutowiredJdbcTemplate jdbcTemplate;@AutowiredDataSource dataSource;@Testvoid contextLoads() {Long along=jdbcTemplate.queryForObject("select count(*) from account_tbl",Long.class);log.info("记录总数:{}",along);log.info("数据源类型:{}",dataSource.getClass());}}


相当于底层操作我们自定义的数据源,从我们自己的druid数据源中获取了连接。

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"destroy-method="close"><property name="url" value="${jdbc.url}" /><property name="username" value="${jdbc.username}" /><property name="password" value="${jdbc.password}" /><property name="maxActive" value="20" /><property name="initialSize" value="1" /><property name="maxWait" value="60000" /><property name="minIdle" value="1" /><property name="timeBetweenEvictionRunsMillis" value="60000" /><property name="minEvictableIdleTimeMillis" value="300000" /><property name="testWhileIdle" value="true" /><property name="testOnBorrow" value="false" /><property name="testOnReturn" value="false" /><property name="poolPreparedStatements" value="true" /><property name="maxOpenPreparedStatements" value="20" />

2、StatViewServlet监控页

Druid内置提供了一个StatViewServlet用于展示Druid的统计信息。
StatViewServlet的用途包括:
提供监控信息展示的html页面
提供监控信息的JSON API

以前的做法

<servlet><servlet-name>DruidStatView</servlet-name><servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>DruidStatView</servlet-name><url-pattern>/druid/*</url-pattern>
</servlet-mapping>

现在

/*** 配置 druid的监控页功能* @return*/@Beanpublic ServletRegistrationBean statViewServlet(){StatViewServlet statViewServlet = new StatViewServlet();ServletRegistrationBean<StatViewServlet> registrationBean = new ServletRegistrationBean<>(statViewServlet, "/druid/*");//监控页账号密码:registrationBean.addInitParameter("loginUsername","admin");registrationBean.addInitParameter("loginPassword","123456");return registrationBean;}/*** WebStatFilter 用于采集web-jdbc关联监控的数据。*/@Beanpublic FilterRegistrationBean webStatFilter(){WebStatFilter webStatFilter = new WebStatFilter();FilterRegistrationBean<WebStatFilter> filterRegistrationBean = new FilterRegistrationBean<>(webStatFilter);filterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));filterRegistrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");return filterRegistrationBean;}

3、StatFilter

用于统计监控信息;如SQL监控、URI监控

需要给数据源中配置如下属性;可以允许多个filter,多个用,分割;如:<property name="filters" value="stat,slf4j" />

系统中所有filter

慢SQL记录配置

<bean id="stat-filter" class="com.alibaba.druid.filter.stat.StatFilter"><property name="slowSqlMillis" value="10000" /><property name="logSlowSql" value="true" />
</bean>使用 slowSqlMillis 定义慢SQL的时长

3.使用官方starter方式

1、引入druid-starter

   <dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.17</version></dependency>

2、分析自动配置

扩展配置项 spring.datasource.druid
DruidSpringAopConfiguration.class, 监控SpringBean的;配置项:spring.datasource.druid.aop-patterns
DruidStatViewServletConfiguration.class, 监控页的配置:spring.datasource.druid.stat-view-servlet;默认开启
DruidWebStatFilterConfiguration.class, web监控配置;spring.datasource.druid.web-stat-filter;默认开启
DruidFilterConfiguration.class}) 所有Druid自己filter的配置

   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";

3、配置示例

spring:datasource:url: jdbc:mysql://localhost:3306/db_accountusername: rootpassword: 123456driver-class-name: com.mysql.jdbc.Driverdruid:aop-patterns: com.atguigu.admin.*  #监控SpringBeanfilters: stat,wall     # 底层开启功能,stat(sql监控),wall(防火墙)stat-view-servlet:   # 配置监控页功能enabled: truelogin-username: adminlogin-password: adminresetEnable: falseweb-stat-filter:  # 监控webenabled: trueurlPattern: /*exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'filter:stat:    # 对上面filters里面的stat的详细配置slow-sql-millis: 1000logSlowSql: trueenabled: truewall:enabled: trueconfig:drop-table-allow: false

SpringBoot配置示例
https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter

配置项列表https://github.com/alibaba/druid/wiki/DruidDataSource%E9%85%8D%E7%BD%AE%E5%B1%9E%E6%80%A7%E5%88%97%E8%A1%A8

3.整合Mybatis

https://github.com/mybatis

starter的命名方式:

SpringBoot官方的Starter:spring-boot-starter-*

第三方的: *-spring-boot-starter

引入依赖:

<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.4</version>
</dependency>

1、配置模式

全局配置文件
SqlSessionFactory: 自动配置好了
SqlSession:自动配置了 SqlSessionTemplate 组合了SqlSession
@Import(AutoConfiguredMapperScannerRegistrar.class);
Mapper: 只要我们写的操作MyBatis的接口标准了 @Mapper 就会被自动扫描进来

@Configuration
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})    //导入mybatis的jar包就有
@ConditionalOnSingleCandidate(DataSource.class)        //有且仅有一个数据源
@EnableConfigurationProperties({MybatisProperties.class}) MyBatis配置项绑定类
@EnableConfigurationProperties(MybatisProperties.class) : MyBatis配置项绑定类
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class })
public class MybatisAutoConfiguration{...
}@ConfigurationProperties(prefix = "mybatis")
public class MybatisProperties{...
}

可以修改配置文件中mybatis开始的所有。

测试

application.yml配置文件:

spring:datasource:url: jdbc:mysql://localhost:3306/db_account?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2b8&allowPublicKeyRetrieval=trueusername: rootpassword: rootdriver-class-name: com.mysql.jdbc.Driverjdbc:template:# 查询超时时间设置为3squery-timeout: 3
#配置mybatis
mybatis:# 指定mybatis全局配置文件的位置config-location: classpath:mybatis/mybatis-config.xml# 指定sql映射文件的位置mapper-locations: classpath:mybatis/mapper/*.xml;

mybatis-config.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!-- 由于Spring Boot自动配置缘故,此处不必配置,只用来做做样。-->
</configuration>

mybatis的SQL映射文件AccountMapper.xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lun.boot.mapper.UserMapper">
<!--public Account getAcct(Long id);    --><select id="getAcct" resultType="com.yujie.admin.bean.Account">select * from account_tbl where id=#{id}</select></mapper>

Mapper接口AccountMapper

public interface AccountMapper {public Account getAcct(Long id);
}

POJO:

@Data
public class Account {private Long id;private String userId;private Integer money;
}

DB:

Controller and Service:

@Controller
public class IndexController {@AutowiredAccountService accountService;@ResponseBody       //返回json数据@GetMapping("/acct")public Account getById(@RequestParam("id") Long id){return accountService.getAcctById(id);}
@Service
public class AccountService {@AutowiredAccountMapper accountMapper;public Account getAcctById(Long id){return accountMapper.getAcct(id);}
}


上面user_Id没给我们封装上,原因在于mybatis默认没有开启驼峰命名策略,数据库中是user_id,java中是userId.可以在全局配置文件中设置

<configuration><!--设置驼峰命名规则--><settings><setting name="mapUnderscoreToCamelCase" value="true"/></settings>
</configuration>

也可以在

配置private Configuration configuration; 也就是配置mybatis.configuration相关的,就是相当于改mybatis全局配置文件中的值。(也就是说配置了mybatis.configuration,就不需配置mybatis全局配置文件了)

# 配置mybatis规则
mybatis:mapper-locations: classpath:mybatis/mapper/*.xml# 可以不写全局配置文件,所有全局配置文件的配置都放在configuration配置项中了。# config-location: classpath:mybatis/mybatis-config.xmlconfiguration:map-underscore-to-camel-case: true

小结
导入MyBatis官方Starter。
编写Mapper接口,需@Mapper注解
编写SQL映射文件并绑定Mapper接口。
在application.yaml中指定Mapper配置文件的所处位置,以及指定全局配置文件的信息 (建议:配置在mybatis.configuration)。

注解配置

你可以通过Spring Initializr添加MyBatis的Starer。


导入数据库

create table city{id INT(11) PRIMARY KEY AUTO_INCREMENT,name VARCHAR(30),state VARCHAR(30),country VARCHAR(30)
}

注意,如果出现以下问题,说明在controller层请求处理完了返回时,没有使用@RestController或@ResponseBody而返回了非json格式。

org.thymeleaf.exceptions.TemplateInputException: Error resolving template [city], template might not exist or might not be accessible by any of the configured Template Resolvers

Mapper文件

@Mapper
public interface CityMapper {@Select("select * from city where id=#{id}")public City getById(Integer id);
}

Controller文件

@ResponseBody       //返回json数据
@GetMapping("/city")
public City getCityById(@RequestParam("id") Integer id){return cityService.getById(id);
}

混合版

注解与配置混合搭配,干活不累:

简单DAO方法就写在注解上。复杂的就写在配置文件里。

使用@MapperScan(“com.lun.boot.mapper”) 简化,Mapper接口就可以不用标注@Mapper注解。

sql映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yujie.admin.mapper.CityMapper">
<!--    public void insert(City city);--><!--可以通过useGeneratedKeys拿到自增主键的值--><insert id="insert" useGeneratedKeys="true" keyProperty="id">insert into city('name','state','country') values(#{name},#{state},#{country})</insert></mapper>

持久层

@Mapper
public interface CityMapper {@Select("select * from city where id=#{id}")public City getById(Integer id);public void insert(City city);
}

控制层

@PostMapping("/city")
public City saveCity(City city){cityService.saveCity(city);return city;
}

这里也可以用注解来实现

@Insert("insert into city('name','state','country') values(#{name},#{state},#{country})")
@Options(useGeneratedKeys = true,keyProperty = "id")
public void insert(City city);

最佳实战:
引入mybatis-starter
配置application.yaml中,指定mapper-location位置即可
编写Mapper接口并标注@Mapper注解
简单方法直接注解方式
复杂方法编写mapper.xml进行绑定映射
@MapperScan(“com.atguigu.admin.mapper”) 简化,其他的接口就可以不用标注@Mapper注解

整合MyBatisPlus操作数据库

IDEA的MyBatis的插件 - MyBatisX

MyBatisPlus官网

MyBatisPlus官方文档

MyBatisPlus是什么

MyBatis-Plus(简称 MP)是一个 MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

生成数据库文件

create table USER{id BIGINT(20)  NOT NULL COMMENT '主键ID',name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',age INT(11) NULL DEFAULT NULL COMMENT '年龄',email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',PRIMARY KEY(id)
}

添加依赖:

<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.1</version>
</dependency>

MybatisPlusAutoConfiguration配置类,MybatisPlusProperties配置项绑定。mybatis-plus:xxx 就是对mybatis-plus的定制

SqlSessionFactory自动配置好,底层是容器中默认的数据源

mapperLocations自动配置好的,有默认值classpath*:/mapper/**/*.xml,这表示任意包的类路径下的所有mapper文件夹下任意路径下的所有xml都是sql映射文件。 建议以后sql映射文件放在 mapper下。

容器中也自动配置好了SqlSessionTemplate。

@Mapper 标注的接口也会被自动扫描,建议直接 @MapperScan(“com.lun.boot.mapper”)批量扫描。

MyBatisPlus优点之一:只需要我们的Mapper继承MyBatisPlus的BaseMapper 就可以拥有CRUD能力,减轻开发工作

pojo类

@Data
public class User {/*原本所有属性都应该在数据库中*/@TableField(exist=false)private String userName;@TableField(exist=false)private String password;//以下是数据库字段private Long id;private String name;private Integer age;private String email;
}

Mapper类

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yujie.admin.bean.User;public interface UserMapper extends BaseMapper<User> {}
@Test
void testMapper(){User user=userMapper.selectById(1);log.info("用户信息,{}",user);
}

测试类

我们有一个问题,这里baseMapper如何知道我们User对象与数据库中哪张表对应。这里有一个默认规则,我们是User对象,就会默认去数据库中找到user表。如果我们将数据表变成user_tbl,此时我们就不能再操作了,我们可以通过@TableName注解来实现

@TableName("user_tbl")
public class User

CRUD实验

数据列表展示

官方文档 - CRUD接口

使用MyBatis Plus提供的IService,ServiceImpl,减轻Service层开发工作。

jUser类接上文。
UserMapper

public interface UserMapper extends BaseMapper<User> {}

UserService

//IService是所有Service的总接口,泛型是查询哪些数据类型
public interface UserService extends IService<User> {}

UserServiceImpl

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {}

Controller

    @AutowiredUserService userService;@GetMapping("/dynamic_table")public String dynamic_table(Model model){//        //表格内容的遍历List<User> list = userService.list();model.addAttribute("users",list);return "table/dynamic_table";}

hrml

<thead><tr><th>#</th><th>id</th><th>name</th><th>age</th><th>email</th><th>操作</th></tr></thead><tbody><tr class="gradeX" th:each="user,stats:${users}"><td th:text="${stats.count}">Trident</td><td th:text="${user.id}">Internet</td><td th:text="${user.name}">Internet</td><td th:text="${user.age}">Internet</td><td>[[${user.email}]]</td><td>X</td></tr></tbody>
    </table>

分页数据展示

MybatisConfig

//给容器中注册一个分页插件
@Configuration
public class MybatisConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false// paginationInterceptor.setOverflow(false);// 设置最大单页限制数量,默认 500 条,-1 不受限制// paginationInterceptor.setLimit(500);// 开启 count 的 join 优化,只针对部分 left join//这是分页拦截器PaginationInnerInterceptor paginationInnerInterceptor=new PaginationInnerInterceptor();paginationInnerInterceptor.setOverflow(true);paginationInnerInterceptor.setMaxLimit(500L);mybatisPlusInterceptor.addInnerInterceptor(paginationInnerInterceptor);return mybatisPlusInterceptor;}
}

Controller

  @AutowiredUserService userService;@GetMapping("/dynamic_table")//通过请求参数的方式获取当前页码,默认值是1public String dynamic_table(@RequestParam(value="pn",defaultValue ="1") Integer pn,Model model){List<User> list = userService.list();model.addAttribute("users",list);//分页查询数据//构建分页对象,传的是当前页码和每页显示几条Page<User> userPage=new Page<>(pn,2);//分页查询的结果 ,page包含了所有Page<User> page = userService.page(userPage, null);model.addAttribute("page",page);return "table/dynamic_table";}

html文件

<table  class="display table table-bordered table-striped" id="dynamic-table"><thead><tr><th>#</th><th>id</th><th>name</th><th>age</th><th>email</th><th>操作</th></tr></thead><tbody><!--分页显示后,用pages.records来显示数据库的数据,users里面的数据被放到了page对象里面--><tr class="gradeX" th:each="user,stats:${page.records}"><td th:text="${stats.count}">Trident</td><td th:text="${user.id}">Internet</td><td th:text="${user.name}">Internet</td><td th:text="${user.age}">Internet</td><td>[[${user.email}]]</td><td>X</td></tr></tbody></table><div class="row-fluid"><div class="span6"><div class="dataTables_info" id="dynamic-table_info">当前第 [[${page.current}]]页 总计  [[${page.pages}]] 页 共  [[${page.total}]]条记录</div></div><div class="span6"><div class="dataTables_paginate paging_bootstrap pagination"><ul><li class="prev disabled"><a href="#">← Previous</a></li><!--thymeleaf遍历生成从几到几--><li class="${num==page.current?'active':''}" th:each="num:${#numbers.sequence(1,page.pages)}"><a th:href="@{/dynamic_table(pn=${num})}">[[${num}]]</a></li><li class="next"><a href="#">Next → </a></li></ul></div></div></div></div>

删除用户完成

@GetMapping("/user/delete/{id}")public String deleteUser(@PathVariable("id") Long id,@RequestParam(value="pn",defaultValue = "1")Integer pn,RedirectAttributes ra){userService.removeById(id);ra.addAttribute("pn",pn);return "redirect:/dynamic_table";}
 <tr class="gradeX" th:each="user,stats:${page.records}"><td th:text="${stats.count}">Trident</td><td th:text="${user.id}">Internet</td><td th:text="${user.name}">Internet</td><td th:text="${user.age}">Internet</td><td>[[${user.email}]]</td><td><a th:href="@{/user/delete/{id}(id=${user.id},pn=${page.current})}" class="btn btn-danger btn-sm" type="button">删除</a></td></tr></tbody>

准备阿里云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><!--导入jedis-->
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId>
</dependency>

RedisAutoConfiguration自动配置类,RedisProperties 属性类 --> spring.redis.xxx是对redis的配置
连接工厂LettuceConnectionConfiguration、JedisConnectionConfiguration是准备好的。
自动注入了RedisTemplate<Object, Object>,xxxTemplate。
自动注入了StringRedisTemplate,key,value都是String
底层只要我们使用StringRedisTemplate、RedisTemplate就可以操作Redis

外网Redis环境搭建:

阿里云
阿里云按量付费Redis,其中选择经典网络。

申请Redis的公网连接地址。

修改白名单,允许0.0.0.0/0访问。

创建一个账号

注意:用完后一定要记得释放。

Redis操作与统计小实验

相关Redis配置:

spring:redis:host: r-bp1d20ke18nzuvs6q4pd.redis.rds.aliyuncs.comport: 6379# url: redis://yujie:Yj123456@r-bp1d20ke18nzuvs6q4pd.redis.rds.aliyuncs.com:6379password: yujie:Yj123456client-type: jedisjedis:pool:max-active: 10

测试Redis连接:

@SpringBootTest
public class Boot05WebAdminApplicationTests {//redis客户端操作@AutowiredStringRedisTemplate stringRedisTemplate;@AutowiredRedisConnectionFactory redisConnectionFactory;@Testpublic void testRedis(){ValueOperations<String,String> operations=stringRedisTemplate.opsForValue();operations.set("hello","world");String hello=operations.get("hello");System.out.println(hello);System.out.println(redisConnectionFactory.getClass());}}

Redis Desktop Manager:可视化Redis管理软件。

URL统计拦截器:

@Component
public class RedisUrlCountInterceptor implements HandlerInterceptor {@AutowiredStringRedisTemplate stringRedisTemplate;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//获取当前请求访问的路径String requestURI = request.getRequestURI();//使用uri作为key,访问次数为value//默认每次访问呢就会计数+1stringRedisTemplate.opsForValue().increment(requestURI);return true;}
}

注册URL统计拦截器:

/** filter和intercepter几乎拥有相同的功能* filter是servlet定义的组件,好处,脱离spring应用也能使用* interceptor是spring定义的接口,可以使用spring自动装配功能。* */@AutowiredRedisUrlCountInterceptor redisUrlCountInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginIntercepter())// /**会拦截所有请求,包括静态资源.addPathPatterns("/**")             //拦截哪些.excludePathPatterns("/","/login","/css/**","/js/**","/fonts/**","/images/**");  //放行哪些registry.addInterceptor(redisUrlCountInterceptor).addPathPatterns("/**").excludePathPatterns("/","/login","/css/**","/js/**","/fonts/**","/images/**");}

Filter、Interceptor 几乎拥有相同的功能?

  • Filter是Servlet定义的原生组件,它的好处是脱离Spring应用也能使用。
  • Interceptor是Spring定义的接口,可以使用Spring的自动装配等功能。

调用Redis内的统计数据:

@Slf4j
@Controller
//这里请求名是main.html,但是我们还是去main.html,之后每次刷新就是main.html@GetMapping("/main.html")public String mainPage(HttpSession session,Model model){//是否登录,拦截器,过滤器Object loginUser=session.getAttribute("loginUser");if(loginUser!=null){ValueOperations<String,String> opsForValue=redisTemplate.opsForValue();String s=opsForValue.get("/main.html");String s1=opsForValue.get("/sql");model.addAttribute("mainCount",s);model.addAttribute("sqlCount",s1);return "main";}else{//回到登录页面model.addAttribute("msg","请重新登录");return "login";}}

main.html文件

<div class="col-md-6 col-xs-12 col-sm-6"><div class="panel red"><div class="symbol"><i class="fa fa-tags"></i></div><div class="state-value"><div class="value" th:text="${sqlCount}">3490</div><div class="title">/sql.html</div></div></div></div></div><div class="row state-overview"><div class="col-md-6 col-xs-12 col-sm-6"><div class="panel blue"><div class="symbol"><i class="fa fa-money"></i></div><div class="state-value"><div class="value">22020</div><div class="title"> Total Revenue</div></div></div></div>

Springboot2数据访问相关推荐

  1. [SpringBoot2]数据访问_数据库场景的自动配置分析和整合测试

    数据访问 1.导入jdbc场景 <dependency><groupId>org.springframework.boot</groupId><artifac ...

  2. 002 第一季SpringBoot2核心技术-核心功能:配置文件、Web开发(原生组件)、数据访问、单元测试、指标监控、原理解析:@Value、命令行参数、手动获取bean、自定义starter

    三.核心技术之- ->核心功能 1. 配置文件 1.1 文件类型 1.1.1 properties 同以前的properties用法 优先级高于yml的方式. 1.1.2 yaml 1) 简介 ...

  3. boot访问resources下边的图片_SpringBoot系列之JDBC数据访问

    SpringBoot系列之JDBC数据访问 SpringBoot jdbc是比较常用的内容,本博客通过实验并简单跟源码的方式进行介绍,希望可以帮助学习者更好地理解 环境准备: IDEA Maven 先 ...

  4. SpringBoot实战系列——数据访问=(Mybatis+Redis)

    前言 在开发中我们通常会对数据库的数据进行操作,SpringBoot对关系性和非关系型数据库的访问操作都提供了非常好的整合支持.SpringData是spring提供的一个用于简化数据库访问.支持云服 ...

  5. DNN 数据访问策略 (转)

    经过几天断断续续的努力,这篇文章终于翻译结束,文章主要讲了DNN的数据访问策略,对于了解系统整体上是如何工作的有一定的帮助,希望能给dnn的初学者一些有用的信息.由于翻译的匆忙+水平有限,错误或不当之 ...

  6. Enterprise Library 4 数据访问应用程序块

    Enterprise Library 数据访问应用程序块简化了实现常规数据访问功能的开发任务.应用程序可以在各种场景中使用此应用程序块,例如为显示而读取数据.传递数据穿过应用程序层( applicat ...

  7. 写一个通用数据访问组件

    出处:http://www.csharp-corner.com willsound(翻译) 我收到过好多Email来问我如何用一个通用的数据提供者(data provider)在不失自然数据提供者(n ...

  8. 将 SQL Server 存储过程用于数据访问

    在 .NET Framework 提供的所有数据访问方法中,基于 SQL Server 的数据访问是生成高性能.可缩放 Web 应用程序的推荐选择.使用托管 SQL Server 提供程序时,可通过使 ...

  9. 多样化实现Windows phone 7本地数据访问5——深入Rapid Repository

    上一篇多样化实现Windows Phone 7本地数据访问<4>--Rapid Repository  中初步的介绍Repid Repository作为Windows phone 7数据库 ...

最新文章

  1. 设置作者_阿里Java开发手册建议创建HashMap时设置初始化容量,但多少合适
  2. 不允许 ASSIGNMENT 语句中包含 FOR XML 子句。
  3. container_of分析
  4. 汇编语言--8086CPU
  5. 矩阵从左上到右下的最短距离问题
  6. 一个基于C++的多线程编程实例(CreateThread函数)
  7. Spring Data REST API集成Springfox、Swagger
  8. ios开发--清理缓存
  9. You're currently running Fcitx with GUI 错误解决 Fcitx
  10. 无人机油动发动机调试
  11. mysql .idb_mysql.idb
  12. xmind文件不见了处理方法
  13. 分享高压超低噪声LDO测试结果(High Voltage Ultra-low Noise LDO)
  14. LabVIEW之TDMS学习笔记
  15. Zxing 生成二维码和条形码去掉白边
  16. 华为手机备份app从内部恢复
  17. MASM32开发COM组件【二】
  18. Http meta详解
  19. 再见了疯狂坦克 再见了游戏大厅
  20. 学习笔记之——基于matlab的数字通信系统(2)之离散信号的傅里叶分析

热门文章

  1. iQOO骑士黑版本四月亮相:搭载骁龙855+12G运存
  2. 抄袭路虎极光多年的陆风X7 终于迎来法院裁定:即刻停止生产
  3. 作为一个码农,必须知道的 Web 协议有哪些?
  4. 不用 Python 自带的 Dict 实现自己的 HashTable
  5. 数据库优化:优化查询
  6. Spring容器创建流程(6)国际化支持
  7. c语言一次绑定多个控件,一入前端深似海,从此红尘是路人系列第九弹之如何实现一个双向数据绑定...
  8. 嵌入式Linux入门7:kernel移植
  9. 简单的C语言开源软件,自己写的一个简单的数据库...完整开源...
  10. 【Flink】ORA-00923: FROM keyword not found where expected