Spring Boot + Redis 解決陪玩平臺原始碼重複提交問題
前言
搭建 Redis 服務 API
/** * redis工具類 */@Componentpublic class RedisService { @Autowired private RedisTemplate redisTemplate; /** * 寫入快取 * @param key * @param value * @return */ public boolean set(finalString key, Object value) { boolean result = false; try { ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue(); operations.set(key, value); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } /** * 寫入快取設定時效時間 * @param key * @param value * @return */ public boolean setEx(finalString key, Object value, Long expireTime) { boolean result = false; try { ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue(); operations.set(key, value); redisTemplate.expire(key, expireTime, TimeUnit.SECONDS); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } /** * 判斷快取中是否有對應的value * @param key * @return */ public boolean exists(finalString key) { return redisTemplate.hasKey(key); } /** * 讀取快取 * @param key * @return */ public Objectget(finalString key) { Object result = null; ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue(); result = operations.get(key); return result; } /** * 刪除對應的value * @param key */ public boolean remove(finalString key) { if (exists(key)) { Boolean delete = redisTemplate.delete(key); return delete; } returnfalse; }}
自定義註解 AutoIdempotent
@Target({ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface AutoIdempotent {}
token 建立和檢驗
publicinterface TokenService { /** * 建立token * @return */ public String createToken(); /** * 檢驗token * @param request * @return */ public boolean checkToken(HttpServletRequest request) throws Exception;}
@Service publicclass TokenServiceImpl implements TokenService { @Autowired private RedisService redisService; /** * 建立token * * @return */ @Override public String createToken() { String str = RandomUtil.randomUUID(); StrBuilder token = new StrBuilder(); try { token.append(Constant.Redis.TOKEN_PREFIX).append(str); redisService.setEx(token.toString(), token.toString(),10000L); boolean notEmpty = StrUtil.isNotEmpty(token.toString()); if (notEmpty) { return token.toString(); } }catch (Exception ex){ ex.printStackTrace(); } returnnull; } /** * 檢驗token * * @param request * @return */ @Override public boolean checkToken(HttpServletRequest request) throws Exception { String token = request.getHeader(Constant.TOKEN_NAME); if (StrUtil.isBlank(token)) {// header中不存在token token = request.getParameter(Constant.TOKEN_NAME); if (StrUtil.isBlank(token)) {// parameter中也不存在token thrownew ServiceException(Constant.ResponseCode.ILLEGAL_ARGUMENT, 100); } } if (!redisService.exists(token)) { thrownew ServiceException(Constant.ResponseCode.REPETITIVE_OPERATION, 200); } boolean remove = redisService.remove(token); if (!remove) { thrownew ServiceException(Constant.ResponseCode.REPETITIVE_OPERATION, 200); } returntrue; }}
攔截器的配置
@Configuration publicclass WebConfiguration extends WebMvcConfigurerAdapter { @Resource private AutoIdempotentInterceptor autoIdempotentInterceptor; /** * 新增攔截器 * @param registry */ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(autoIdempotentInterceptor); super.addInterceptors(registry); }}
/** * 攔截器 */@Component publicclass AutoIdempotentInterceptor implements HandlerInterceptor { @Autowired private TokenService tokenService; /** * 預處理 * * @param request * @param response * @param handler * @return * @throws Exception */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (!(handler instanceof HandlerMethod)) { returntrue; } HandlerMethod handlerMethod = (HandlerMethod) handler; Method method = handlerMethod.getMethod(); //被ApiIdempotment標記的掃描 AutoIdempotent methodAnnotation = method.getAnnotation(AutoIdempotent.class); if (methodAnnotation != null) { try { return tokenService.checkToken(request);// 冪等性校驗, 校驗通過則放行, 校驗失敗則丟擲異常, 並通過統一異常處理返回友好提示 }catch (Exception ex){ ResultVo failedResult = ResultVo.getFailedResult(101, ex.getMessage()); writeReturnJson(response, JSONUtil.toJsonStr(failedResult)); throw ex; } } //必須返回true,否則會被攔截一切請求 returntrue; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } /** * 返回的json值 * @param response * @param json * @throws Exception */ private void writeReturnJson(HttpServletResponse response, String json) throws Exception{ PrintWriter writer = null; response.setCharacterEncoding("UTF-8"); response.setContentType("text/html; charset=utf-8"); try { writer = response.getWriter(); writer.print(json); } catch (IOException e) { } finally { if (writer != null) writer.close(); } }}
測試用例
@RestController publicclass BusinessController { @Resource private TokenService tokenService; @Resource private TestService testService; @PostMapping("/get/token") public String getToken(){ String token = tokenService.createToken(); if (StrUtil.isNotEmpty(token)) { ResultVo resultVo = new ResultVo(); resultVo.setCode(Constant.code_success); resultVo.setMessage(Constant.SUCCESS); resultVo.setData(token); return JSONUtil.toJsonStr(resultVo); } return StrUtil.EMPTY; } @AutoIdempotent @PostMapping("/test/Idempotence") public String testIdempotence() { String businessResult = testService.testIdempotence(); if (StrUtil.isNotEmpty(businessResult)) { ResultVo successResult = ResultVo.getSuccessResult(businessResult); return JSONUtil.toJsonStr(successResult); } return StrUtil.EMPTY; }}
總結
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69996194/viewspace-2847920/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 如何利用限流解決遊戲陪玩app開發中的重複提交問題?遊戲APP
- 如何用分散式鎖解決陪玩平臺原始碼中的併發問題?分散式原始碼
- 解決表單重複提交的問題
- 用 Go + Redis 實現陪玩平臺原始碼中的分散式鎖GoRedis原始碼分散式
- 簡單介紹redis分散式鎖解決表單重複提交的問題Redis分散式
- 陪玩平臺原始碼中的CDN服務不可用時的解決辦法原始碼
- Springboot+Redisson自定義註解一次解決重複提交問題(含原始碼)Spring BootRedis原始碼
- 遊戲陪玩平臺原始碼,日期格式化的程式碼分析遊戲原始碼
- 遊戲陪玩原始碼的輪詢鎖,使用時遇到的問題與解決方案遊戲原始碼
- 透過 Pulsar 原始碼徹底解決重複消費問題原始碼
- SpringMVC後臺token防重複提交解決方案SpringMVC
- 測試平臺系列(82) 解決APScheduler重複執行的問題
- 解決spring security自定義filter重複執行問題SpringFilter
- Java使用Redis實現分散式鎖來防止重複提交問題JavaRedis分散式
- 8 種方案解決重複提交問題!你選擇哪一種呀?
- 關於ajax提交表單,重複提交解決方法
- 提升陪玩平臺原始碼的整體效能,MySQL資料庫如何優化?原始碼MySql資料庫優化
- 陪玩平臺原始碼中的排序演算法,插入排序的實現原始碼排序演算法
- 遊戲陪玩平臺原始碼開發,依賴收集和觸發的實現遊戲原始碼
- 前端陪玩平臺原始碼管理是否得當,可以從哪些方面考證?前端原始碼
- strust2 重複提交的問題Rust
- Shell 解決Redis Slow Log去重問題Redis
- 解決winform窗體重複建立問題ORM
- 如何使用 Redis 實現 陪玩原始碼中“附近的人” 這一功能?Redis原始碼
- 玩轉spring boot——結合redisSpring BootRedis
- Spring boot 解決跨域問題配置類Spring Boot跨域
- 使用者互動聊天,看陪玩平臺原始碼怎麼透過html實現原始碼HTML
- 陪玩平臺原始碼實現類似手機懸浮按鈕,需要如何做?原始碼
- PHP防止表單重複提交的解決方法PHP
- 快速解決mongodb出現id重複問題MongoDB
- 重複登入問題最終解決方法
- 解決angular+spring boot的跨域問題AngularSpring Boot跨域
- Spring MVC表單防重複提交SpringMVC
- 解決直播商城原始碼中,getView被重複呼叫原始碼View
- 分散式重複提交問題架構設計思路分散式架構
- JavaWeb——驗證碼功能解決表單重複提交問題(使用谷歌驗證碼jar包為例)JavaWeb谷歌JAR
- 解決生產日誌重複列印的問題
- 解決alertmanager重複傳送訊息的問題