SpringBoot 2.x 使用Redis作为项目数据缓存

Stella981
• 阅读 425

一、添加依赖

<!-- 添加缓存支持 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>

        <!-- 添加Redis缓存支持 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <!-- 工具类 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.15</version>
        </dependency>

二、配置Redis数据库

spring:
  redis:
    #数据库索引
    database: 1
    host: 192.168.2.230
    port: 6379
    password:
    jedis:
      pool:
        #最大连接数
        max-active: 8
        #最大阻塞等待时间(负数表示没限制)
        max-wait: -1
        #最大空闲
        max-idle: 8
        #最小空闲
        min-idle: 0
    #连接超时时间
    timeout: 10000

三、Redis配置类

package com.hn.lz.config;

import com.hn.lz.handler.FastJsonRedisSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.Cache;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.serializer.RedisSerializationContext;

import java.lang.reflect.Method;
import java.time.Duration;

/**
 * Created by mll on 2018/7/16.
 */
@Configuration
@EnableCaching  //开启支持缓存
public class RedisConfiguration extends CachingConfigurerSupport {

    static Logger logger = LoggerFactory.getLogger(RedisConfiguration.class);

    /**
     * 自定义生成key的规则
     *
     * @return
     */
    @Override
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object o, Method method, Object... objects) {
                //格式化缓存key字符串
                StringBuilder sb = new StringBuilder();
                //追加类名
                sb.append(o.getClass().getName()).append(".");
                //追加方法名
                sb.append(method.getName());
                //遍历参数并且追加
                for (Object obj : objects) {
                    sb.append(".");
                    sb.append(obj.toString());
                }
                System.out.println("调用Redis缓存Key : " + sb.toString());
                return sb.toString();
            }
        };
    }

    /**
     * 设置 redis 数据默认过期时间
     * 设置 Cache 序列化方式
     *
     * @return
     */
    @Bean
    public RedisCacheConfiguration redisCacheConfiguration() {
        FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
        RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
        configuration = configuration
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer))
                .entryTtl(Duration.ofDays(30));
        return configuration;
    }

}

四、自定义存入Redis数据库值的序列化方式

package com.hn.lz.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;

import java.nio.charset.Charset;

/**
 * Created by mll on 2018/7/17.
 */
public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {

    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    private Class<T> clazz;

    public FastJsonRedisSerializer(Class<T> clazz) {
        super();
        this.clazz = clazz;
    }

    @Override
    public byte[] serialize(T t) throws SerializationException {
        if (null == t) {
            return new byte[0];
        }
        return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
    }

    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
        if (null == bytes || bytes.length <= 0) {
            return null;
        }
        String str = new String(bytes, DEFAULT_CHARSET);
        return (T)JSON.parseObject(str, clazz);
    }

}

五、使用注解来缓存数据

package com.hn.lz.service;

import com.hn.lz.mapper.UserMapper;
import com.hn.lz.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * Created by mll on 2018/6/21.
 */
@CacheConfig(cacheNames = "user")
@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    // ----------------------------------  数据操作 BEGIN  --------------------------------------
    /**
     * 插入数据
     * @param data
     * @return
     */
    @Transactional
    @CachePut(key = "#data.id")
    public User insert(User data){
        userMapper.insert(data);
        return data;
    }

    /**
     * 更新数据
     * @param data
     * @return
     */
    @Transactional
    @CachePut(key = "#data.id")
    public User update(User data){
        userMapper.updateByPrimaryKeySelective(data);
        return data;
    }

    /**
     * 删除数据
     * @param id
     * @return
     */
    @Transactional
    @CacheEvict(key = "#id")
    public int delete(String id){
        int result = userMapper.deleteByPrimaryKey(id);
        return result;
    }

    /**
     * 得到所有数据列表
     * @return
     */
    public List<User> select() {
        List<User> list = userMapper.selectAll();
        return list;
    }

    /**
     * 根据id查询数据
     * @param id
     * @return
     */
    @Cacheable(key = "#id")
    public User query(String id){
        User data = userMapper.selectByPrimaryKey(id);
        return data;
    }
    // ----------------------------------  数据操作 END  --------------------------------------
}

六、要点

1、注解

  • @CacheConfig这个注解主要用于配置该类中会用到的一些公用的缓存配置。我们也可以不使用该注解,直接通过自己的注解配置缓存集的名字来定义。

    @CacheConfig(cacheNames = "user") @Service public class UserService

  • @CachePut这个注解直接将返回值放入缓存中,通常用于保存和修改方法中。

  • value缓存的名称,必须指定至少一个。

  • key缓存的 key,可以为空,如果指定要按照 SpEL(Spring Expression Language) 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合。

  • condition:缓存的条件,可以为空,使用 SpEL 编写,返回true或者false只有为true才进行缓存。

    @CachePut(value = "user", key = "#data.id", condition = "#result.username ne 'zhang'")
    public User insert(User data)

  • @Cacheable这个注解在执行前先查看缓存中是不是已经存在了,如果存在,直接返回。如果不存在,将方法的返回值放入缓存。

  • value缓存的名称,必须指定至少一个。

  • key缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合。

  • condition缓存的条件,可以为空,使用 SpEL 编写,返回true或者false只有为true才进行缓存。

    @Cacheable(value = "user", key = "#id", condition = "#id lt 10")
    public User query(Long id)

  • @CacheEvict这个注解在执行方法执行成功后会从缓存中移除。

  • value缓存的名称,必须指定至少一个。

  • key缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合。

  • condition缓存的条件,可以为空,使用 SpEL 编写,返回true或者false只有为true才进行缓存。

  • allEntries是否清空所有缓存内容,缺省为false如果指定为true则方法调用后将立即清空所有缓存。

  • beforeInvocation是否在方法执行前就清空,缺省为false如果指定为true则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存。

    @CacheEvict(value = "user", key = "#data.id", beforeInvocation = false, condition = "#result.username ne 'zhang'")
    public User delete(User data)

  • @Caching这个注解组合多个Cache注解使用,并且可以自定义注解使用。

    @Caching(
    put = {
    @CachePut(value = "user", key = "#user.id"),
    @CachePut(value = "user", key = "#user.username"),
    @CachePut(value = "user", key = "#user.email")
    }
    )
    @Caching(
    put = {
    @CachePut(value = "user", key = "#user.id"),
    @CachePut(value = "user", key = "#user.username"),
    @CachePut(value = "user", key = "#user.email")
    }
    )
    @Target({ElementType.METHOD, ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    public @interface MyCache {
    }

    @MyCache public User save(User data)

2、Spring Cache提供了一些供我们使用的SpEL上下文数据

名字

描述

示例

methodName

当前被调用的方法名

#root.methodName

method

当前被调用的方法

#root.method.name

target

当前被调用的目标对象

#root.target

targetClass

当前被调用的目标对象类

#root.targetClass

args

当前被调用的方法的参数列表

#root.args[0]

caches

当前方法调用使用的缓存列表(如@Cacheable(value={"cache1", "cache2"})),则有两个cache

#root.caches[0].name

argument name

当前被调用的方法的参数,如findById(Long id),我们可以通过#id拿到参数

#user.id

result

方法执行后的返回值(仅当方法执行之后的判断有效,如‘unless’,'cache evict'的beforeInvocation=false)

#result

3、Redis常用命令

flushdb:清空当前数据库。
select index:选择索引数据库,index为索引值名,如:select 1
del key:删除一条指定key的值。
keys *:查看数据库内所有的key。
flushall:清空所有数据库。
quit:退出客户端连接。

作者:maololo
链接:https://www.jianshu.com/p/e67e85eb63b2
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这