1. 程式人生 > 程式設計 >關於SpringBoot使用Redis空指標的問題(不能成功注入的問題)

關於SpringBoot使用Redis空指標的問題(不能成功注入的問題)

自己的一個小專案使用redis在一個類裡可以注入成功,而在另一個類以卻不能注入成功

不多bb直接上程式碼

package com.common.utils;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
 
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
 
 
@Component
public class RedisUtil {
 
 @Autowired
 private RedisTemplate<String,Object> redisTemplate;
 
 public RedisUtil(RedisTemplate<String,Object> redisTemplate) {
  this.redisTemplate = redisTemplate;
 }
 
 /**
  * 指定快取失效時間
  * @param key 鍵
  * @param time 時間(秒)
  * @return
  */
 public boolean expire(String key,long time){
  try {
   if(time>0){
    redisTemplate.expire(key,time,TimeUnit.SECONDS);
   }
   return true;
  } catch (Exception e) {
   e.printStackTrace();
   return false;
  }
 }
 
 /**
  * 根據key 獲取過期時間
  * @param key 鍵 不能為null
  * @return 時間(秒) 返回0代表為永久有效
  */
 public long getExpire(String key){
  return redisTemplate.getExpire(key,TimeUnit.SECONDS);
 }
 
 /**
  * 判斷key是否存在
  * @param key 鍵
  * @return true 存在 false不存在
  */
 public boolean hasKey(String key){
  try {
   return redisTemplate.hasKey(key);
  } catch (Exception e) {
   e.printStackTrace();
   return false;
  }
 }
 
 /**
  * 刪除快取
  * @param key 可以傳一個值 或多個
  */
 @SuppressWarnings("unchecked")
 public void del(String ... key){
  if(key!=null&&key.length>0){
   if(key.length==1){
    redisTemplate.delete(key[0]);
   }else{
    redisTemplate.delete(CollectionUtils.arrayToList(key));
   }
  }
 }
 
 //============================String=============================
 /**
  * 普通快取獲取
  * @param key 鍵
  * @return 值
  */
 public Object get(String key){
  return key==null?null:redisTemplate.opsForValue().get(key);
 }
 
 /**
  * 普通快取放入
  * @param key 鍵
  * @param value 值
  * @return true成功 false失敗
  */
 public boolean set(String key,Object value) {
  try {
   redisTemplate.opsForValue().set(key,value);
   return true;
  } catch (Exception e) {
   e.printStackTrace();
   return false;
  }
 }
 
 /**
  * 普通快取放入並設定時間
  * @param key 鍵
  * @param value 值
  * @param time 時間(分鐘) time要大於0 如果time小於等於0 將設定無限期
  * @return true成功 false 失敗
  */
 public boolean set(String key,Object value,long time){
  try {
   if(time>0){
    redisTemplate.opsForValue().set(key,value,TimeUnit.MINUTES);
   }else{
    set(key,value);
   }
   return true;
  } catch (Exception e) {
   e.printStackTrace();
   return false;
  }
 }
 
 /**
  * 遞增
  * @param key 鍵
  * @param delta 要增加幾(大於0)
  * @return
  */
 public long incr(String key,long delta){
  if(delta<0){
   throw new RuntimeException("遞增因子必須大於0");
  }
  return redisTemplate.opsForValue().increment(key,delta);
 }
 
 /**
  * 遞減
  * @param key 鍵
  * @param delta 要減少幾(小於0)
  * @return
  */
 public long decr(String key,long delta){
  if(delta<0){
   throw new RuntimeException("遞減因子必須大於0");
  }
  return redisTemplate.opsForValue().increment(key,-delta);
 }
 
 //================================Map=================================
 /**
  * HashGet
  * @param key 鍵 不能為null
  * @param item 項 不能為null
  * @return 值
  */
 public Object hget(String key,String item){
  return redisTemplate.opsForHash().get(key,item);
 }
 
 /**
  * 獲取hashKey對應的所有鍵值
  * @param key 鍵
  * @return 對應的多個鍵值
  */
 public Map<Object,Object> hmget(String key){
  return redisTemplate.opsForHash().entries(key);
 }
 
