总结一下redis的使用

总结一下redis的使用。

我这里是有一个redisTemplate操作缓存数据,  和一个使用缓存管理器,对方法缓存的注解。两种方式缓存。

第一步引包:

<!--redis依赖配置-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

第二步配置redis:

package com.xnpool.common.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.xnpool.common.service.RedisService;
import com.xnpool.common.service.impl.RedisServiceImpl;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.time.Duration;

/**
 * Redis基础配置
 * Created by heqiwen on 2020/6/19.
 */
public class BaseRedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisSerializer<Object> serializer = redisSerializer();
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(serializer);
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(serializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    @Bean
    public RedisSerializer<Object> redisSerializer() {
        //创建JSON序列化器
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //必须设置,否则无法将JSON转化为对象,会转化成Map类型
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(objectMapper);
        return serializer;
    }

    /**
     * 有cachemanager(redis缓存管理器使用):配置+注解  可以对 方法进行缓存。带有注解@Cacheable、@CachePut、@CacheEvict 注解
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
        //设置Redis缓存有效期为1天
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer())).entryTtl(Duration.ofDays(1));
        return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
    }

    /**
     * 对方法进行缓存时,注解的属性。 生成redis的key用的。
     * @return
     */
    @Bean
    public KeyGenerator simpleKeyGenerator() {
        return (o, method, objects) -> {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(method.getName());
            stringBuilder.append(":");
            for (Object obj : objects) {
                stringBuilder.append(getAttributes(obj));
            }
            return stringBuilder.toString();
        };
    }

    /**
     * 对方法进行缓存时,注解的属性。 生成redis的key用的。
     * @return
     */
    @Bean
    public KeyGenerator tokenKeyGenerator() {
        return (oobj, method, objects) -> {
            StringBuilder stringBuilder = new StringBuilder();
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            Long userId=(Long) request.getAttribute("currentUserId");
            Long appId=(Long) request.getAttribute("currentApp");
            stringBuilder.append("appid"+appId);
            stringBuilder.append("userid"+userId+"_");
            stringBuilder.append(method.getName());
            stringBuilder.append(":");
            for (Object obj : objects) {
                stringBuilder.append(getAttributes(obj));
            }

            return stringBuilder.toString();
        };
    }

    /**
     * 用于清除当前用户自己的数据(redis的key)
     * @return
     */
    @Bean
    public KeyGenerator evictoKeyGenerator() {
        return (obj, method, objects) -> {
            StringBuilder stringBuilder = new StringBuilder();
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            Long userId=(Long) request.getAttribute("currentUserId");
            Long appId=(Long) request.getAttribute("currentApp");
            stringBuilder.append("appid"+appId);
            stringBuilder.append("userid"+userId+"_*");
            return stringBuilder.toString();
        };
    }


    @Bean
    public RedisService redisService(){
        return new RedisServiceImpl();
    }

    //获取对象的所有属性,如果是基础数据类型就直接返回tostring
    private String getAttributes(Object obj){
        Class<?> aClass = obj.getClass();
        if(aClass.getName().startsWith("java.lang.")||aClass.getName().startsWith("java.util.")){
            return obj.toString();
        }else if(aClass.getName().startsWith("javax.servlet.http")){
            return "";
        }else {
            try {
                StringBuilder sb = new StringBuilder();
                Field[] declaredFields = aClass.getDeclaredFields();
                for (Field field:declaredFields){
                    String fname=field.getName();
                    String fristLetter=fname.substring(0,1).toUpperCase();
                    String methodName="get"+fristLetter+fname.substring(1);
                    Method getMethod=aClass.getMethod(methodName,new Class[]{});
                    Object value=getMethod.invoke(obj,new Object[]{});
                    if(value==null){
                        continue;
                    }else {
                        sb.append(fname);
                        sb.append(String.valueOf(value));
                    }
                }
                Class<?> superclass = aClass.getSuperclass();
                if(!superclass.getName().startsWith("java.lang.")){
                    Field[] fields = superclass.getDeclaredFields();
                    for (Field field:fields){
                        String fname=field.getName();
                        String fristLetter=fname.substring(0,1).toUpperCase();
                        String methodName="get"+fristLetter+fname.substring(1);
                        Method getMethod=aClass.getMethod(methodName,new Class[]{});
                        Object value=getMethod.invoke(obj,new Object[]{});
                        if(value==null){
                            continue;
                        }else {
                            sb.append(fname);
                            sb.append(String.valueOf(value));
                        }
                    }
                }
                return sb.toString();
            }catch (Exception e){
                return obj.toString();
            }
        }
    }
}

这是一个springboot项目,redis属性会自动注入的。

spring:

redis:
  host: localhost # Redis服务器地址
  database: 0 # Redis数据库索引(默认为0)
  port: 6379 # Redis服务器连接端口
  password: # Redis服务器连接密码(默认为空)
  timeout: 3000ms # 连接超时时间(毫秒)

