Java封装redis工具类RedisUtils,以及在@Postconstruct注解中调用redis可能出现redisTemplate空指针异常

1、封装redis工具类RedisUtils

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author xuxilan
 */
@Component
public class RedisUtils {

    private static RedisTemplate<String, Object> redisTemplate;

    @Resource
    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
        RedisUtils.redisTemplate = redisTemplate;
    }

    /**
     * 根据正则表达式,获取所有key值
     * @param patten
     * @return
     */
    public static Set<String> getAllKeys(String patten){
        return redisTemplate.keys(patten);
    }

    /**
     * 设置单个缓存
     * @param key
     * @param value
     * @param expire
     * @param timeUnit
     */
    public static void set(String key, Object value, long expire, TimeUnit timeUnit){
        redisTemplate.opsForValue().set(key, value, expire, timeUnit);
    }

    /**
     *  普通缓存
     * @param key
     * @param value
     */
    public static void set(String key, Object value) {
        redisTemplate.opsForValue().set(key,value);
    }

    /**
     * 按秒缓存
     * @param key
     * @param value
     * @param expire
     */
    public static void setSeconds(String key, Object value, long expire) {
        set(key,value,expire, TimeUnit.SECONDS);
    }

    /**
     * 按分钟缓存
     * @param key
     * @param value
     * @param expire
     */
    public static void setMinutes(String key, Object value, long expire) {
        set(key,value,expire, TimeUnit.MINUTES);
    }

    /**
     * 按小时缓存
     * @param key
     * @param value
     * @param expire
     */
    public static void setHours(String key, Object value, long expire) {
        set(key,value,expire, TimeUnit.HOURS);
    }

    /**
     * 通过key 获取value
     */

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

    /**
     * 设置过期时间
     * @param key
     * @param timeout
     * @param timeUnit
     */
    public static void expire(String key, long timeout, TimeUnit timeUnit){
        redisTemplate.expire(key,timeout,timeUnit);
    }

    /**
     * 获取过期时间
     * @param key
     * @return
     */
    public static Long getExpire(String key){
        return redisTemplate.getExpire(key);
    }

    /**
     * 判断是否存在某个 key
     * @param key
     * @return
     */
    public static boolean hasKey(String key) {
        Boolean hasKey = redisTemplate.hasKey(key);
        return hasKey != null && hasKey;
    }

    /**
     * 删除某个 key
     * @param key
     */
    public static void delete(String key) {
        redisTemplate.delete(key);
    }

    /**
     * 给 value 自增1
     * @param key
     */
    public void increment(String key){
        redisTemplate.boundValueOps(key).increment(1);
    }

    /**
     * 给 value 减少1
     * @param key
     */
    public void decrement(String key){
        redisTemplate.boundValueOps(key).increment(-1);
    }


    public static boolean nSet(String key, Object value,long timeout,TimeUnit timeUnit){
        return redisTemplate.opsForValue().setIfAbsent(key,value,timeout,timeUnit);
    }

    /*************************** opsForZSet ************************************/

    /**
     * 添加
     * @param key
     * @param member
     * @param score
     */
    public static void zAdd(String key, Object member, double score) {
        redisTemplate.opsForZSet().add(key,member,score);
    }

    /**
     * 批量添加
     * @param key
     * @param typedTuples
     */
    public static void zmAdd(String key, Set<ZSetOperations.TypedTuple<Object>> typedTuples){
        if (typedTuples == null || typedTuples.size() == 0) {
            return;
        }
        redisTemplate.opsForZSet().add(key,typedTuples);
    }

    /**
     * 根据分数范围获取成员及分数
     * @param key
     * @param min
     * @param max
     * @return
     */
    public static Set<ZSetOperations.TypedTuple<Object>> zRangeByScoreWithScores(String key, double min, double max){
        return redisTemplate.opsForZSet().rangeByScoreWithScores(key,min,max);
    }

    /**
     * 根据分数范围获取成员
     * @param key
     * @param min
     * @param max
     * @return
     */
    public static Set<Object> zRangeByScore(String key, double min, double max){
        return redisTemplate.opsForZSet().rangeByScore(key,min,max);
    }

    public static Set<Object> zReverseRangeByScore(String key, double min, double max){
        return redisTemplate.opsForZSet().reverseRangeByScore(key,min,max);
    }

    /**
     * 删除所有
     * @param key
     */
    public static void zRemoveAllByScore(String key){
        redisTemplate.opsForZSet().removeRangeByScore(key,0,-1);
    }

    public static Set<Object> zGetReverseRange(String key,int start,int end){
        return redisTemplate.opsForZSet().reverseRange(key, start, end);
    }

    public static Set<Object> zGetRange(String key,int start,int end){
        return redisTemplate.opsForZSet().range(key, start, end);
    }

    public static Set<Object> zGetAllRange(String key){
        return redisTemplate.opsForZSet().range(key, 0,-1);
    }

    public static Double zGetScore(String key,Object member){
        return redisTemplate.opsForZSet().score(key,member);
    }

    /**
     * 判断zset中是否存在某个值
     * @param key
     * @param member
     * @return
     */
    public static boolean zExist(String key, Object member) {
        Long rank = redisTemplate.opsForZSet().rank(key, member);
        return rank != null;
    }

    /**
     * 删除某个成员
     * @param key
     * @param member
     */
    public static void zRem(String key, Object member) {
        redisTemplate.opsForZSet().remove(key,member);
    }

    public static Double zincrby(String key,Object member,double delta){
        return redisTemplate.opsForZSet().incrementScore(key,member,delta);
    }


    /*************************** opsForHash ************************************/

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

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

    public static List<Object> hGetAll(String key) {
        return redisTemplate.opsForHash().values(key);
    }


    /*************************** opsForList ************************************/

    public static void leftPush(String key,Object value){
        redisTemplate.opsForList().leftPush(key, value);
    }

    public static void rightPush(String key,Object value){
        redisTemplate.opsForList().rightPush(key, value);
    }

    public static Object rightPop(String key){
        return redisTemplate.opsForList().rightPop(key);
    }

}