 /**
  * HashSet
  * @param key 鍵
  * @param map 對應多個鍵值
  * @return true 成功 false 失敗
  */
 public boolean hmset(String key,Map<String,Object> map){
  try {
   redisTemplate.opsForHash().putAll(key,map);
   return true;
  } catch (Exception e) {
   e.printStackTrace();
   return false;
  }
 }
 
 /**
  * HashSet 並設定時間
  * @param key 鍵
  * @param map 對應多個鍵值
  * @param time 時間(秒)
  * @return true成功 false失敗
  */
 public boolean hmset(String key,Object> map,long time){
  try {
   redisTemplate.opsForHash().putAll(key,map);
   if(time>0){
    expire(key,time);
   }
   return true;
  } catch (Exception e) {
   e.printStackTrace();
   return false;
  }
 }
 
 /**
  * 向一張hash表中放入資料,如果不存在將建立
  * @param key 鍵
  * @param item 項
  * @param value 值
  * @return true 成功 false失敗
  */
 public boolean hset(String key,String item,Object value) {
  try {
   redisTemplate.opsForHash().put(key,item,value);
   return true;
  } catch (Exception e) {
   e.printStackTrace();
   return false;
  }
 }
 
 /**
  * 向一張hash表中放入資料,如果不存在將建立
  * @param key 鍵
  * @param item 項
  * @param value 值
  * @param time 時間(秒) 注意:如果已存在的hash表有時間,這裡將會替換原有的時間
  * @return true 成功 false失敗
  */
 public boolean hset(String key,long time) {
  try {
   redisTemplate.opsForHash().put(key,value);
   if(time>0){
    expire(key,time);
   }
   return true;
  } catch (Exception e) {
   e.printStackTrace();
   return false;
  }
 }
 
 /**
  * 刪除hash表中的值
  * @param key 鍵 不能為null
  * @param item 項 可以使多個 不能為null
  */
 public void hdel(String key,Object... item){
  redisTemplate.opsForHash().delete(key,item);
 }
 
 /**
  * 判斷hash表中是否有該項的值
  * @param key 鍵 不能為null
  * @param item 項 不能為null
  * @return true 存在 false不存在
  */
 public boolean hHasKey(String key,String item){
  return redisTemplate.opsForHash().hasKey(key,item);
 }
 
 /**
  * hash遞增 如果不存在,就會建立一個 並把新增後的值返回
  * @param key 鍵
  * @param item 項
  * @param by 要增加幾(大於0)
  * @return
  */
 public double hincr(String key,double by){
  return redisTemplate.opsForHash().increment(key,by);
 }
 
