SpringBoot实战项目学习(11)——集成Redis缓存

文章目录

  • 项目结构
  • pom.xml
  • application.yml
  • 实体类User
  • service层
    • 用户接口UserService
    • 实现类UserServiceImpl
    • 与缓存有关的常用注解
  • 测试类
    • UserServiceTest
    • RedisTest

使用SpringBoot集成redis,使用redis缓存数据

基于GitHub项目xkcoding/**spring-boot-demo**进行学习

项目地址:https://github.com/xkcoding/spring-boot-demo

项目结构

SpringBoot实战项目学习(11)——集成Redis缓存_第1张图片

pom.xml

  • 导入redis依赖spring-boot-starter-data-redis,其中使用Lettuce连接池
  • 导入对象池依赖commons-pool2

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>

    <artifactId>spring-boot-demo-cache-redisartifactId>
    <version>1.0.0-SNAPSHOTversion>
    <packaging>jarpackaging>

    <name>spring-boot-demo-cache-redisname>
    <description>Demo project for Spring Bootdescription>

    <parent>
        <groupId>com.xkcodinggroupId>
        <artifactId>spring-boot-demoartifactId>
        <version>1.0.0-SNAPSHOTversion>
    parent>

    <properties>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
        <java.version>1.8java.version>
    properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starterartifactId>
        dependency>

        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-data-redisartifactId>
        dependency>

        
        <dependency>
            <groupId>org.apache.commonsgroupId>
            <artifactId>commons-pool2artifactId>
        dependency>

        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-jsonartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>

        <dependency>
            <groupId>com.google.guavagroupId>
            <artifactId>guavaartifactId>
        dependency>

        <dependency>
            <groupId>cn.hutoolgroupId>
            <artifactId>hutool-allartifactId>
        dependency>

        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <optional>trueoptional>
        dependency>
    dependencies>

    <build>
        <finalName>spring-boot-demo-cache-redisfinalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            plugin>
        plugins>
    build>

project>

application.yml

spring:
  redis:
    host: localhost
    # 连接超时时间(记得添加单位,Duration)
    timeout: 10000ms
    # Redis默认情况下有16个分片,这里配置具体使用的分片
    # database: 0
    lettuce:
      pool:
        # 连接池最大连接数(使用负值表示没有限制) 默认 8
        max-active: 8
        # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
        max-wait: -1ms
        # 连接池中的最大空闲连接 默认 8
        max-idle: 8
        # 连接池中的最小空闲连接 默认 0
        min-idle: 0
  cache:
    # 一般来说是不用配置的,Spring Cache 会根据依赖的包自行装配
    type: redis
logging:
  level:
    com.xkcoding: debug

实体类User

package com.xkcoding.cache.redis.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * 

* 用户实体 *

* * @package: com.xkcoding.cache.redis.entity * @description: 用户实体 * @author: yangkai.shen * @date: Created in 2018/11/15 16:39 * @copyright: Copyright (c) 2018 * @version: V1.0 * @modified: yangkai.shen */
@Data @AllArgsConstructor @NoArgsConstructor public class User implements Serializable { private static final long serialVersionUID = 2892248514883451461L; /** * 主键id */ private Long id; /** * 姓名 */ private String name; }

service层

用户接口UserService

package com.xkcoding.cache.redis.service;

import com.xkcoding.cache.redis.entity.User;

/**
 * 

* UserService *

* * @package: com.xkcoding.cache.redis.service * @description: UserService * @author: yangkai.shen * @date: Created in 2018/11/15 16:45 * @copyright: Copyright (c) 2018 * @version: V1.0 * @modified: yangkai.shen */
public interface UserService { /** * 保存或修改用户 * * @param user 用户对象 * @return 操作结果 */ User saveOrUpdate(User user); /** * 获取用户 * * @param id key值 * @return 返回结果 */ User get(Long id); /** * 删除 * * @param id key值 */ void delete(Long id); }

实现类UserServiceImpl

