SpringBoot以Redis+MySQLhead请求头验证的方式谈话

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 Tair(兼容Redis),内存型 2GB
简介: SpringBoot以Redis+MySQLhead请求头验证的方式谈话

主页:写程序的小王叔叔的博客欢迎来访👀

支持:点赞收藏关注


1 配置

1 pom.xml

<!--引用Jedis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency>

2 spring.xml

##################Redis配置######### Redis服务器地址spring.redis.host=127.0.0.1
# Redis服务器连接端口spring.redis.port=6379
# Redis服务器连接密码(默认为空)spring.redis.password=123456789
# 连接池最大连接数(使用负值表示没有限制)spring.redis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接spring.redis.pool.min-idle=0
# 连接超时时间(毫秒)spring.redis.timeout=0
spring.redis.commandTimeout=5000
#连接的数据库spring.redis.database=0
# redis.clusterspring.redis.cluster.nodes=127.0.0.1:6379
####################################################

3 CacheManager

直接配置会提示错误:

image.png

new RedisCacheManager(redisTemplate)没有此构造

现在这么写会有报错

The constructor RedisCacheManager(RedisTemplate) is undefined。

这是因为Spring Boot 2.x版本删除了RedisCacheManager这个构造器, 也不可以通过之前的setDefaultExpiration方法设置默认的缓存过期时间等。

通过设置RedisConnectionFactory factory进行解决,最后RedisConfig.java如下:

/**** 配置redis缓存* @author Administrator**/@Configuration@EnableCaching//启用缓存publicclassRedisConfigextendsCachingConfigurerSupport{
//注入 RedisConnectionFactory@AutowiredpublicRedisConnectionFactoryredisConnectionFactory;
//实例化 RedisTemplate 对象 设置数据存入 redis 的序列化方式@BeanpublicRedisTemplate<String, Object>functionDomainRedisTemplate() {
RedisTemplate<String, Object>redisTemplate=newRedisTemplate<>();
//定义key生成策略redisTemplate.setKeySerializer(newStringRedisSerializer());
redisTemplate.setHashKeySerializer(newStringRedisSerializer());
redisTemplate.setHashValueSerializer(newJdkSerializationRedisSerializer());
redisTemplate.setValueSerializer(newJdkSerializationRedisSerializer());
redisTemplate.setConnectionFactory(redisConnectionFactory);
returnredisTemplate;
    }
//缓存管理器 --》配置缓存时间@BeanpublicCacheManagercacheManager(RedisConnectionFactoryfactory) {
RedisCacheConfigurationconfig=RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(-1));
RedisCacheManagercacheManager=RedisCacheManager.builder(factory).cacheDefaults(config).build();
returncacheManager;
    }
}

image.png

创建实体类,一定要实现Serializable序列化,因为redis保存对象的时候要求对象是序列化

如:


实体类配置好后,将redis的操作的接口类进行封装后,进行使用:

publicinterfaceRedisService{
publicbooleanset(finalStringkey, Objectvalue);
publicbooleanset(finalStringkey, Objectvalue, LongexpireTime);
publicvoidremove(finalString... keys);
publicvoidremovePattern(finalStringpattern);
publicvoidremove(finalStringkey);
publicbooleanexists(finalStringkey);
publicObjectget(finalStringkey);
publicvoidhmSet(Stringkey, ObjecthashKey, Objectvalue);
publicObjecthmGet(Stringkey, ObjecthashKey);
publicvoidlPush(Stringk,Objectv);
publicList<Object>lRange(Stringk, longl, longl1);
publicvoidadd(Stringkey,Objectvalue);
publicSet<Object>setMembers(Stringkey);
publicvoidzAdd(Stringkey,Objectvalue,doublescoure);
publicSet<Object>rangeByScore(Stringkey,doublescoure,doublescoure1);
}
package***;
importjava.io.Serializable;
importjava.util.List;
importjava.util.Set;
importjava.util.concurrent.TimeUnit;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.data.redis.core.HashOperations;
importorg.springframework.data.redis.core.ListOperations;
importorg.springframework.data.redis.core.RedisTemplate;
importorg.springframework.data.redis.core.SetOperations;
importorg.springframework.data.redis.core.ValueOperations;
importorg.springframework.data.redis.core.ZSetOperations;
importorg.springframework.stereotype.Service;
@SuppressWarnings("all")
@ServicepublicclassRedisServiceImplimplementsRedisService{
@AutowiredprivateRedisTemplateredisTemplate;
/*** 写入缓存* @param key* @param value* @return*/publicbooleanset(finalStringkey, Objectvalue) {
booleanresult=false;
try {
ValueOperations<Serializable, Object>operations=redisTemplate.opsForValue();
operations.set(key, value);
result=true;
        } catch (Exceptione) {
e.printStackTrace();
        }
returnresult;
    }
/*** 写入缓存设置时效时间* @param key* @param value* @return*/publicbooleanset(finalStringkey, Objectvalue, LongexpireTime) {
booleanresult=false;
try {
ValueOperations<Serializable, Object>operations=redisTemplate.opsForValue();
operations.set(key, value);
redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
result=true;
        } catch (Exceptione) {
e.printStackTrace();
        }
returnresult;
    }
/*** 批量删除对应的value* @param keys*/publicvoidremove(finalString... keys) {
for (Stringkey : keys) {
remove(key);
        }
    }
/*** 批量删除key* @param pattern*/publicvoidremovePattern(finalStringpattern) {
Set<Serializable>keys=redisTemplate.keys(pattern);
if (keys.size() >0)
redisTemplate.delete(keys);
    }
/*** 删除对应的value* @param key*/publicvoidremove(finalStringkey) {
if (exists(key)) {
redisTemplate.delete(key);
        }
    }
/*** 判断缓存中是否有对应的value* @param key* @return*/publicbooleanexists(finalStringkey) {
returnredisTemplate.hasKey(key);
    }
/*** 读取缓存* @param key* @return*/publicObjectget(finalStringkey) {
Objectresult=null;
ValueOperations<Serializable, Object>operations=redisTemplate.opsForValue();
result=operations.get(key);
returnresult;
    }
/*** 哈希 添加* @param key* @param hashKey* @param value*/publicvoidhmSet(Stringkey, ObjecthashKey, Objectvalue){
HashOperations<String, Object, Object>hash=redisTemplate.opsForHash();
hash.put(key,hashKey,value);
    }
/*** 哈希获取数据* @param key* @param hashKey* @return*/publicObjecthmGet(Stringkey, ObjecthashKey){
HashOperations<String, Object, Object>hash=redisTemplate.opsForHash();
returnhash.get(key,hashKey);
    }
/*** 列表添加* @param k* @param v*/publicvoidlPush(Stringk,Objectv){
ListOperations<String, Object>list=redisTemplate.opsForList();
list.rightPush(k,v);
    }
/*** 列表获取* @param k* @param l* @param l1* @return*/publicList<Object>lRange(Stringk, longl, longl1){
ListOperations<String, Object>list=redisTemplate.opsForList();
returnlist.range(k,l,l1);
    }
/*** 集合添加* @param key* @param value*/publicvoidadd(Stringkey,Objectvalue){
SetOperations<String, Object>set=redisTemplate.opsForSet();
set.add(key,value);
    }
/*** 集合获取* @param key* @return*/publicSet<Object>setMembers(Stringkey){
SetOperations<String, Object>set=redisTemplate.opsForSet();
returnset.members(key);
    }
/*** 有序集合添加* @param key* @param value* @param scoure*/publicvoidzAdd(Stringkey,Objectvalue,doublescoure){
ZSetOperations<String, Object>zset=redisTemplate.opsForZSet();
zset.add(key,value,scoure);
    }
/*** 有序集合获取* @param key* @param scoure* @param scoure1* @return*/publicSet<Object>rangeByScore(Stringkey,doublescoure,doublescoure1){
ZSetOperations<String, Object>zset=redisTemplate.opsForZSet();
returnzset.rangeByScore(key, scoure, scoure1);
    }
}

redis-key的整理,创建一个key的管理文件,进行将所有要缓存的业务类进行统一管理,如

/***** 整合redis缓存key文件* @author Administrator**/publicclassRedisServiceKey  {
publicstaticfinalStringProduct_REDIS_KEY="Product_KEY"; 
}

基本配置就全部完成,可以启动。


启动后可能遇见的问题:

1.问题:HostAndPort need to be seperated by ':'.

image.png

解决:如上图,添加端口127.0.0.1:6379