 /**
  * hash遞減
  * @param key 鍵
  * @param item 項
  * @param by 要減少記(小於0)
  * @return
  */
 public double hdecr(String key,-by);
 }
 
 //============================set=============================
 /**
  * 根據key獲取Set中的所有值
  * @param key 鍵
  * @return
  */
 public Set<Object> sGet(String key){
  try {
   return redisTemplate.opsForSet().members(key);
  } catch (Exception e) {
   e.printStackTrace();
   return null;
  }
 }
 
 /**
  * 根據value從一個set中查詢,是否存在
  * @param key 鍵
  * @param value 值
  * @return true 存在 false不存在
  */
 public boolean sHasKey(String key,Object value){
  try {
   return redisTemplate.opsForSet().isMember(key,value);
  } catch (Exception e) {
   e.printStackTrace();
   return false;
  }
 }
 
 /**
  * 將資料放入set快取
  * @param key 鍵
  * @param values 值 可以是多個
  * @return 成功個數
  */
 public long sSet(String key,Object...values) {
  try {
   return redisTemplate.opsForSet().add(key,values);
  } catch (Exception e) {
   e.printStackTrace();
   return 0;
  }
 }
 
 /**
  * 將set資料放入快取
  * @param key 鍵
  * @param time 時間(秒)
  * @param values 值 可以是多個
  * @return 成功個數
  */
 public long sSetAndTime(String key,long time,Object...values) {
  try {
   Long count = redisTemplate.opsForSet().add(key,values);
   if(time>0) {
    expire(key,time);
   }
   return count;
  } catch (Exception e) {
   e.printStackTrace();
   return 0;
  }
 }
 
 /**
  * 獲取set快取的長度
  * @param key 鍵
  * @return
  */
 public long sGetSetSize(String key){
  try {
   return redisTemplate.opsForSet().size(key);
  } catch (Exception e) {
   e.printStackTrace();
   return 0;
  }
 }
 
 /**
  * 移除值為value的
  * @param key 鍵
  * @param values 值 可以是多個
  * @return 移除的個數
  */
 public long setRemove(String key,Object ...values) {
  try {
   Long count = redisTemplate.opsForSet().remove(key,values);
   return count;
  } catch (Exception e) {
   e.printStackTrace();
   return 0;
  }
 }
 //===============================list=================================
 
 /**
  * 獲取list快取的內容
  * @param key 鍵
  * @param start 開始
  * @param end 結束 0 到 -1代表所有值
  * @return
  */
 public List<Object> lGet(String key,long start,long end){
  try {
   return redisTemplate.opsForList().range(key,start,end);
  } catch (Exception e) {
   e.printStackTrace();
   return null;
  }
 }
 
 /**
  * 獲取list快取的長度
  * @param key 鍵
  * @return
  */
 public long lGetListSize(String key){
  try {
   return redisTemplate.opsForList().size(key);
  } catch (Exception e) {
   e.printStackTrace();
   return 0;
  }
 }
 
 /**
  * 通過索引 獲取list中的值
  * @param key 鍵
  * @param index 索引 index>=0時, 0 表頭,1 第二個元素,依次類推;index<0時,-1,表尾,-2倒數第二個元素,依次類推
  * @return
  */
 public Object lGetIndex(String key,long index){
  try {
   return redisTemplate.opsForList().index(key,index);
  } catch (Exception e) {
   e.printStackTrace();
   return null;
  }
 }
 
 /**
  * 將list放入快取
  * @param key 鍵
  * @param value 值
  * @return
  */
 public boolean lSet(String key,Object value) {
  try {
   redisTemplate.opsForList().rightPush(key,value);
   return true;
  } catch (Exception e) {
   e.printStackTrace();
   return false;
  }
 }
 
 /**
  * 將list放入快取
  * @param key 鍵
  * @param value 值
  * @param time 時間(秒)
  * @return
  */
 public boolean lSet(String key,long time) {
  try {
   redisTemplate.opsForList().rightPush(key,value);
   if (time > 0) {
    expire(key,time);
   }
   return true;
  } catch (Exception e) {
   e.printStackTrace();
   return false;
  }
 }
 
 /**
  * 將list放入快取
  * @param key 鍵
  * @param value 值
  * @return
  */
 public boolean lSet(String key,List<Object> value) {
  try {
   redisTemplate.opsForList().rightPushAll(key,List<Object> value,long time) {
  try {
   redisTemplate.opsForList().rightPushAll(key,time);
   }
   return true;
  } catch (Exception e) {
   e.printStackTrace();
   return false;
  }
 }
 
 /**
  * 根據索引修改list中的某條資料
  * @param key 鍵
  * @param index 索引
  * @param value 值
  * @return
  */
 public boolean lUpdateIndex(String key,long index,Object value) {
  try {
   redisTemplate.opsForList().set(key,index,value);
   return true;
  } catch (Exception e) {
   e.printStackTrace();
   return false;
  }
 }
 
 /**
  * 移除N個值為value
  * @param key 鍵
  * @param count 移除多少個
  * @param value 值
  * @return 移除的個數
  */
 public long lRemove(String key,long count,Object value) {
  try {
   Long remove = redisTemplate.opsForList().remove(key,count,value);
   return remove;
  } catch (Exception e) {
   e.printStackTrace();
   return 0;
  }
 }
 
 /**
  * 模糊查詢獲取key值
  * @param pattern
  * @return
  */
 public Set keys(String pattern){
  return redisTemplate.keys(pattern);
 }
 
 /**
  * 使用Redis的訊息佇列
  * @param channel
  * @param message 訊息內容
  */
 public void convertAndSend(String channel,Object message){
  redisTemplate.convertAndSend(channel,message);
 }
 
 
 
 /**
  * 根據起始結束序號遍歷Redis中的list
  * @param listKey
  * @param start 起始序號
  * @param end 結束序號
  * @return
  */
 public List<Object> rangeList(String listKey,long end) {
  //繫結操作
  BoundListOperations<String,Object> boundValueOperations = redisTemplate.boundListOps(listKey);
  //查詢資料
  return boundValueOperations.range(start,end);
 }
 /**
  * 彈出右邊的值 --- 並且移除這個值
  * @param listKey
  */
 public Object rifhtPop(String listKey){
  //繫結操作
  BoundListOperations<String,Object> boundValueOperations = redisTemplate.boundListOps(listKey);
  return boundValueOperations.rightPop();
 }
}

