springboot连接redis的去中心集群模式

1、连接前需要做的操作

  • redis已经配置好去中心集群模式
  • 释放了端口号

2、springboot连接redis。我搭建的是一个springboot+mybaits-plus的工程

  • 使用redisTemplate该类可以存放任意数据类型的数据,但是该类型的数据必须实现序列化,获取redis对应的数据时,会进行序列化
    (1)、导入所需依赖
 <dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.18</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.3.0</version>
        </dependency>

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

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

(2)、编写配置类

  • jdk的序列化方式存储的内容会很大,而且以二进制的形式进行存储,看不懂,可以换成其他的序列化方式,比如下面的String序列化方式,jackson序列化方式等等

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setConnectionFactory(factory);
        //key序列化方式
        template.setKeySerializer(redisSerializer);
        //value序列化
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //value hashmap序列化
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        return template;
    }
}

(3)、编写Controller层


@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    /**
     * 根据id查询用户
     * @param userId
     * @return
     */
    @GetMapping("/findUserById/{userId}")
    public User findUserById(@PathVariable("userId")Integer userId){
        return userService.findUserById(userId);
    }

    /**
     * 跟新用户信息
     * @param user
     * @return
     */
    @GetMapping("/updateUser")
    public User updateUser(User user){
        return userService.updateUser(user);
    }

    /**
     * 根据id删除用户
     * @param userid
     * @return
     */
    @GetMapping("/deleteUserById/{userId}")
    public int deleteUserById(@PathVariable("userId") Integer userid){
        return userService.deleteUserById(userid);
    }
}

(4)、编写service类

@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserDao userDao;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public User findUserById(Integer userid) {
        ValueOperations valueOperations = redisTemplate.opsForValue();
        //查询redis缓存中是否含有与之比配的key,如果有,则直接从redis缓存中拿
        Object o = valueOperations.get("findUserById::" + userid);
        if (o!=null){
            return (User)o;
        }
        //如果redis缓存中没有,则去数据库中,并且将查询出来的数据放在缓存中
        User user = userDao.selectById(userid);
        valueOperations.set("findUserById::"+userid,user);
        return user;
    }

    @Override
    public User updateUser(User user) {
        //使用跟新操作的时候,会先把redis里面的缓存先删除,然后根据操作完成之后,再将新的数据放到redis缓存中
        redisTemplate.delete("findUserById::"+user.getId());
        int i = userDao.updateById(user);
        redisTemplate.opsForValue().set("findUserById::"+user.getId(),user);
        return user;
    }

    @Override
    public int deleteUserById(Integer userid) {
        //删除数据库的内容后,也将redis的存在redis里的缓存删除
        int i = userDao.deleteById(userid);
        redisTemplate.delete("findUserById::"+userid);
        return i;
    }


}

(5)、编写实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("t_user")
public class User {
    @TableField
    private Integer id;
    private String username;
    private String password;
    private String phone;
    private String address;
}

(6)、编写dao层

public interface UserDao extends BaseMapper<User> {
}

(6)、修改配置文件,连接redis

server.port=8888

spring.datasource.druid.username=root
spring.datasource.druid.password=root
spring.datasource.druid.url=jdbc:mysql:///fuxi2
spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver


logging.level.com.kai.dao=debug

spring.redis.cluster.nodes=192.168.31.78:8001,192.168.31.78:8002,192.168.31.78:8003,192.168.31.78:8004,192.168.31.78:8005,192.168.31.78:8006


3、使用缓存注解进行配置

(1)、需要修改上面的配置类的内容,改成如下的内容

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setConnectionFactory(factory);
        //key序列化方式
        template.setKeySerializer(redisSerializer);
        //value序列化
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //value hashmap序列化
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        return template;
    }

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        //解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        // 配置序列化(解决乱码的问题),过期时间600秒
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600)) //缓存过期10分钟 ---- 业务需求。
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))//设置key的序列化方式
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)) //设置value的序列化
                .disableCachingNullValues();
        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        return cacheManager;
    }
}

(2)、修改service层

@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserDao userDao;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    //该注解的作用是:会先去redis缓存中查询是否存在所需要的数据,
    // 如果存在,则不执行代码块,直接返回缓存中的数据,
    // 如果redis缓存中不存在所需数据,则执行该方法,并将查询的数据放入redis缓存中。
    //缓存中的key默认以 findUserById::userid拼接起来
    @Cacheable(cacheNames = "findUserById" ,key = "#userid")
    public User findUserById(Integer userid) {
        User user = userDao.selectById(userid);
        return user;
    }

    @Override
    //这个注解是必须执行方法体,而且会把方法体执行的结果放入到缓存中。 如果发生异常则不操作缓存。
    @CachePut(cacheNames = "findUserById",key = "#user.id")
    public User updateUser(User user) {
        int i = userDao.updateById(user);
        return user;
    }

    @Override

    //beforeInvocation:默认为false,是否在方法执行前就清空,
    // 如果指定为 true,则在方法还没有执行的时候就清空缓存。如果为false且方法执行抛出异常,则不会清空缓存。
    @CacheEvict(cacheNames = "findUserById",key = "#userid")
    public int deleteUserById(Integer userid) {
        return userDao.deleteById(userid);
    }


}

(3)、开启redis缓存注解,在启动类上加如下注解

@EnableCaching

版权声明:本文为Harrycheng1原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。