「SpringBoot」05 数据访问

SpringBoot—数据访问

笔记整理自【尚硅谷】雷神SpringBoot2视频教程

SQL

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

Ⅰ. 导入JDBC场景

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

image.png

为什么导入JDBC场景,官方不导入数据库驱动?官方不知道我们接下要操作什么数据库。

数据库版本和驱动版本对应

<!-- 默认版本:SpringBoot2.7.1对应<mysql.version>8.0.29</mysql.version> -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

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

Ⅱ. 分析自动配置

自动配置的类

  • 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:事务管理器的自动配置。

  • JdbcTemplateAutoConfigurationJdbcTemplate的自动配置,可以来对数据库进行CRUD。

    ➢ 可以修改前缀为spring.jdbc的配置项来修改JdbcTemplate

    ➢ Spring容器中有这个JdbcTemplate组件,使用@Autowired

    @Bean
    @Primary
    JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) {
    	...
    }
    
  • JndiDataSourceAutoConfiguration:JNDI的自动配置。

  • XADataSourceAutoConfiguration:分布式事务相关的。

Ⅲ. 设置配置项

application.yaml

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

Ⅳ. 测试

@Slf4j
@SpringBootTest
class Boot05WebAdminApplicationTests {

	@Autowired
	JdbcTemplate jdbcTemplate;

	@Test
	void contextLoads() {
		Long aLong = jdbcTemplate.queryForObject("select count(*) from payment", Long.class);
		log.info("记录总数:{}", aLong);
	}
}

2. 使用Druid数据源

druid官方github地址

https://github.com/alibaba/druid

整合第三方技术的两种方式

  • 自定义
  • 找starter

Ⅰ. 自定义方式

添加依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.17</version>
</dependency>
1️⃣ 创建数据源
// 默认的自动配置是判断容器中没有才会配@ConditionalOnMissingBean(DataSource.class)
@ConfigurationProperties("spring.datasource") // 跟配置文件中的属性绑定
@Bean
public DataSource dataSource() {
    DruidDataSource druidDataSource = new DruidDataSource();
    return druidDataSource;
}
2️⃣ 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>
// 默认的自动配置是判断容器中没有才会配@ConditionalOnMissingBean(DataSource.class)
@ConfigurationProperties("spring.datasource") // 跟配置文件中的属性绑定
@Bean
public DataSource dataSource() throws SQLException {
    DruidDataSource druidDataSource = new DruidDataSource();
    druidDataSource.setFilters("stat"); // 加入监控功能
    return druidDataSource;
}

/**
 * 配置druid的监控页功能
 * @return
 */
@Bean
public ServletRegistrationBean statViewServlet() {
    StatViewServlet statViewServlet = new StatViewServlet();
    ServletRegistrationBean<StatViewServlet> registrationBean = new ServletRegistrationBean<>(statViewServlet, "/druid/*");
    
    // 监控页账号密码
    registrationBean.addInitParameter("loginUsername", "admin");
    registrationBean.addInitParameter("loginPassword"," 123456");
    
    return registrationBean;
}
3️⃣ StatFilter

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

<!-- 需要给数据源中配置如下属性;可以允许多个filter,多个用,分割;如: -->
<property name="filters" value="stat,slf4j" />
/**
 * WebStatFilter 用于采集web-jdbc关联监控的数据。
 */
@Bean
public 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;
}

系统中所有filter:

别名Filter类名
defaultcom.alibaba.druid.filter.stat.StatFilter
statcom.alibaba.druid.filter.stat.StatFilter
mergeStatcom.alibaba.druid.filter.stat.MergeStatFilter
encodingcom.alibaba.druid.filter.encoding.EncodingConvertFilter
log4jcom.alibaba.druid.filter.logging.Log4jFilter
log4j2com.alibaba.druid.filter.logging.Log4j2Filter
slf4jcom.alibaba.druid.filter.logging.Slf4jLogFilter
commonloggingcom.alibaba.druid.filter.logging.CommonsLogFilter

慢SQL记录配置

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

所有配置代码都可以直接在配置文件中进行配置。

