關(guān)于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;
}
}
/**
* 根據(jù)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;
}
}
/**
* 普通緩存放入并設(shè)置時間
* @param key 鍵
* @param value 值
* @param time 時間(分鐘) time要大于0 如果time小于等于0 將設(shè)置無限期
* @return true成功 false 失敗
*/
public boolean set(String key,Object value,long time){
try {
if(time>0){
redisTemplate.opsForValue().set(key, value, time, 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對應(yīng)的所有鍵值
* @param key 鍵
* @return 對應(yīng)的多個鍵值
*/
public Map<Object,Object> hmget(String key){
return redisTemplate.opsForHash().entries(key);
}
/**
* HashSet
* @param key 鍵
* @param map 對應(yīng)多個鍵值
* @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 并設(shè)置時間
* @param key 鍵
* @param map 對應(yīng)多個鍵值
* @param time 時間(秒)
* @return true成功 false失敗
*/
public boolean hmset(String key, Map<String,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表中放入數(shù)據(jù),如果不存在將創(chuàng)建
* @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表中放入數(shù)據(jù),如果不存在將創(chuàng)建
* @param key 鍵
* @param item 項
* @param value 值
* @param time 時間(秒) 注意:如果已存在的hash表有時間,這里將會替換原有的時間
* @return true 成功 false失敗
*/
public boolean hset(String key,String item,Object value,long time) {
try {
redisTemplate.opsForHash().put(key, item, 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遞增 如果不存在,就會創(chuàng)建一個 并把新增后的值返回
* @param key 鍵
* @param item 項
* @param by 要增加幾(大于0)
* @return
*/
public double hincr(String key, String item,double by){
return redisTemplate.opsForHash().increment(key, item, by);
}
/**
* hash遞減
* @param key 鍵
* @param item 項
* @param by 要減少記(小于0)
* @return
*/
public double hdecr(String key, String item,double by){
return redisTemplate.opsForHash().increment(key, item,-by);
}
//============================set=============================
/**
* 根據(jù)key獲取Set中的所有值
* @param key 鍵
* @return
*/
public Set<Object> sGet(String key){
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 根據(jù)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;
}
}
/**
* 將數(shù)據(jù)放入set緩存
* @param key 鍵
* @param values 值 可以是多個
* @return 成功個數(shù)
*/
public long sSet(String key, Object...values) {
try {
return redisTemplate.opsForSet().add(key, values);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 將set數(shù)據(jù)放入緩存
* @param key 鍵
* @param time 時間(秒)
* @param values 值 可以是多個
* @return 成功個數(shù)
*/
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 移除的個數(shù)
*/
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緩存的內(nèi)容
* @param key 鍵
* @param start 開始
* @param end 結(jié)束 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倒數(shù)第二個元素,依次類推
* @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, Object value, 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, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 將list放入緩存
* @param key 鍵
* @param value 值
* @param time 時間(秒)
* @return
*/
public boolean lSet(String key, List<Object> value, long time) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根據(jù)索引修改list中的某條數(shù)據(jù)
* @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 移除的個數(shù)
*/
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 消息內(nèi)容
*/
public void convertAndSend(String channel, Object message){
redisTemplate.convertAndSend(channel,message);
}
/**
* 根據(jù)起始結(jié)束序號遍歷Redis中的list
* @param listKey
* @param start 起始序號
* @param end 結(jié)束序號
* @return
*/
public List<Object> rangeList(String listKey, long start, long end) {
//綁定操作
BoundListOperations<String, Object> boundValueOperations = redisTemplate.boundListOps(listKey);
//查詢數(shù)據(jù)
return boundValueOperations.range(start, end);
}
/**
* 彈出右邊的值 --- 并且移除這個值
* @param listKey
*/
public Object rifhtPop(String listKey){
//綁定操作
BoundListOperations<String, Object> boundValueOperations = redisTemplate.boundListOps(listKey);
return boundValueOperations.rightPop();
}
}
上面是Redis的配置文件和自定義方法類,下面是調(diào)用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);
// 設(shè)置值(value)的序列化采用Jackson2JsonRedisSerializer。
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
// 設(shè)置鍵(key)的序列化采用StringRedisSerializer。
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
上面這個是發(fā)送郵件的類,把郵箱存在Redis里方便效驗(不用查數(shù)據(jù)庫了),性能更好一點
在這里使用@Autowired和@Configuration可以成功注入Redis和調(diào)用其set方法

且redisUtil是有數(shù)據(jù)的是有數(shù)據(jù)的
但是我又新寫了個業(yè)務(wù)類名為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("742919609@qq.com");
message.setTo(mail);
message.setSubject("歡迎成為寵物救助平臺的用戶");
message.setText("您的注冊驗證碼為:" + checkCode);
javaMailSender.send(message);
logger.info("郵件發(fā)送成功");
} catch (MailSendException e) {
logger.error("目標(biāo)郵箱不存在");
} catch (Exception e) {
e.printStackTrace();
logger.error("文本郵件發(fā)送異常");
}
return checkCode;
}
}
和那個setMail類一模一樣的代碼,一模一樣的注釋,而且都有spring的小圖標(biāo),說明應(yīng)該是都注入進去了呀

但是調(diào)用這個卻有空指針的問題:
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發(fā)現(xiàn)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和清緩存都不行
求解
到此這篇關(guān)于關(guān)于SpringBoot使用Redis空指針的問題(不能成功注入的問題)的文章就介紹到這了,更多相關(guān)SpringBoot使用Redis空指針內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用SpringBoot 配置Oracle和H2雙數(shù)據(jù)源及問題
這篇文章主要介紹了使用SpringBoot 配置Oracle和H2雙數(shù)據(jù)源及問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
Java中tomcat memecached session 共享同步問題的解決辦法
這篇文章主要介紹了Java中tomcat memecached session 共享同步問題的解決辦法的相關(guān)資料,需要的朋友可以參考下2015-10-10
IntelliJ?IDEA2022中的Java文檔注釋設(shè)置、操作方法
這篇文章主要介紹了IntelliJ?IDEA2022中的Java文檔注釋設(shè)置、操作詳述,本文通過圖文并茂的方式給大家介紹IDEA2022?文檔注釋設(shè)置方法,需要的朋友可以參考下2022-08-08
Java中Collection與Collections的區(qū)別詳解
這篇文章主要為大家詳細介紹了Java中Collection與Collections的區(qū)別,文中有詳細的代碼示例,具有一定的參考價值,感興趣的同學(xué)可以參考一下2023-06-06
關(guān)于如何搭建CAS服務(wù)并將CAS項目導(dǎo)入IDEA
這篇文章主要介紹了關(guān)于如何搭建CAS服務(wù)并將CAS項目導(dǎo)入IDEA的問題,文中提供了詳細的圖文講解,需要的朋友可以參考下,如果有錯誤的地方還請指正2023-03-03
詳解Java的內(nèi)置異常以及創(chuàng)建自定義異常子類的方法
這篇文章主要介紹了詳解Java的內(nèi)置異常以及創(chuàng)建自定義異常子類的方法,是Java入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-09-09
form-data與x-www-form-urlencoded的區(qū)別以及知識延伸
這篇文章主要給大家介紹了關(guān)于form-data與x-www-form-urlencoded的區(qū)別以及知識延伸,form-data和x-www-form-urlencoded都是HTTP請求中用于傳輸表單數(shù)據(jù)的編碼格式,需要的朋友可以參考下2023-11-11

