2步轻松搞定SpringBoot2.x分布式session共享,极少配置

点击上方蓝色字体,选择“标星公众号”

优质文章,第一时间送达

99套Java企业级实战项目

4000G架构师资料

作者 :日常打BUG

转载自 :blog.csdn.net/qq_38023253/article/details/90581455

集成redis

1.引入jar包

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

2.配置属性
在application.properties增加Redis服务的相关信息

#################redis单服务基础配置#################
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.password=
spring.redis.port=6379

3. RedisTemplate配置

/**
   * RedisTemplate配置
     */
  @Bean
  public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
    // 设置序列化
    Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(
        Object.class);
    ObjectMapper om = new ObjectMapper();
    om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    jackson2JsonRedisSerializer.setObjectMapper(om);
    // 配置redisTemplate
    RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
    redisTemplate.setConnectionFactory(lettuceConnectionFactory);
    RedisSerializer<?> stringSerializer = new StringRedisSerializer();
    redisTemplate.setKeySerializer(stringSerializer);// key序列化
    redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);// value序列化
    redisTemplate.setHashKeySerializer(stringSerializer);// Hash key序列化
    redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);// Hash value序列化
    redisTemplate.afterPropertiesSet();
    return redisTemplate;
  }

不配置RedisTemplate,也是可以自动注入StringRedisTemplate进行redis的读写操作,但是不能注入 RedisTemplate<K, V>对象,这里先配置了 RedisTemplate<String, Object>来操作redis

@RequestMapping(path = "/redis" )
public class RedisController {
    @Autowired
  private StringRedisTemplate stringRedisTemplate;

  @Autowired
  private RedisTemplate<String, Object> redisTemplate;
       /**
   * stringRedisTemplate 传入对象
   * @return
   */
  @GetMapping("/test2")
  public UUser testRedis2() {
    UUser user = new UUser();
    user.setUserName("test2");
    user.setEmail("11费@QQ.com");
    stringRedisTemplate.opsForValue().set("A2", JSONObject.toJSONString(user));
    UUser stu1 = JSONObject.parseObject(stringRedisTemplate.opsForValue().get("A2"), UUser.class);
    return stu1;
  }

  /**
   * redisTemplate传入对象
   * @return
   */
  @GetMapping("/test1")
  public UUser testRedis1() {
    UUser user = new UUser();
    user.setUserName("test1");
    user.setEmail("11飞@163.com");
    redisTemplate.opsForValue().set("A1", user);
    UUser stu1 = (UUser) redisTemplate.opsForValue().get("A1");
// redisTemplate.delete("A1");
    return stu1;
  }
}

通过localhost:8080/redis/test1、localhost:8080/redis/test2来进行验证

5.可配置连接池

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

Jedis与Lettuce的区别:

Jedis在实现上是直接连接的redis server,如果在多线程环境下是非线程安全的,这个时候只有使用连接池,为每个Jedis实例增加物理连接

Lettuce的连接是基于Netty的,连接实例(StatefulRedisConnection)可以在多个线程间并发访问,应为StatefulRedisConnection是线程安全的,所以一个连接实例(StatefulRedisConnection)就可以满足多线程环境下的并发访问,当然这个也是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例。

springboot2.0后将之前的jedis已经改成Lettuce,默认使用Lettuce

集成spring-session-Redis

参考 https://blog.csdn.net/qq_35206261/article/details/82289066

1 引入jar包

<dependency>
      <groupId>org.springframework.session</groupId>
      <artifactId>spring-session-data-redis</artifactId>
    </dependency>


2 配置

@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1900)
public class RedisSessionConfig {


}

application.properties增加

spring.session.store-type=redis

也可不进行配置,都有默认值,开箱即用。
这里的maxInactiveIntervalInSeconds设置还没生效,原因还在寻找中。

@RestController
@RequestMapping(path = "/redis" )
public class RedisController {
  /**
   * session测试
   * @param request
   * @return
   */
  @RequestMapping(value = "/session", method = RequestMethod.GET)
  public Map<String, String> addSession (HttpServletRequest request){
    String sessionId = request.getSession().getId();
    String requestURI = request.getRequestURI() + ":"  + request.getServerPort();
    // 向session中保存用户信息 key规则:user + "_" + uid
    request.getSession().setAttribute("user_1", "{uid:1,username:11@qq.com}");


    Map<String, String> sessionInfoMap = new HashMap<>(2);
    sessionInfoMap.put("sessionId", sessionId);
    sessionInfoMap.put("requestURI", requestURI);
    return sessionInfoMap;
  }