Ⅱ. 使用官方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

  • 自动配置类 DruidDataSourceAutoConfigure

  • DruidSpringAopConfiguration.class, 监控SpringBean的;配置项:spring.datasource.druid.aop-patterns

  • DruidStatViewServletConfiguration.class, 监控页的配置。配置项:spring.datasource.druid.stat-view-servlet

    ➢ 默认为false,必须手动开启

    @ConditionalOnProperty(name = "spring.datasource.druid.stat-view-servlet.enabled", havingValue = "true")
    
  • DruidWebStatFilterConfiguration.class,web监控配置。配置项:spring.datasource.druid.web-stat-filter

    ➢ 默认为false,必须手动开启

    @ConditionalOnProperty(name = "spring.datasource.druid.web-stat-filter.enabled", havingValue = "true")
    
  • 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_account
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver

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

      stat-view-servlet:   # 配置监控页功能
        enabled: true
        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

3. 整合MyBatis操作

https://github.com/mybatis

  • 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>

Ⅰ. 配置模式

  • 全局配置文件

  • SqlSessionFactory:自动配置好了

  • SqlSession:自动配置了 SqlSessionTemplate 组合了 SqlSession

  • @Import(AutoConfiguredMapperScannerRegistrar.class)AutoConfiguredMapperScannerRegistrar

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

    @EnableConfigurationProperties(MybatisProperties.class) // MyBatis配置项绑定类。
    @AutoConfigureAfter({ DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class })
    public class MybatisAutoConfiguration {
        ...
    }
    
    @ConfigurationProperties(prefix = MybatisProperties.MYBATIS_PREFIX)
    public class MybatisProperties {				//   ↑ 
    												//   ↑
      public static final String MYBATIS_PREFIX = "mybatis";
    

    可以修改配置文件中 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>
        <!-- 所有的配置SpringBoot都自动配置好了 这里无需再写入内容 -->
    </configuration>
    
  • 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="com.aiguigu.admin.mapper.UserMapper">
    	<!-- public User getUser(Integer id); -->
        <select id="getUser" resultType="com.atguigu.admin.bean.User">
            select * from user where id=#{id}
        </select>
    </mapper>
    
  • Mapper接口

    @Mapper
    public interface UserMapper {
        public User getUser(Integer id);
    }
    
  • POJO

    public class User {
        private Integer id;
        private String name;
        
    	//getters and setters...
    }
    
  • Controller

    @Controller
    public class UserController {
    
        @Autowired
        private UserService userService;
    
        @ResponseBody
        @GetMapping("/user")
        public User getUser(@RequestParam("id") Integer id){
    
            return userService.getUser(id);
        }
    }
    
  • Service

    @Service
    public class UserService {
    
        @Autowired
        private UserMapper userMapper;
    
        public User getUser(Integer id){
            return userMapper.getUser(id);
        }
    }
    
  • 配置private Configuration configuration; 也就是配置mybatis.configuration相关的,就是相当于改mybatis全局配置文件中的值。(也就是说配置了mybatis.configuration,就不需配置mybatis全局配置文件了)

    # 配置mybatis规则
    mybatis:
      # 可以不写全局配置文件,所有全局配置文件的配置都放在configuration配置项中了。
      # config-location: classpath:mybatis/mybatis-config.xml
      mapper-locations: classpath:mybatis/mapper/*.xml
      configuration: # 指定MyBatis全局配置文件中的相关配置项
        map-underscore-to-camel-case: true # 开启驼峰命名规则匹配
    

小结

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

Ⅱ. 注解模式

纯注解 不需要xxxMapper.xml配置文件

@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")
    public void insert(City city);

}

Ⅲ. 混合模式

既有注解 也有配置文件

@Mapper
public interface CityMapper {

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

    public void insert(City city); // sql写在CityMapper.xml中

}

CityMapper.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.aiguigu.admin.mapper.UserMapper">
	<!-- 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注解

    @MapperScan("com.atguigu.admin.mapper") // 写在主配置类中 扫描mapper包下的所有类
    @SpringBootApplication
    public class Boot05WebAdminApplication {
    
       public static void main(String[] args) {
          SpringApplication.run(Boot05WebAdminApplication.class, args);
       }
    
    }
    

4. 整合 MyBatis-Plus 完成 CRUD

Ⅰ. 什么是MyBatis-Plus

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

MyBatis-Plus 官网

建议安装 MybatisX 插件

Ⅱ. 整合MyBatis-Plus

快速开始

引入依赖

<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(核心组件) 自动配置好,底层是容器中默认的数据源。
  • SqlSessionFactory自动配置好,底层是容器中默认的数据源。
  • mapperLocations自动配置好的,有默认值classpath*:/mapper/**/*.xml,这表示任意包的类路径下的所有mapper文件夹下任意路径下的所有xml都是sql映射文件;建议以后sql映射文件放在mapper下。
  • 容器中也自动配置好了SqlSessionTemplate
  • @Mapper标注的接口也会被自动扫描,建议直接@MapperScan("com.lun.boot.mapper")批量扫描。

优点

  • 只需要我们的Mapper继承MyBatisPlus的 BaseMapper 就可以拥有CRUD能力,减轻开发工作。

    public interface UserMapper extends BaseMapper<User> {
    
    }
    

代码构建

  • 实体类

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
    
        // 只要写在实体类中的数据 都应该在数据库中存在 所以此时不需要的属性即可加上MyBatis-plus的@TableField注解
        @TableField(exist = false)
        private String userName;
        @TableField(exist = false)
        private String password;
    
        // 以下是数据库字段
        private Long id;
        private String name;
        private Integer age;
        private String email;
        
    }
    
  • UserMapper

    /**
     * 只需要继承BaseMapper即可直接调用CRUD方法
     */
    public interface UserMapper extends BaseMapper<User> {
    
    }
    
  • Test

    @Autowired
    UserMapper userMapper;
    
    @Test
    void testUserMapper() {
       User user = userMapper.selectById(1L);
       log.info("用户信息:{}", user);
    }
    

    image-20220724185006539