第三步使用redisTemplate

package com.xnpool.common.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.xnpool.common.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * redis操作实现类
 * Created by heqiwen on 2020/3/3.
 */
public class RedisServiceImpl implements RedisService {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public void set(String key, Object value, long time) {
        redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
    }

    @Override
    public void set(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    @Override
    public Object get(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    @Override
    public Boolean del(String key) {
        return redisTemplate.delete(key);
    }

    @Override
    public Boolean delPrex(String prex){
        try{
            Set<String> keys = redisTemplate.keys(prex);
            if (CollectionUtils.isNotEmpty(keys)) {
                redisTemplate.delete(keys);
            }
        }catch (Exception e){
            return false;
        }
        return true;
    }
    @Override
    public Long del(List<String> keys) {
        return redisTemplate.delete(keys);
    }

    @Override
    public Boolean expire(String key, long time) {
        return redisTemplate.expire(key, time, TimeUnit.SECONDS);
    }

    @Override
    public Long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    @Override
    public Boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }

    @Override
    public Long incr(String key, long delta) {
        return redisTemplate.opsForValue().increment(key, delta);
    }

    @Override
    public Long decr(String key, long delta) {
        return redisTemplate.opsForValue().increment(key, -delta);
    }

    @Override
    public Object hGet(String key, String hashKey) {
        return redisTemplate.opsForHash().get(key, hashKey);
    }

    @Override
    public Boolean hSet(String key, String hashKey, Object value, long time) {
        redisTemplate.opsForHash().put(key, hashKey, value);
        return expire(key, time);
    }

    @Override
    public void hSet(String key, String hashKey, Object value) {
        redisTemplate.opsForHash().put(key, hashKey, value);
    }

    @Override
    public Map<Object, Object> hGetAll(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    @Override
    public Boolean hSetAll(String key, Map<String, Object> map, long time) {
        redisTemplate.opsForHash().putAll(key, map);
        return expire(key, time);
    }

    @Override
    public void hSetAll(String key, Map<String, ?> map) {
        redisTemplate.opsForHash().putAll(key, map);
    }

    @Override
    public void hDel(String key, Object... hashKey) {
        redisTemplate.opsForHash().delete(key, hashKey);
    }

    @Override
    public Boolean hHasKey(String key, String hashKey) {
        return redisTemplate.opsForHash().hasKey(key, hashKey);
    }

    @Override
    public Long hIncr(String key, String hashKey, Long delta) {
        return redisTemplate.opsForHash().increment(key, hashKey, delta);
    }

    @Override
    public Long hDecr(String key, String hashKey, Long delta) {
        return redisTemplate.opsForHash().increment(key, hashKey, -delta);
    }

    @Override
    public Set<Object> sMembers(String key) {
        return redisTemplate.opsForSet().members(key);
    }

    @Override
    public Long sAdd(String key, Object... values) {
        return redisTemplate.opsForSet().add(key, values);
    }

    @Override
    public Long sAdd(String key, long time, Object... values) {
        Long count = redisTemplate.opsForSet().add(key, values);
        expire(key, time);
        return count;
    }

    @Override
    public Boolean sIsMember(String key, Object value) {
        return redisTemplate.opsForSet().isMember(key, value);
    }

    @Override
    public Long sSize(String key) {
        return redisTemplate.opsForSet().size(key);
    }

    @Override
    public Long sRemove(String key, Object... values) {
        return redisTemplate.opsForSet().remove(key, values);
    }

    @Override
    public List<Object> lRange(String key, long start, long end) {
        return redisTemplate.opsForList().range(key, start, end);
    }

    @Override
    public Long lSize(String key) {
        return redisTemplate.opsForList().size(key);
    }

    @Override
    public Object lIndex(String key, long index) {
        return redisTemplate.opsForList().index(key, index);
    }

    @Override
    public Long lPush(String key, Object value) {
        return redisTemplate.opsForList().rightPush(key, value);
    }

    @Override
    public Long lPush(String key, Object value, long time) {
        Long index = redisTemplate.opsForList().rightPush(key, value);
        expire(key, time);
        return index;
    }

    @Override
    public Long lPushAll(String key, Object... values) {
        return redisTemplate.opsForList().rightPushAll(key, values);
    }

    @Override
    public Long lPushAll(String key, Long time, Object... values) {
        Long count = redisTemplate.opsForList().rightPushAll(key, values);
        expire(key, time);
        return count;
    }

    @Override
    public Long lRemove(String key, long count, Object value) {
        return redisTemplate.opsForList().remove(key, count, value);
    }

    /**
     * 获得锁
     *
     * @param lock
     * @return
     */
    public boolean lock(String lock,Long LOCK_EXPIRE) {
        return (boolean) redisTemplate.execute((RedisCallback) connection -> {
            //获取时间毫秒值
            long expireAt = System.currentTimeMillis() + LOCK_EXPIRE + 1;
            //获取锁
            Boolean acquire = connection.setNX(lock.getBytes(), String.valueOf(expireAt).getBytes());
            if (acquire) {
                return true;
            } else {
                byte[] bytes = connection.get(lock.getBytes());
                //非空判断
                if (Objects.nonNull(bytes) && bytes.length > 0) {
                    long expireTime = Long.parseLong(new String(bytes));
                    // 如果锁已经过期
                    if (expireTime < System.currentTimeMillis()) {
                        // 重新加锁,防止死锁
                        byte[] set = connection.getSet(lock.getBytes(), String.valueOf(System.currentTimeMillis() + LOCK_EXPIRE + 1).getBytes());
                        return Long.parseLong(new String(set)) < System.currentTimeMillis();
                    }
                }
            }
            return false;
        });
    }
}

第四步使用缓存管理器cacheManage:

package com.xnpool.enterprise.modules.appmanage.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.xnpool.common.api.CommonResult;
import com.xnpool.enterprise.modules.appmanage.dto.SubUserQuery;
import com.xnpool.enterprise.modules.appmanage.model.TApplicationWhiteList;
import com.xnpool.enterprise.modules.appmanage.model.TSubuser;
import com.xnpool.enterprise.modules.appmanage.service.TSubuserService;
import com.xnpool.enterprise.security.annotation.TradeApiTokenCheck;
import com.xnpool.enterprise.security.util.CurrentUserUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author heqiwen
 * @since 2021-01-14
 */
@Api(tags = "用户的子账户维护", description = "用户的子账户维护")
@Slf4j
@RestController
@RequestMapping("/subuser")
public class TSubuserController {
    @Autowired
    private TSubuserService subuserService;

    @ApiOperation("增加子账户")
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    @Caching(evict={@CacheEvict(value = "subuser_m",keyGenerator = "evictoKeyGenerator",allEntries = true),
            @CacheEvict(value = "useraddress_m",keyGenerator = "evictoKeyGenerator",allEntries = true)})
    public CommonResult<TSubuser> add(@RequestBody TSubuser subuser) {
        
        CommonResult<TSubuser> result=subuserService.addSubuser(subuser);
        return result;
    }

    @ApiOperation("修改子账户")
    @RequestMapping(value = "/update", method = RequestMethod.POST)
    @Caching(evict={@CacheEvict(value = "subuser_m",keyGenerator = "evictoKeyGenerator",allEntries = true),
            @CacheEvict(value = "useraddress_m",keyGenerator = "evictoKeyGenerator",allEntries = true)})
    public CommonResult<String> update(@RequestBody TSubuser subuser) {
        subuser.setUpdateTime(new Date());
        if(subuser.getParentId()==null || subuser.getParentId()==0){
            Long currentUserId = CurrentUserUtil.getCurrentUserId();//取当前登录人
            subuser.setParentId(currentUserId);
        }
        subuserService.updateById(subuser);
        return CommonResult.success(String.valueOf(subuser.getId()));
    }

    @ApiOperation("根据ID删除子账户")
    @RequestMapping(value = "/delete/{id}", method = RequestMethod.POST)
    @Caching(evict={@CacheEvict(value = "subuser_m",keyGenerator = "evictoKeyGenerator",allEntries = true),
            @CacheEvict(value = "useraddress_m",keyGenerator = "evictoKeyGenerator",allEntries = true)})
    public CommonResult<String> delete(@PathVariable Long id) {
        
        CommonResult<String> result=subuserService.deleteSubuser(id);
        return result;
    }

    @ApiOperation("根据ID查看子账户")
    @RequestMapping(value = "/detail/{id}", method = RequestMethod.POST)
    public CommonResult<TSubuser> detail(@PathVariable Long id) {

        TSubuser subuser=subuserService.getById(id);

        return CommonResult.success(subuser);
    }

    @ApiOperation("查询子账户")
    @RequestMapping(value = "/list", method = RequestMethod.POST)
    @Cacheable(value = "subuser_m",keyGenerator = "tokenKeyGenerator",unless = "#result.data==null || #result.data.size()==0")
    public CommonResult<List<TSubuser>> list(@RequestBody SubUserQuery subuser) {
        Long currentUserId = CurrentUserUtil.getCurrentUserId();//取当前登录人
        if(currentUserId==null){
            return CommonResult.failed("token中用户数据为空");
        }
        subuser.setParentId(currentUserId);
        log.info("查询子账号列表,userid:"+currentUserId);
        List<TSubuser> list = subuserService.list(new QueryWrapper<TSubuser>().lambda().eq(TSubuser::getParentId, subuser.getParentId()).eq(TSubuser::getArtived,1).orderByDesc(TSubuser::getCreateTime));
        return CommonResult.success(list);
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值