扩展:host变成ip:port,集群多个ip和端口用“,”分割,

2.问题:再次启动出现问题:org.springframework.data.redis.core.HashOperations

image.png

解决:缺少redis中HashOperationsbean,其实在下面已经提示了,所以在redisconfig中注入bean,并同时在再调用下就可以了

//实例化 HashOperations 对象,可以使用 Hash 类型操作

 

@BeanpublicHashOperations<String, String, Object>hashOperations(RedisTemplate<String, Object>redisTemplate) {
returnredisTemplate.opsForHash();
    }
//实例化 ValueOperations 对象,可以使用 String 操作@BeanpublicValueOperations<String, Object>valueOperations(RedisTemplate<String, Object>redisTemplate) {
returnredisTemplate.opsForValue();
    }
//实例化 ListOperations 对象,可以使用 List 操作@BeanpublicListOperations<String, Object>listOperations(RedisTemplate<String, Object>redisTemplate) {
returnredisTemplate.opsForList();
    }
//实例化 SetOperations 对象,可以使用 Set 操作@BeanpublicSetOperations<String, Object>setOperations(RedisTemplate<String, Object>redisTemplate) {
returnredisTemplate.opsForSet();
    }
//实例化 ZSetOperations 对象,可以使用 ZSet 操作@BeanpublicZSetOperations<String, Object>zSetOperations(RedisTemplate<String, Object>redisTemplate) {
returnredisTemplate.opsForZSet();
    }

如上图的Service.java文件中

image.png

3.问题:Cannot retrieve initial cluster partitions from initial URIs [RedisURI [host='127.0.0.1', port=6379]]

当前问题说:在配置redis集群时,地址用的是127的IP

解决 :在配置集群时,一定要用IP地址,不要用127/localhost等代替IP

4.问题:Command timed out 连接请求超时

将spring.xml中时间设长一点

# 连接超时时间(毫秒)
spring.redis.timeout=200
spring.redis.commandTimeout=500000

通过上面的配置完全解决这个问题的所在.

2、通过redis实现CRUD

1 存list

Redis中的 ListOperations ---------> 存list

在controller.java中引入RedisTemplate

@Autowired
  protected RedisTemplate<String,Object> redisTemplate;
List<WxUsers> wxUserList = wxUsersService.findAll();
 redisTemplate.opsForList().rightPushAll(RedisServiceKey.WxMemberList_REDIS_KEY, wxUserList);

当前方法执行成功之后,在redis查看工具【Redis的初始,安装及运行和使用】中进行查看对应的redis-key的值:(可能会出现乱码情况,出现则进行修改RedisConfig.java中的setValueSerializer()的属性)

image.png

@Bean
    public RedisTemplate<String,Object> functionDomainRedisTemplate() {
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
       //定义key生成策略
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        return redisTemplate;
    }

附 : Springboot 、redis 、 jwt 实现token验证

  1. Token 为什么要存储到Redis?
  2. 1.Token 具有时效性,简单来说就是有效期,超过了这个期限Token 就会失效,需要用户重新登录。但是怎么在项目中实现这个时效性,这个时候就用到Redis,Redis天然支持支持设置过期时间以及通过一些第三方提供包的API到达自动续时效果。
  3. 2.Redis采用NoSQL技术,可以支持每秒十几万此的读/写操作,其性能远超数据库,在请求数量较多的时候,Redis也可以从容应对
  4. 3.用户登录信息一般不需要长效储存,放在内存中,可以减少数据库的压力;

2 取list

Redis中的 取出刚存的 list 判断是否存在 redisTemplate.hasKey(Constants.USER_TOKEN_KEY );

存在就取出 redisTemplate.opsForValue().get( Constants.USER_TOKEN_KEY );

List<WxUsers>wxUserList=redisTemplate.opsForList().range(RedisServiceKey.WxMemberList_REDIS_KEY, 0, -1);
log.info(">>>>>>>>>>>>>>>list = {}", wxUserList);
Iterator<WxUsers>it=wxUserList.iterator();
while(it.hasNext()){
WxUserswxUser=it.next();
if(!token.equals(wxUser.getWx_userOpenId())) {
thrownewRuntimeException(ErrorMessage.error_login_no_user);    
                }
           }

3 比对某个值

通过引入 在拦截器中配置redis缓存机制 实现比对redis中值是否相同

