一、连接操作redis

Spring Boot中操作redis还是需要使用相关的启动器

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

按照之前的逻辑 我们还是要分析一下这个启动器的自动配置类RedisAutoConfiguration做了什么

@AutoConfiguration
@ConditionalOnClass({RedisOperations.class})
// 将spring.redis开头的配置和redis进行绑定
@EnableConfigurationProperties({RedisProperties.class})
// 引入了两个redis连接客户端,Lettuce(启动器默认使用)和Jedis的连接配置类
@Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})
public class RedisAutoConfiguration {
    public RedisAutoConfiguration() {
    }

	// 注入redisTemplate类,认定key-value都是Object类型
    @Bean
    @ConditionalOnMissingBean(
        name = {"redisTemplate"}
    )
    @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

	// 注入StringRedisTemplate类,认定key-value都是String类型
    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        return new StringRedisTemplate(redisConnectionFactory);
    }
}

分析完之后,我们就可以通过一个简单的demo,来了解Spring Boot是如何连接操作redis的

首先,我们先设置一下redis客户端的防火墙,要打开6379端口

firewall-cmd --list-port # 查看所有的开放的端口号

firewall-cmd --zone=public --add-port=6379/tcp --permanent #将6379端口加入防火墙

systemctl stop firewalld.service #停止firewall

systemctl start firewalld.service #打开firewall

如果不使用Lettuce连接redis,使用Jedis,我们还需要导入相关依赖

<dependency>
	<groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
</dependency>

然后在配置文件中配置相关连接参数

spring:
    redis:
      host: 192.168.153.128
      port: 6379
      client-type: jedis
      jedis:
        pool:
          max-active: 10
#     username: 用户名
#     password: 密码

最后测试一下对redis的set和get操作
我们创建一个拦截器,将每次请求的访问路径当作key,访问次数当作value放入redis中

package com.decade.interceptor;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class RedisInterceptor implements HandlerInterceptor {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 获取请求路径,把它当作key,每请求一次,这个key对应的value就自增1
        final String requestURI = request.getRequestURI();
        stringRedisTemplate.opsForValue().increment(requestURI);

        return true;
    }
}

将这个拦截器通过之前的配置类注册到容器中
我们还考虑了一下filter和interceptor的区别

package com.decade.config;

import com.decade.interceptor.LoginInterceptor;
import com.decade.interceptor.RedisInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
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 MyConfig implements WebMvcConfigurer {

	/**
     * filter和interceptor的功能类似,这两者的区别在哪?
     * filter:它是servlet定义的原生组件,脱离了spring也可以使用
     * interceptor:它是spring定义的接口,可以使用spring的自动装配等功能
     */
    @Autowired
    private RedisInterceptor redisInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // addPathPatterns:设置要拦截的请求,如果是/**,那么会拦截包括静态资源在内的所有请求
        // excludePathPatterns:设置不被拦截的请求,这里我们放行登录页请求和静态资源
        registry.addInterceptor(new LoginInterceptor())
            .addPathPatterns("/**")
            .excludePathPatterns("/", "/login", "/css/**", "/images/**", "/js/**", "/fonts/**");
        // 这里不能使用new来实例化,因为RedisInterceptor中使用了@Autowired注解,自己new的对象没被spring管理,所以它不会自动进行依赖注入,所以这里应该从容器中拿
        registry.addInterceptor(redisInterceptor)
            .addPathPatterns("/**")
            .excludePathPatterns("/", "/login", "/css/**", "/images/**", "/js/**", "/fonts/**");
    }

最后,在首页相关的接口中获取访问次数,并打印出来

package com.decade.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import javax.servlet.http.HttpSession;

@Controller
@Slf4j
public class IndexController {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 去main页面
     * @return 跳转主页面
     */
    @GetMapping("/main.html")
    public String mainPage(HttpSession session,Model model){
        final ValueOperations opsForValue = stringRedisTemplate.opsForValue();
        final Object visitTimes = opsForValue.get("/main.html");
        log.info("访问首页次数为:{}", visitTimes);
        return "main";
    }
}

访问几次首页之后,后端打印结果如下

java使用redis多条件组合查询_redis

redis客户端查询结果如下

java使用redis多条件组合查询_spring boot_02

注意:如果出现报错如下报错

org.springframework.dao.InvalidDataAccessApiUsageException: 
DENIED Redis is running in protected mode because protected mode is enabled and no password is set for the default user...

这就说明,redis处于保护模式,这是默认开启的,报错信息中会提供好几种解决方式
因为博主虚拟机上的redis只有自己使用,所以选择了比较省事的一种,那就是关掉保护模式

在redis.conf中搜索protected-mode,将后面的值设置为no即可

java使用redis多条件组合查询_java_03

另外,我们还需要将6379端口加入防火墙白名单(已在上方写出)

再检查bind设置,如果绑定的是本机IP,需要将那一行注掉

然后重启redis服务

java使用redis多条件组合查询_java_04

如有错误,欢迎指正!!!