06、数据访问

06、数据访问

1、SQL

1、数据源的自动配置-HikariDataSource

1、导入JDBC场景

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

img

数据库驱动?

为什么导入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>

2、分析自动配置

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(Spring提供的一个操作数据库的小工具)的自动配置,可以来对数据库进行crud

    • 可以修改这个配置项@ConfigurationProperties(prefix = “spring.jdbc”) 来修改JdbcTemplate
    • @Bean @Primary JdbcTemplate底层已经向容器中加入了这个组件.需要使用时直接使用@Autowired注入.
  • JndiDataSourceAutoConfiguration: jndi的自动配置

  • XADataSourceAutoConfiguration: 分布式事务相关的

3、修改配置项

spring:
  datasource:
    url: jdbc:mysql:///bookstore
    username: root
    password: 186259
    driver-class-name: com.mysql.jdbc.Driver

4、测试

@SpringBootTest
class Boot05AdminApplicationTests {
    
    
    @Autowired  //底层已经注入该组件,直接拿来用.
    private JdbcTemplate jdbcTemplate;

    @Test
    void contextLoads() {
    
    
        Integer count = jdbcTemplate.queryForObject("select count(*) from account", Integer.class);
        System.out.println(count);
    }

}

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 {
    
    

    //默认的自动配置是判断容器中没有才会配 HikariDataSource连接池.==>@ConditionalOnMissingBean(DataSource.class)
    @ConfigurationProperties("spring.datasource") //将该配置文件的值与数据源进行绑定
    @Bean
    public DataSource dataSource() throws SQLException {
    
    
        DruidDataSource druidDataSource = new DruidDataSource();
        // 打开Druid的监控统计功能. 开启防火墙.
        //druidDataSource.setFilters("stat,wall");
        return druidDataSource;
    }

2、使用Druid的内置监控页面(配置StatViewServlet)

官方文档========================================

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
     */
    @Bean
    public ServletRegistrationBean statViewServlet(){
    
    
        StatViewServlet statViewServlet = new StatViewServlet();
        ServletRegistrationBean<StatViewServlet> registrationBean = new ServletRegistrationBean<>(statViewServlet, "/druid/*");
        //配置用户名,密码
        registrationBean.addInitParameter("loginUsername","admin");
        registrationBean.addInitParameter("loginPassword","admin");
        return registrationBean;

    }

3、打开Druid的监控统计功能(StatFilter)

官方文档

在spring中使用别名配置方式如下:

  <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
  	... ...
  	<property name="filters" value="stat" />
  </bean>

实现代码:

向DataSource数据源配置中加入:

druidDataSource.setFilters("stat");//打开Druid的监控统计功能

4.配置内置的Web监控

官方文档===============

WebStatFilter用于采集web-jdbc关联监控的数据。(如JDBC语句,请求次数,请求时间…)

web.xml配置

  <filter>
  	<filter-name>DruidWebStatFilter</filter-name>
  	<filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
  	<init-param>
  		<param-name>exclusions</param-name>
  		<param-value>*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*</param-value>
  	</init-param>
  </filter>
  <filter-mapping>
  	<filter-name>DruidWebStatFilter</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>
 /**
     * webStatFilter用于采集web-jdbc关联监控的数据.
     * @return
     */
    @Bean
    public FilterRegistrationBean webStatFilter(){
    
    
        WebStatFilter webStatFilter = new WebStatFilter();

        FilterRegistrationBean <WebStatFilter> registrationBean = new FilterRegistrationBean <WebStatFilter>(webStatFilter);
        registrationBean.setUrlPatterns(Arrays.asList("/*"));
        registrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");

        return registrationBean;
    }

5.配置防御SQL注入攻击(防火墙)

=官方文档

使用缺省配置的WallFilter

  <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
      ...
      <property name="filters" value="wall"/>
  </bean>

实现代码:

向DataSource数据源配置中加入:

druidDataSource.setFilters("wall");//打开Druid的防火墙功能

以上的关于Spring数据源的配置都可以在配置文件中进行配置.

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

需要给数据源中配置如下属性;可以允许多个filter,多个用,分割;如:

<property name="filters" value="stat,slf4j" />

系统中所有filter:

别名 Filter类名
default com.alibaba.druid.filter.stat.StatFilter
stat com.alibaba.druid.filter.stat.StatFilter
mergeStat com.alibaba.druid.filter.stat.MergeStatFilter
encoding com.alibaba.druid.filter.encoding.EncodingConvertFilter
log4j com.alibaba.druid.filter.logging.Log4jFilter
log4j2 com.alibaba.druid.filter.logging.Log4j2Filter
slf4j com.alibaba.druid.filter.logging.Slf4jLogFilter
commonlogging com.alibaba.druid.filter.logging.CommonsLogFilter

慢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、分析自动配置

DruidDataSourceAutoConfigure

@Configuration
@ConditionalOnClass(DruidDataSource.class)
@AutoConfigureBefore(DataSourceAutoConfiguration.class) // 在DataSourceAutoConfiguration之前进行生效,这样使用的就是DruidDataSource
@EnableConfigurationProperties({
    
    DruidStatProperties.class, DataSourceProperties.class})
@Import({
    
    DruidSpringAopConfiguration.class,
    DruidStatViewServletConfiguration.class,
    DruidWebStatFilterConfiguration.class,
    DruidFilterConfiguration.class})
public class DruidDataSourceAutoConfigure {
    
    
  • 扩展配置项 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";//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";//slf4j
    private static final String FILTER_LOG4J_PREFIX = "spring.datasource.druid.filter.log4j";//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";//wall

3、配置示例

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/db_account
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver

    druid:
      aop-patterns: com.atguigu.admin.*  #监控SpringBean
      filters: stat,wall     # 底层开启功能,stat(sql监控),wall(防火墙)

      stat-view-servlet:   # 配置监控页功能
        enabled: true     # 进行开启,默认为false.
        login-username: admin
        login-password: admin
        resetEnable: false

      web-stat-filter:  # 监控web
        enabled: true
        urlPattern: /* # 过滤的路径
        exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'  # 排除路径


      filter:
        stat:    # 对上面filters里面的stat的详细配置
          slow-sql-millis: 1000
          logSlowSql: true
          enabled: true
        wall:
          enabled: true
          config:
            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 MyBatis属于第三方…

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

img

1、配置模式

之前我们使用Mybatis的方式:

  • 编写全局配置文件—>SqlMapConfig.xml

  • 创建SqlSessionFactory:

  • 获取SqlSession

  • 编写Mapper接口.

现在所有的配置都在MybatisAutoConfiguration中.

  • SqlSessionFactoryMybatisAutoConfiguration自动配置好了.也自动配置了 SqlSessionTemplate,内部 组合了SqlSession.

  • AutoConfiguredMapperScannerRegistrar:处理我们的Mapper, 只要我们写的操作MyBatis的接口标注了 @Mapper 就会被自动扫描进来

@ConditionalOnClass({
    
     SqlSessionFactory.class, SqlSessionFactoryBean.class })//这些都是Mybatis中的,当导入Mybatis依赖后才会生效.
@ConditionalOnSingleCandidate(DataSource.class) //使用咱们Druid的
@EnableConfigurationProperties(MybatisProperties.class) //Mybatis配置项绑定类
@AutoConfigureAfter({
    
     DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class })
public class MybatisAutoConfiguration implements InitializingBean {
    
    
    @Bean
  @ConditionalOnMissingBean
  public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
    
    ...}
    @Bean
  @ConditionalOnMissingBean
  public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
    
    ...}
    public static class AutoConfiguredMapperScannerRegistrar implements BeanFactoryAware, ImportBeanDefinitionRegistrar {
    
    
        ...
    }

}
  • MyBatis的所有配置项都以mybatis开头,全局配置都以mybatis.configuration.XXX开头.

测试代码:

#########################################Account######################################
@Data
public class Account {
    
    
    private Long id;
    private String userId;
    private Integer money;
}
###########################################IndexController###########################
@Slf4j
@Controller
public class IndexController {
    
    


    @Autowired
    AccountService accountService;

    @ResponseBody
    @GetMapping("/acct")
    public Account getById(@RequestParam("id") Long id){
    
    
        return accountService.getAcctById(id);
    }
}
##############################AccountService####################################
public interface AccountService {
    
    

    public Account getAcctById(Long id);
}

@Service
public class AccountServiceImpl implements AccountService {
    
    

    @Autowired
    AccountMapper accountMapper;

    @Override
    public Account getAcctById(Long id) {
    
    
        return accountMapper.getAcct(id);
    }
}

配置文件:

####################################AccountMapper.xml################################

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.rg.admin.mapper.AccountMapper">
    <select id="getAcct" resultType="com.rg.admin.bean.Account">
        select * from account where id = #{id}
    </select>
</mapper>
###########################################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>
    <!--<settings>-->
    <!--    <setting name="mapUnderscoreToCamelCase" value="true"/>-->
    <!--</settings>-->
    <!--开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。-->

</configuration>


#################################application.yaml################################
spring:
  datasource:
    url: jdbc:mysql:///test
    username: root
    password: 186259
    driver-class-name: com.mysql.jdbc.Driver

mybatis:
#  config-location: classpath:mybatis/mybatis-config.xml #全局配置文件位置
  mapper-locations: classpath:mybatis/mapper/*.xml  #sql映射文件位置
  configuration:
    map-underscore-to-camel-case: true # 开启驼峰命名自动映射(在数据库中映射为_)

# 可以不写全局配置文件;所有全局配置文件的配置都放在configuration配置项中即可

注:配置mybatis.configuration下面的所有,就是相当于改mybatis全局配置文件中的值

SpringBoot整合MyBatis开发步骤总结:

  • 导入mybatis官方starter

  • 编写mapper接口。标准@Mapper注解

  • 编写sql映射文件并绑定mapper接口

  • 在application.yaml中指定Mapper配置文件的位置,以及指定全局配置文件的信息 (建议;配置在mybatis.configuration

2、注解模式 及混合模式

@Mapper
public interface CityMapper {
    
    

    @Select("select * from city where id = #{id}")
    public City getById(Long id);

    // @Insert("insert into  city(`name`,`state`,`country`) values(#{name},#{state},#{country})")
    // @Options(useGeneratedKeys = true,keyProperty = "id")
     // MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键并封装到city中
    public void saveCity(City city);


}


<?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.atguigu.admin.mapper.CityMapper">

    public void insert(City city);
    <insert id="insert" useGeneratedKeys="true" keyProperty="id">
        insert into  city(`name`,`state`,`country`) values(#{name},#{state},#{country})
    </insert>

</mapper>

最佳实战:

  • 引入mybatis-starter

  • 配置application.yaml中,指定mapper-location位置即可

  • 编写Mapper接口并标注@Mapper注解

  • 简单方法直接注解方式

  • 复杂方法编写mapper.xml进行绑定映射

  • *@MapperScan(“com.atguigu.admin.mapper”) *简化,其他的接口就可以不用标注@Mapper注解

4、整合 MyBatis-Plus 完成CRUD

1、什么是MyBatis-Plus

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

mybatis plus 官网

建议安装 MybatisX 插件

2、整合MyBatis-Plus

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.1</version>
        </dependency>
里面包含着MybatisPlusAutoConfiguration ,Mybatis核心包,jdbc操作数据库的包,mybatis-spring整合包.

自动配置

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

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

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

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

  • @Mapper 标注的接口也会被自动扫描;建议直接 @MapperScan(“com.atguigu.admin.mapper”) 批量扫描就行

优点:

  • 只需要我们的Mapper继承 BaseMapper 就可以拥有crud能力

3、CRUD功能测试

#########################################UserMapper###############################
//UserMapper
public interface UserMapper extends BaseMapper<User> {
    
    
} 

####################################UserService#######################################
public interface UserService extends IService<User> {
    
    //T:定义要操作的数据表的实体.
}
@Service
//ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> M要操作的Mapper类,T:对应的实体.
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService  {
    
    
}
###############################controller#############################################
//表格数据显示
    @GetMapping("/dynamic_table")
    public String dynamic_table(@RequestParam(value = "pn",defaultValue = "1") Integer pn, Model model){
    
    
        //分页查询数据
        Page <User> userPage = new Page <>(pn, 2);
        Page <User> page = userService.page(userPage, null);//分页查询结果.
        //long pages = page.getPages();
       // long current = page.getCurrent();
       // List <User> records = page.getRecords();
        model.addAttribute("page", page);


        return "table/dynamic_table";
    }

//删除用户逻辑
@GetMapping("/user/delete/{id}")
    public String deleteUser(@PathVariable("id") Long id, @RequestParam(value = "pn",defaultValue = "1") Integer pn,
                             RedirectAttributes ra){
    
    //RedirectAttributes 重定向携带的数据.
        userService.removeById(id);
        ra.addAttribute("pn", pn);// 会拼在转发路径后面..
        return "redirect:/dynamic_table";
    }
//


静态页面dynamic_table.html

 <div class="panel-body">
                            <div class="adv-table">
                                <table class="display table table-bordered" id="hidden-table-info">
                                    <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,status:${page.records}">
                                        <td th:text="${status.count}">Trident</td>
                                        <td th:text="${user.id}"></td>
                                        <td th:text="${user.name}">Win 95+</td>
                                        <td th:text="${user.age}">4</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>
                                </table>
                               <!--  分页代码  -->
                                <div class="row-fluid">
                                    <div class="span6">
                                        <div class="dataTables_info" id="hidden-table-info_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>
                                                <!--  单击之后跳转到指定页  -->
                                                <li th: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>
                        </div>

效果展示:

在这里插入图片描述

2、NoSQL

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings)散列(hashes)列表(lists)集合(sets)有序集合(sorted sets) 与范围查询, bitmapshyperloglogs地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication)LUA脚本(Lua scripting)LRU驱动事件(LRU eviction)事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

1、Redis自动配置

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

img

自动配置:

  • RedisAutoConfiguration 自动配置类。RedisProperties 属性类 --> spring.redis.xxx是对redis的配置

  • 连接工厂是准备好的。LettuceConnectionConfiguration、JedisConnectionConfiguration

  • 自动注入了RedisTemplate<Object, Object> : xxxTemplate都是工具类;

  • 自动注入了StringRedisTemplate;k:v都是String

  • 底层只要我们使用 StringRedisTemplate、RedisTemplate就可以操作redis

redis环境搭建

1、阿里云按量付费redis。经典网络

2、申请redis的公网连接地址

3、修改白名单 允许0.0.0.0/0 访问

有个默认账号,当然也可以申请多个账号.

使用完后要记得释放下…

2、RedisTemplate与Lettuce

    @Test
    void testRedis(){
    
    
        ValueOperations<String, String> operations = redisTemplate.opsForValue();

        operations.set("hello","world");

        String hello = operations.get("hello");
        System.out.println(hello);
    }

3、切换至jedis

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

<!--        导入jedis客户端操作redis(因为默认还有Lettuce也可以进行操作.)-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
spring:
  redis:
#    redis://user:[email protected]:6379
    url: redis://lxy:[email protected]:6379
    jedis:
      pool:
        max-active: 10 # 最大活跃数

案例:显示main.html以及sql的访问次数到main页面.

#################################Interceptor########################################
@Component
public class RedisUrlCountInterceptor implements HandlerInterceptor {
    
    
    @Autowired
    StringRedisTemplate redisTemplate;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
    
        String uri = request.getRequestURI();
        //默认每次访问当前uri就会计数+1
        redisTemplate.opsForValue().increment(uri);

        return true;
    }
}
#######################################WebMvcConfigurer############################
@Configuration
public class AdminWebConfig implements WebMvcConfigurer {
    
    
    /**
     * Filter、Interceptor 几乎拥有相同的功能?
     * 1、Filter是Servlet定义的原生组件。好处,脱离Spring应用也能使用
     * 2、Interceptor是Spring定义的接口。可以使用Spring的自动装配等功能
     *
     */
 @Autowired
    RedisUrlCountInterceptor redisUrlCountInterceptor;
@Override
    public void addInterceptors(InterceptorRegistry registry) {
    
    
        registry.addInterceptor(new LoginInterceptor()) //登录注册拦截器
                .addPathPatterns("/**")// 所有的请求都被拦截器拦截,包括静态资源  /**中 * 单级目录,/**代表多级目录.不能直接使用/*/*
                .excludePathPatterns("/", "/login","/error", "/css/**", "/fonts/**", "/images/**", "/js/**");//放行的请求.

        //这里一定要使用注入的,使用new 的,里面的东西都为空...
        registry.addInterceptor(redisUrlCountInterceptor).addPathPatterns("/**")
                .excludePathPatterns("/", "/login","/error", "/css/**", "/fonts/**", "/images/**", "/js/**");
    }
}
################################Controller##########################################
@Slf4j
@Controller
public class IndexController {
    
    
   @GetMapping("/main.html")
    public String mainPage(HttpSession session,Model model){
    
    
        log.info("当前方法是:{}","mainPage");
        // // 是否登录  拦截器,过滤器
        // Object loginUser = session.getAttribute("loginUser");
        // if(loginUser!=null){
    
    
        //     return "main";
        // }else{
    
    
        //     //回到登录页面
        //     model.addAttribute("msg","请重新登录");
        //     return "login";
        // }

        ValueOperations <String, String> operations = redisTemplate.opsForValue();
        String s = operations.get("/main.html");
        String s1 = operations.get("/sql");
        model.addAttribute("mainCount", s);
        model.addAttribute("sqlCount", s1);
        return "main";
        //这中间的所有拦截操作,可以交给拦截器来搞.

    }
}

###########################main.html###############################################
  <div class="col-xs-8">
      <span class="state-title" th:text="${mainCount}">  New Order  </span>
       <h4>\main.html</h4>
 </div>
          
<div class="col-xs-8">
     <span class="state-title" th:text="${sqlCount}">  Unique Visitors  </span>
       <h4>/sql</h4>
 </div>

运行结果:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/LXYDSF/article/details/120689092