/**** 存入list- redis 并取出 list - redis  - openid*/booleanhasKey=redisTemplate.hasKey(RedisServiceKey.WxMemberList_REDIS_KEY);
if(hasKey) {  
//取listList<WxUsers>wxUserList=redisTemplate.opsForList().range(RedisServiceKey.WxMemberList_REDIS_KEY, 0, -1);
log.info(">>>>>>>>>>>>>>>list = {}", wxUserList);
Iterator<WxUsers>it=wxUserList.iterator();
while(it.hasNext()){
WxUserswxUser=it.next();
if(token.equals(wxUser.getWx_userOpenId())) {
break;
                    } 
//                    // 验证 token//                      JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(token)).build();//                      try {//                          jwtVerifier.verify(token);//                      } catch (JWTVerificationException e) {//                          throw new RuntimeException("401");//                      }                  }
            }else {
//存listList<WxUsers>wxUserList=wxUsersService.findAll();
redisTemplate.opsForList().rightPushAll(RedisServiceKey.WxMemberList_REDIS_KEY, wxUserList);
thrownewRuntimeException(ErrorMessage.error_login_no_user);
            }

以上代码是比对的所需内容,但是在启动项目时,会提示下面错误,

image.png

原因

springboot拦截器是在Bean实例化之前执行的,所以Bean实例无法注入,也就是当我们想获取redis里面key是token的值时,发现redisTemplate没有是空的没有注入进来

解决

知道拦截器执行在bean实例化前执行的,那么我们就让拦截器执行的时候实例化拦截器Bean,在拦截器配置类里面先实例化拦截器,然后再获取。

拦截器配置:WebAppConfig.java

@ConfigurationpublicclassWebAppConfigextendsWebMvcConfigurerAdapter {  
//访问图片方法@OverridepublicvoidaddResourceHandlers(ResourceHandlerRegistryregistry) {      
Stringos=System.getProperty("os.name");        
if (os.toLowerCase().startsWith("win")) {  //如果是Windows系统registry.addResourceHandler("/images/**")
// /apple/**表示在磁盘apple目录下的所有资源会被解析为以下的路径                  .addResourceLocations("file:/D:/images/"); //媒体资源         } else {  //linux 和macregistry.addResourceHandler("/images/**")
                  .addResourceLocations("file:/usr/local/wwwroot/images/");   //媒体资源         }
super.addResourceHandlers(registry);
    }
//引用拦截器@OverridepublicvoidaddInterceptors(InterceptorRegistryregistry) {
registry.addInterceptor(handlerInterceptor()).addPathPatterns( "/**");
    }
//注册拦截器@BeanpublicHandlerInterceptorhandlerInterceptor(){
returnnewHandlerInterceptor();
    }  
}

过滤器配置:HandlerInterceptor.java

@ComponentpublicclassHandlerInterceptorextendsHandlerInterceptorAdapter {
privatestaticfinalorg.slf4j.Loggerlog=org.slf4j.LoggerFactory.getLogger(HandlerInterceptor.class);
@AutowiredprivateRedisTemplate<String, Object>redisTemplate;
@AutowiredprivateValueOperations<String,Object>opsForValue;
@AutowiredprivateWxUsersServicewxUsersService;
publicbooleanpreHandle(HttpServletRequestrequest, HttpServletResponseresponse, Objecthandler) {
Stringtoken=request.getHeader(Constants.USER_OPENID_KEY);// 从 http 请求头中取出 token// 如果是handler方法直接继续执行if (!handler.getClass().isAssignableFrom(HandlerMethod.class)) {
log.debug("This is handler.");
System.out.println("-----This is handler.-----");
returntrue;
        }
finalHandlerMethodhandlerMethod= (HandlerMethod) handler;
finalMethodmethod=handlerMethod.getMethod();
finalClass<?>clazz=method.getDeclaringClass();
// 如果有auth注解,进行token登录验证if (clazz.isAnnotationPresent(Auth.class) ||method.isAnnotationPresent(Auth.class)) {
log.debug("-----Auth----token:"+Constants.USER_OPENID_KEY+"-----");
System.out.println("-----Auth----token:"+Constants.USER_OPENID_KEY+"-----");
// 如果没有token进行拦截。if (token==null) {
thrownewRuntimeException(ErrorMessage.error_fresh_user_login_all);
            }