Ⅲ. CRUD功能

1️⃣ 数据列表展示
  • UserService

    /**
     * 继承顶级 Service
     */
    public interface UserService extends IService<User> {
    
    }
    
  • UserServiceImpl

    /**
     * 继承 IService 实现类( 泛型:M 是 mapper 对象,T 是实体 )
     */
    @Service
    public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
        // 什么方法都不用写 方法都在MyBatis-plus提供的ServiceImpl类中写好了
    }
    
  • Controller

    @GetMapping("/dynamic_table")
    public String dynamic_table(Model model) {
        // 从数据库中查出user表中的用户进行展示
        List<User> list = userService.list();
        model.addAttribute("users", list);
        return "table/dynamic_table";
    }
    
  • 修改前端页面

    <tr>
        <th>#</th>
        <th>id</th>
        <th>name</th>
        <th>ages</th>
        <th>email</th>
        <th>操作</th>
    </tr>
    </thead>
    <tbody>
    <tr class="gradeX" th:each="user,stat:${users}">
        <td th:text="${stat.count}">Trident</td>
        <td th:text="${user.id}">id</td>
        <td th:text="${user.name}">Internet
            Explorer 4.0
        </td>
        <td th:text="${user.age}"></td>
        <td class="center hidden-phone">[[${user.email}]]</td>
        <td class="center hidden-phone">X</td>
    </tr>
    

    展示成功

    image-20220724211153202