与缓存有关的常用注解

  • @Cacheable:主要针对方法配置,能够根据方法的请求参数对其结果进行缓存 ;

    参数 解释 example
    value 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 例如: @Cacheable(value=”mycache”) @Cacheable(value={”cache1”,”cache2”}
    key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 @Cacheable(value=”testcache”,key=”#userName”)
    condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存 @Cacheable(value=”testcache”,condition=”#userName.length()>2”)
  • @CachePut: 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用 ;

    参数 解释 example
    value 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 例如: @Cacheable(value=”mycache”) @Cacheable(value={”cache1”,”cache2”}
    key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 @Cacheable(value=”testcache”,key=”#userName”)
    condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存 @Cacheable(value=”testcache”,condition=”#userName.length()>2”)
  • @CachEvict: 主要针对方法配置,能够根据一定的条件对缓存进行清空

参数 解释 example
value 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 @CacheEvict(value=”my cache”)
key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 @CacheEvict(value=”testcache”,key=”#userName”)
condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存 @CacheEvict(value=”testcache”,condition=”#userName.length()>2”)
allEntries 是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存 @CachEvict(value=”testcache”,allEntries=true)
beforeInvocation 是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存 @CachEvict(value=”testcache”,beforeInvocation=true)
package com.xkcoding.cache.redis.service.impl;

import com.google.common.collect.Maps;
import com.xkcoding.cache.redis.entity.User;
import com.xkcoding.cache.redis.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * 

* UserService *

* * @package: com.xkcoding.cache.redis.service.impl * @description: UserService * @author: yangkai.shen * @date: Created in 2018/11/15 16:45 * @copyright: Copyright (c) 2018 * @version: V1.0 * @modified: yangkai.shen */
@Service @Slf4j public class UserServiceImpl implements UserService { /** * 模拟数据库 * 定义一个Map映射 */ private static final Map<Long, User> DATABASES = Maps.newConcurrentMap(); /** * 初始化数据,首先放入一点数据 */ static { DATABASES.put(1L, new User(1L, "user1")); DATABASES.put(2L, new User(2L, "user2")); DATABASES.put(3L, new User(3L, "user3")); } /** * 保存或修改用户 * * @param user 用户对象 * @return 操作结果 */ @CachePut(value = "user", key = "#user.id") // 与@Cacheable类似,在需要在不影响方法执行的情况下更新缓存,每次都会触发真实方法的调用 @Override public User saveOrUpdate(User user) { DATABASES.put(user.getId(), user); log.info("保存用户【user】= {}", user); return user; } /** * 获取用户 * * @param id key值 * @return 返回结果 */ // @Cacheable主要针对方法配置,能够根据方法的请求参数对其结果进行缓存 @Cacheable(value = "user", key = "#id") // 从user缓存中查询,如果没有,则将执行的结果存入缓存中,否则返回缓存中的对象 @Override public User get(Long id) { // 我们假设从数据库读取 log.info("查询用户【id】= {}", id); return DATABASES.get(id); } /** * 删除 * * @param id key值 */ @CacheEvict(value = "user", key = "#id") // 针对方法配置,能够根据一定的条件对缓存进行清空 @Override public void delete(Long id) { DATABASES.remove(id); log.info("删除用户【id】= {}", id); } }

测试类

UserServiceTest

package com.xkcoding.cache.redis.service;

import com.xkcoding.cache.redis.SpringBootDemoCacheRedisApplicationTests;
import com.xkcoding.cache.redis.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 

* Redis - 缓存测试 *

* * @package: com.xkcoding.cache.redis.service * @description: Redis - 缓存测试 * @author: yangkai.shen * @date: Created in 2018/11/15 16:53 * @copyright: Copyright (c) 2018 * @version: V1.0 * @modified: yangkai.shen */
@Slf4j public class UserServiceTest extends SpringBootDemoCacheRedisApplicationTests { @Autowired private UserService userService; /** * 获取两次,查看日志验证缓存 */ @Test public void getTwice() { // 模拟查询id为1的用户 User user1 = userService.get(1L); log.debug("【user1】= {}", user1); // 再次查询 User user2 = userService.get(1L); log.debug("【user2】= {}", user2); // 查看日志,只打印一次日志,证明缓存生效 } /** * 先存,再查询,查看日志验证缓存 */ @Test public void getAfterSave() { userService.saveOrUpdate(new User(4L, "测试中文")); User user = userService.get(4L); log.debug("【user】= {}", user); // 查看日志,只打印保存用户的日志,查询是未触发查询日志,因此缓存生效 } /** * 测试删除,查看redis是否存在缓存数据 */ @Test public void deleteUser() { // 查询一次,使redis中存在缓存数据 userService.get(1L); // 删除,查看redis是否存在缓存数据 userService.delete(1L); } }

RedisTest

package com.xkcoding.cache.redis;

import com.xkcoding.cache.redis.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.io.Serializable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;

/**
 * 

* Redis测试 *

* * @package: com.xkcoding.cache.redis * @description: Redis测试 * @author: yangkai.shen * @date: Created in 2018/11/15 17:17 * @copyright: Copyright (c) 2018 * @version: V1.0 * @modified: yangkai.shen */
@Slf4j public class RedisTest extends SpringBootDemoCacheRedisApplicationTests { @Autowired private StringRedisTemplate stringRedisTemplate; @Autowired private RedisTemplate<String, Serializable> redisCacheTemplate; /** * 测试 Redis 操作 */ @Test public void get() { // 测试线程安全,程序结束查看redis中count的值是否为1000 ExecutorService executorService = Executors.newFixedThreadPool(1000); IntStream.range(0, 1000).forEach(i -> executorService.execute(() -> stringRedisTemplate.opsForValue().increment("count", 1))); stringRedisTemplate.opsForValue().set("k1", "v1"); String k1 = stringRedisTemplate.opsForValue().get("k1"); log.debug("【k1】= {}", k1); // 以下演示整合,具体Redis命令可以参考官方文档 String key = "xkcoding:user:1"; redisCacheTemplate.opsForValue().set(key, new User(1L, "user1")); // 对应 String(字符串) User user = (User) redisCacheTemplate.opsForValue().get(key); log.debug("【user】= {}", user); } }

你可能感兴趣的:(SpringBoot实战项目)