/**** 存入list- redis 并取出 list - redis  - openid*/booleanhasKey=redisTemplate.hasKey(RedisServiceKey.WxMemberList_REDIS_KEY);
if(hasKey) {    
//取listList<WxUsers>wxUserList=redisTemplate.opsForList().range(RedisServiceKey.WxMemberList_REDIS_KEY, 0, -1);
log.info(">>>>>>>>>>>>>>>list = {}", wxUserList);
Iterator<WxUsers>it=wxUserList.iterator();
while(it.hasNext()){
WxUserswxUser=it.next();
if(token.equals(wxUser.getWx_userOpenId())) {
break;
                      } 
//                    // 验证 token//                      JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(token)).build();//                      try {//                          jwtVerifier.verify(token);//                      } catch (JWTVerificationException e) {//                          throw new RuntimeException("401");//                      }                  }
            }else {
//存listList<WxUsers>wxUserList=wxUsersService.findAll();
redisTemplate.opsForList().rightPushAll(RedisServiceKey.WxMemberList_REDIS_KEY, wxUserList);
thrownewRuntimeException(ErrorMessage.error_login_no_user);
            }
returntrue;
        }
log.debug("-----Auth----No-----");
System.out.println("-----Auth----No-----");
returntrue;
    }
/*** 在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)*/@OverridepublicvoidafterCompletion(HttpServletRequestrequest, HttpServletResponseresponse, Objecthandler, Exceptionex) {
//        System.out.println("执行了TestInterceptor的afterCompletion方法");    }
}

4 传参调用

在小程序端head中输入要传的参数值:

image.png

//获取小程序平台基本信息wx.request({       
url: base.path.www+'WxPlatform/SelectWxPlatformInfo',
method: 'post',
data: {  },
header: { 'content-type': 'application/json;charset=UTF-8' , 'wx_userOpenId': wx.getStorageSync('wxMemberOpenId') },
success(res) {                 
wx.setStorageSync('wxPlatformInfo', res.data.data.wxPlatformInfo);
that.setData({
wxPlatformInfo: res.data.data.wxPlatformInfo          }); 
        }
      }),

然后在后台服务器中通过拦截器进行取head中的wx_userOpenId并进行验证是否验证通过

image.png

stringRedisTemplate.opsForValue().set("test", "100",60*10,TimeUnit.SECONDS);//向redis里存入数据和设置缓存时间stringRedisTemplate.opsForValue().get("test") //根据key获取缓存中的valstringRedisTemplate.boundValueOps("test").increment(-1); //val做-1操作stringRedisTemplate.boundValueOps("test").increment(1); //val +1stringRedisTemplate.getExpire("test") //根据key获取过期时间stringRedisTemplate.getExpire("test",TimeUnit.SECONDS) //根据key获取过期时间并换算成指定单位stringRedisTemplate.delete("test"); //根据key删除缓存stringRedisTemplate.hasKey("546545"); //检查key是否存在,返回boolean值stringRedisTemplate.expire("red_123",1000 , TimeUnit.MILLISECONDS); //设置过期时间stringRedisTemplate.opsForSet().add("red_123", "1","2","3");  //向指定key中存放set集合stringRedisTemplate.opsForSet().isMember("red_123", "1")  //根据key查看集合中是否存在指定数据stringRedisTemplate.opsForSet().members("red_123");  //根据key获取set集合


遗留问题就是 redis的客户端工具显示的key是乱码,正在解决,有知道的大佬请帮下谢谢了!!!

image.png

扩展:

@OverridepublicWxPlatformSelectWxDefaultPlatformInfo(StringwxAgentAddrId) {
WxAgentAddresswxAgentAddress=wxAgentAddressService.getDefaultPlatform(wxAgentAddrId);
WxPlatformplatform=wxPlatformRepository.getWxDafaultPlatformInfo(wxAgentAddress.getWx_areaId());
// 判断key是否存在if(!redisServiceImpl.exists(RedisServiceKey.WxPlatform_REDIS_KEY)) {
// 获取key的valueWxPlatformwxPlat= (WxPlatform) redisServiceImpl.get(RedisServiceKey.WxPlatform_REDIS_KEY);
if(wxPlat!=null&&!wxPlat.getWx_agentAddressId().equals(wxAgentAddrId)) {
// 删除keyredisServiceImpl.remove(RedisServiceKey.WxPlatform_REDIS_KEY);
      }
    } 
