Easymall项目分布式拆分整合(八)

                         Easymall项目分布式拆分整合(八)


目录

                         Easymall项目分布式拆分整合(八)

一.User用户系统的2个延伸问题

1.登录顶替

1.UserController类

2.UserService类

2.30分钟超时突然断开

1.解决办法:实现续租逻辑

2.UserController类

3.userService类


一.User用户系统的2个延伸问题

1.登录顶替

  • 每次登录时,利用唯一值判断当前用户是否曾经登录过; user_id相关,value就是登录时创建的ticket
  • 发现没有key,从来没有登陆过,直接执行登录逻辑
  • 发现有值,有人曾经登录过,获取ticket,del删除,执行后续登录逻辑

1.UserController类

	//验证登录的用户名密码是否正确
	@RequestMapping("login")
	public String doLogin(User user){
		String ticket=userService.doLogin(user);
		//成功登录返回redis的key,失败返回""
		return ticket;
	}

2.UserService类

	@Autowired
	private RedisCumUtils redis;
	public String doLogin(User user) {
		//查询一下数据库数据,是否存在userExist
		//处理用户密码加密
		user.setUserPassword(MD5Util.md5(user.getUserPassword()));
		User exist=userMapper.selectExist(user);
		try{
			if(exist==null){//登录失败
				return "";
			}else{
				//通过唯一值确定是否已经存在
				String alterKey="alterKey_"+exist.getUserId();
				if(redis.isExist(alterKey)){
					redis.delete(redis.query(alterKey));
				}
			//表示成功,存储在redis返回key值
			
			String ticket=MD5Util.md5("EM_TICKET"+System.currentTimeMillis()
			+exist.getUserId());
			//准备value值,mapper转化user为json字符串
			String userJson=MapperUtils.MP.writeValueAsString(exist);
			//set数据到redis供后续逻辑使用
			redis.addOrUpdateExpire(ticket, userJson, 60*30);
			//生产一个
			redis.addOrUpdate(alterKey, ticket);
			//验证最多一个用户登录,顶替登录逻辑 
			//TODO
			return ticket;
			}
		}catch(Exception e){
			e.printStackTrace();
			return "";
		}
	}

在登录方法里先做判断,获取当前值,判断是否已经存在,如果存在,把之前的值删除,保存新的数据

2.30分钟超时突然断开

用户在访问系统过程中,总是通过redis的ticket来判断登录用户的状态,获取用户的信息,从而进行各种操作(购物车,订单提交)

一旦数据超时30分钟,就会突然在用户浏览器无法访问使用用户登录状态;

1.解决办法:实现续租逻辑

每次校验登录状态,判断剩余时间ttl,如果发现登录状态的ticket在操作时,判断剩余时间小于10分钟,续租5分钟

工具类封装方法

1.判断剩余时间

//拿到剩余时间
	public Long queryTimeLeft(String key){
		ShardedJedis jedis = pool.getResource();
		try{
			return jedis.ttl(key);
		}catch(Exception e){
			e.printStackTrace();
			return 0l;
		}finally{
			pool.returnBrokenResource(jedis);
		}
	}

2.延长时间

//延迟时间
	public void expandTime(String key,Integer seconds){
		ShardedJedis jedis = pool.getResource();
		try{
			jedis.expire(key, seconds);
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			pool.returnBrokenResource(jedis);
		}
	}

2.UserController类

//校验登录状态,查询redis数据
	@RequestMapping("query/{ticket}")
	public String checkTicket(@PathVariable String ticket
			,String callback){
		try{
			//走到redis校验数据
			String userJson=userService.queryTicket(ticket);
			//封装返回的json数据,SysResult
			SysResult result=null;
			if(StringUtils.isNotEmpty(userJson)){//登录状态正常
				result=SysResult.build(200, "", userJson);
			}else{
				result=SysResult.build(201, "", null);
			}
			//将result解析成json等待返回使用
			String resultJson=MapperUtils.MP.writeValueAsString(result);
			//判断请求需要的数据格式,callback
			if(callback==null){
				return resultJson;//作为json字符串返回
			}else{
				return callback+"("+resultJson+")";//jsonp格式返回
			}
		}catch(Exception e){
			return "";
		}
	}

3.userService类

	public String queryTicket(String ticket) {
		//TODO 超时时间延长--续租
				//每次访问到这个方法,都是由于用户访问了head.jsp的js代码
				//判断剩余时间
				Long time=redis.queryTimeLeft(ticket);
				if(time<60*10){//将时间添加5分钟做续租
					Integer extTime=(int) (time+60*5);
					redis.expandTime(ticket, extTime);
				}
				return redis.query(ticket);
	}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值