2️⃣ 分页功能实现
  • 整合分页插件

    配置类MyBatisConfig

    @Configuration
    public class MyBatisConfig {
    
        /**
         * MybatisPlusInterceptor
         * @return
         */
        @Bean
        public MybatisPlusInterceptor paginationInterceptor() {
            MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
            // MyBatis-plus3.4版本以后的分页拦截器
            PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
            // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
            // paginationInterceptor.setOverflow(false);
            paginationInnerInterceptor.setOverflow(true);
            // 设置最大单页限制数量,默认 500 条,-1 不受限制
            // paginationInterceptor.setLimit(500);
            paginationInnerInterceptor.setMaxLimit(500L);
            mybatisPlusInterceptor.addInnerInterceptor(paginationInnerInterceptor);
    
            return mybatisPlusInterceptor;
        }
    }
    
  • 给Controller增加分页功能

    @GetMapping("/dynamic_table")
    public String dynamic_table(@RequestParam(value = "pn", defaultValue = "1") Integer pn, Model model) {
        // 从数据库中查出user表中的用户进行展示
        List<User> list = userService.list();
        //model.addAttribute("users", list);
        // 分页查询数据
        Page<User> userPage = new Page<>(pn, 2);
        // 分页查询的结果
        Page<User> page = userService.page(userPage, null);
        model.addAttribute("page", page);
        return "table/dynamic_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="#">← 前一页</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 disabled"><a href="#">下一页 → </a></li>
                </ul>
            </div>
        </div>
    </div>
    

    分页成功

    image-20220724220325020

    image-20220724220336792

3️⃣ 删除功能实现
  • 增加删除button

    <td>
        <a
           th:href="@{/user/delete/{id}(id=${user.id},pn=${page.current})}"
           class="btn btn-danger btn-sm"
           type="button">
            删除
        </a>
    </td>
    
  • Controller

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

    image-20220724225112027

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>

image.png

自动配置

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

Redis环境搭建

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

  • 申请Redis的公网连接地址。

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

2. RedisTemplate与Lettuce

  • 配置文件

    spring:
      redis:
        host: r-bp1nc7reqesxisgxpipd.redis.rds.aliyuncs.com
        port: 6379
        password: lfy:Lfy123456
    
  • Test

    @Autowired
    StringRedisTemplate redisTemplate;
    
    @Test
    void testRedis() {
        ValueOperations<String, String> operations = redisTemplate.opsForValue();
    
        operations.set("hello", "world");
    
        String hello = operations.get("hello");
        System.out.println(hello);
    }
    

3. 切换至jedis

  • 导入jedis

    <dependency>
       <groupId>redis.clients</groupId>
       <artifactId>jedis</artifactId>
    </dependency>
    
  • 配置文件标明客户端类型为jedis

    spring:
      redis:
        host: r-bp1nc7reqesxisgxpipd.redis.rds.aliyuncs.com
        port: 6379
        password: lfy:Lfy123456
        client-type: jedis
    
  • Test

    @Autowired
    RedisConnectionFactory redisConnectionFactory;
    
    @Test
    void testRedis(){
        // org.springframework.data.redis.connection.jedis.JedisConnectionFactory
        System.out.println(redisConnectionFactory.getClass());
    }
    

拓展

利用Redis实现一个URL统计功能

  • URL统计拦截器

    @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;
        }
    }
    
  • 注册URL统计拦截器

    @Configuration
    public class AdminWebConfig implements WebMvcConfigurer {
    
        @Autowired
        RedisUrlCountInterceptor redisUrlCountInterceptor;
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
    
            registry.addInterceptor(redisUrlCountInterceptor)
                    .addPathPatterns("/**")
                    .excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**",
                            "/js/**","/aa/**");
        }
    }
    

    image-20220725121723182

  • 调用Redis内的统计数据

    @Slf4j
    @Controller
    public class IndexController {
    
    	@Autowired
        StringRedisTemplate redisTemplate;
        
    	@GetMapping("/main.html")
        public String mainPage(HttpSession session, Model model) {
    
            log.info("当前方法是:{}", "mainPage");
    
            ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
    
            String s = opsForValue.get("/main.html"); // 获取main.html页面访问的次数
            String s1 = opsForValue.get("/sql");      // 获取sql请求访问的次数
    
            model.addAttribute("mainCount", s);
            model.addAttribute("sqlCount", s1);
    
            return "main";
        }
    }
    
  • 修改前端页面

    <div class="col-md-6 col-xs-12 col-sm-6">
        <div class="panel purple">
            <div class="symbol">
                <i class="fa fa-gavel"></i>
            </div>
            <div class="state-value">
                <div class="value" th:text="${mainCount}">230</div>
                <div class="title">/main.html</div>
            </div>
        </div>
    </div>
    <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</div>
            </div>
        </div>
    </div>
    

    功能实现

    image-20220725122338738

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

  • Filter是Servlet定义的原生组件,好处:脱离Spring应用也能使用。
  • Interceptor是Spring定义的接口,可以使用Spring的自动装配等功能。
  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小成同学_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值