  /**
   * session测试
   * @param request
   * @return
   */
  @RequestMapping(value = "/getSession", method = RequestMethod.GET)
  public Map<String, String> getSession (HttpServletRequest request){
    String sessionId = request.getSession().getId();
    String requestURI = request.getRequestURI() + ":"  + request.getServerPort();

    Map<String, String> sessionInfoMap = new HashMap<>(2);
    // 获取session中uid为1的用户的信息
    String user_1 = (String) request.getSession().getAttribute("user_1");

    sessionInfoMap.put("sessionId", sessionId);
    sessionInfoMap.put("requestURI", requestURI);
    sessionInfoMap.put("user_1", user_1);
    return sessionInfoMap;
  }
}

分别启动不同的端口号,使用浏览器、postman、rest client测试sessionID

结果:使用同一工具,例如postman测试不同端口号请求,其sessionId值一致,并且能从一个端口获取另一个端口存在request中的user信息。session数据存放在redis中

1.8080端口往session中放入对象

2.8081端口请求session中对象

实验效果:

sessionId一致,且成功获取了session中对象,不同端口间session实现共享

开箱即用的便利

注释掉第二步集成spring-session-Redis后的配置,只导入jar包进行测试,其session还是存入了Redis中,结果如上面二图所示,跟增加配置后的效果一致

将引入spring-session-Redis jar包也注释掉 进行测试,也就是回到没集成session-redis前,如下图所示,此时session不再存放在Redis中,且不同端口号之间的session不互通,相同端口session也会有过期时间。

1.8080往session中放入对象

2.8081读取session信息


3.8081再次读取session信息(刷新一次)

结果:相同端口之间的session共享,不同端口间session隔离
出现上下两种情况是springboot开箱即用的效果,引入jar包后无需配置即可使用。

有热门推荐????

BigDecimal使用不当,老板的损失照样从你工资里扣

好神奇:RocketMQ一行代码造成大量消息丢失

Spring Boot 2.3.0 新特性:优雅停机

秒杀系统设计最全攻略!!

没学历,写简历这几个细节很重要!

干货分享:扫码关注下面的公众号后台回复“99”领取99套实战项目+资料

想充电就关注序员闪充宝

文章有帮助的话,在看,转发吧。

谢谢支持哟 (*^__^*)

@RequestMapping("/testjson") @ResponseBody public Map<String,Object> testjson(String data) throws JSONException { Map<String,Object> map = new HashMap<>(); // String objectStr="{\\\\"username\":\"老李\",\"nickname\":\"李刚\",\"remark\":\"肚痛\"}"; // String basestr = Base64.getBase64(objectStr); String javabean = Base64.getFromBase64(data);//解密 // System.out.println(javabean+"解密后"); JSONObject JSON = JSONObject.parseObject(javabean);//转json String j = JSON.get("data").toString();//根据key获取value // System.out.println(j+"解密后"); JSONObject JSONs = JSONObject.parseObject(j);//value转json SysUser sysUser = JSONs.toJavaObject(SysUser.class);//json转实体类 System.out.println(sysUser.getUsername()+"名字"); return map; } 测试类 package com.example.hello; import com.alibaba.fastjson.JSONObject; import com.example.hello.util.Base64; import com.example.hello.util.HttpClientUtil; import org.junit.Test; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; public class HelloApplicationTests { public static final String baseUrl = "http://localhost:8080/"; @Test public void contextLoads() throws UnsupportedEncodingException { String requestUrl = baseUrl + "testjson"; Map<String, Object> argsMap = new HashMap<String, Object>(); argsMap.put("data", "{'username':'老李','nickname':'李刚','remark':'肚痛'}"); String argsStr = JSONObject.toJSONString(argsMap); System.out.println("加密前"+argsStr); String base = Base64.getBase64(argsStr); argsStr = URLEncoder.encode(base,"utf8"); HttpClientUtil.httpRequest(requestUrl + "?data=" + argsStr, ""); System.out.println("10000000000"); } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值