// 保存keyredisServiceImpl.set(RedisServiceKey.WxPlatform_REDIS_KEY, platform);  
//WxPlatform wxPlat = (WxPlatform) redisServiceImpl.get(RedisServiceKey.WxPlatform_REDIS_KEY);    returnplatform;
  }


在操作redis中的key时,每个key都要去判断下hashkey是否存在,然后进行业务的相关操作


⚠️注意 ~

💯本期内容就结束了,如果内容有误,麻烦大家评论区指出!

如有疑问❓可以在评论区💬或私信💬,尽我最大能力🏃‍♀️帮大家解决👨‍🏫!

如果我的文章有帮助到您,欢迎关注+点赞✔️鼓励博主🏃,您的鼓励是我分享的动力🏃🏃🏃~


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2月前
|
JSON 安全 算法
|
2月前
|
前端开发 Java 数据安全/隐私保护
用户登录前后端开发(一个简单完整的小项目)——SpringBoot与session验证(带前后端源码)全方位全流程超详细教程
文章通过一个简单的SpringBoot项目,详细介绍了前后端如何实现用户登录功能,包括前端登录页面的创建、后端登录逻辑的处理、使用session验证用户身份以及获取已登录用户信息的方法。
290 2
用户登录前后端开发(一个简单完整的小项目)——SpringBoot与session验证(带前后端源码)全方位全流程超详细教程
|
27天前
|
NoSQL Java API
springboot项目Redis统计在线用户
通过本文的介绍,您可以在Spring Boot项目中使用Redis实现在线用户统计。通过合理配置Redis和实现用户登录、注销及统计逻辑,您可以高效地管理在线用户。希望本文的详细解释和代码示例能帮助您在实际项目中成功应用这一技术。
30 4
|
29天前
|
消息中间件 NoSQL Java
Spring Boot整合Redis
通过Spring Boot整合Redis,可以显著提升应用的性能和响应速度。在本文中,我们详细介绍了如何配置和使用Redis,包括基本的CRUD操作和具有过期时间的值设置方法。希望本文能帮助你在实际项目中高效地整合和使用Redis。
45 2
|
2月前
|
NoSQL Java Redis
redis的基本命令,并用netty操作redis(不使用springboot或者spring框架)就单纯的用netty搞。
这篇文章介绍了Redis的基本命令,并展示了如何使用Netty框架直接与Redis服务器进行通信,包括设置Netty客户端、编写处理程序以及初始化Channel的完整示例代码。
62 1
redis的基本命令,并用netty操作redis(不使用springboot或者spring框架)就单纯的用netty搞。
|
2月前
|
缓存 NoSQL Java
springboot的缓存和redis缓存,入门级别教程
本文介绍了Spring Boot中的缓存机制,包括使用默认的JVM缓存和集成Redis缓存,以及如何配置和使用缓存来提高应用程序性能。
122 1
springboot的缓存和redis缓存,入门级别教程
|
2月前
|
缓存 NoSQL Java
Spring Boot与Redis:整合与实战
【10月更文挑战第15天】本文介绍了如何在Spring Boot项目中整合Redis,通过一个电商商品推荐系统的案例,详细展示了从添加依赖、配置连接信息到创建配置类的具体步骤。实战部分演示了如何利用Redis缓存提高系统响应速度,减少数据库访问压力,从而提升用户体验。
108 2
|
2月前
|
JSON NoSQL Java
springBoot:jwt&redis&文件操作&常见请求错误代码&参数注解 (九)
该文档涵盖JWT(JSON Web Token)的组成、依赖、工具类创建及拦截器配置,并介绍了Redis的依赖配置与文件操作相关功能,包括文件上传、下载、删除及批量删除的方法。同时,文档还列举了常见的HTTP请求错误代码及其含义,并详细解释了@RequestParam与@PathVariable等参数注解的区别与用法。
|
2月前
|
NoSQL Java Redis
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
这篇文章介绍了如何使用Spring Boot整合Apache Shiro框架进行后端开发,包括认证和授权流程,并使用Redis存储Token以及MD5加密用户密码。
36 0
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
|
1月前
|
JavaScript NoSQL Java
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
38 0