上面是Redis的配置檔案和自定義方法類,下面是呼叫Redis自定義方法類

package com.common.config;
 
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.StringRedisSerializer;
 
 
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport{
 /**
  * 配置自定義redisTemplate
  * @return
  */
 @Bean
 RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
 
  RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
  redisTemplate.setConnectionFactory(redisConnectionFactory);
  Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
  // 設定值(value)的序列化採用Jackson2JsonRedisSerializer。
  redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
  // 設定鍵(key)的序列化採用StringRedisSerializer。
  redisTemplate.setKeySerializer(new StringRedisSerializer());
  redisTemplate.setHashKeySerializer(new StringRedisSerializer());
 
  redisTemplate.afterPropertiesSet();
  return redisTemplate;
 }
}

上面這個是傳送郵件的類,把郵箱存在Redis裡方便效驗(不用查資料庫了),效能更好一點
在這裡使用@Autowired和@Configuration可以成功注入Redis和呼叫其set方法
關於SpringBoot使用Redis空指標的問題(不能成功注入的問題)

且redisUtil是有資料的是有資料的
但是我又新寫了個業務類名為AddLoginTooken,新增使用者登入tooken效驗用的

package com.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.MailSendException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;

import java.util.Random;

@Configuration
public class SetMail {

 @Autowired
 RedisTemplate redisTemplate;

 @Autowired
 RedisUtil redisUtil;

 @Autowired
 private JavaMailSender javaMailSender;

 Logger logger = LoggerFactory.getLogger(this.getClass());

 public String sendMail(String mail){
  String checkCode = String.valueOf(new Random().nextInt(899999) + 100000);
  SimpleMailMessage message = new SimpleMailMessage();
  try {
   redisUtil.set(mail,checkCode,1);
   message.setFrom("[email protected]");
   message.setTo(mail);
   message.setSubject("歡迎成為寵物救助平臺的使用者");
   message.setText("您的註冊驗證碼為:" + checkCode);

   javaMailSender.send(message);
   logger.info("郵件傳送成功");
  } catch (MailSendException e) {
   logger.error("目標郵箱不存在");
  } catch (Exception e) {
   e.printStackTrace();
   logger.error("文字郵件傳送異常");
  }
  return checkCode;

 }
}

和那個setMail類一模一樣的程式碼,一模一樣的註釋,而且都有spring的小圖示,說明應該是都注入進去了呀

在這裡插入圖片描述

但是呼叫這個卻有空指標的問題:

package com.common.utils;

import com.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.Date;
import java.util.UUID;

@Configuration
public class AddLoginTooken {

 @Autowired
 RedisTemplate redisTemplate;

 @Autowired
 RedisUtil redisUtil;

 public User addLoginTicket(User user){

  Date date = new Date();
  date.setTime(date.getTime()+1000*3600*30);
  user.setUser_tooken(UUID.randomUUID().toString().replaceAll("-",""));

  String user_tooken = user.getUser_tooken();
  redisUtil.set("user_tooken",user_tooken);

  return user;

 }

}

debug發現redisUtil為空

在這裡插入圖片描述

我解決他的第一個想法是在Application里加一個掃描

java.lang.NullPointerException
	at com.common.utils.AddLoginTooken.addLoginTicket(AddLoginTooken.java:26)
	at com.service.impl.LoginServiceImpl.login(LoginServiceImpl.java:39)
	at com.controller.LoginController.login(LoginController.java:33)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)

但是還是不行,重啟IDEA和清快取都不行

求解

到此這篇關於關於SpringBoot使用Redis空指標的問題(不能成功注入的問題)的文章就介紹到這了,更多相關SpringBoot使用Redis空指標內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!