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);
	}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章