用不到的可自行删除

2、注意事项

在使用@Postconstruct注解时,如果调用redis工具类,redisTemplate有可能会出现空指针导致异常错误,大概是上面的RedisUtils@Resource 注解还未注入的原因导致空指针异常,如果需要在项目启动时执行某段代码中有调用redis,请不要用@Postconstruct,可以实现接口InitializingBean、或是CommandLineRunner、或是ApplicationRunner
当然也可以使用@Bean注入使用,如下:

// 三种方法最好都在类上加一个 @Component
@Component
public class Auto() {

	@Bean
    InitializingBean initializingBean() {
        return () -> {
        	// 要执行的代码
        };
    }
	
	@Bean
    CommandLineRunner commandLineRunner() {
        return args -> {
            // 要执行的代码
        };
    }
    
    @Bean
    ApplicationRunner applicationRunner() {
        return args -> {
            // 要执行的代码
        };
    }
}

当然,如果非要用@Postconstruct注解也可以,需要将上述的

	private static RedisTemplate<String, Object> redisTemplate;

    @Resource
    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
        RedisUtils.redisTemplate = redisTemplate;
    }

替换成

	private static final RedisTemplate<String, Object> redisTemplate;
	
    static {
        redisTemplate = SpringUtils.getBean("redisTemplate");
    }

即使用SpringUtils工具类获取bean即可,同时要去掉类上的@Component注解。
不过,这也和redis的版本有很大的关系。低版本的redis并不会有这种问题,比如3.x版本,所以如果遇到此类问题,也可以将redis版本往下调即可。
SpringUtils工具类如下。

3、SpringUtils工具类

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
public class SpringUtils implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringUtils.applicationContext = applicationContext;
    }

    /**
     * 获取applicationContext对象
     * @return
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public static <T> T getBean(String id, Class<T> clazz) {
        return (T) getBeanById(id);
    }
    
	public static <T> T getBean(String id) {
        return (T) getBeanById(id);
    }

    /**
     * 根据bean的id来查找对象
     * @param id
     * @return
     */
    public static Object getBeanById(String id) {
        return applicationContext.getBean(id);
    }

    /**
     * 根据bean的class来查找对象
     * @param c
     * @return
     */
    public static <T> T getBeanByClass(Class<T> c) {
        return applicationContext.getBean(c);
    }

    /**
     * 根据bean的class来查找所有的对象(包括子类)
     * @param c
     * @return
     */
    public static <T> Map<String, T> getBeansByClass(Class<T> c) {
        return applicationContext.getBeansOfType(c);
    }
}
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值