当前位置: 首页 > news >正文

天津建设厅 注册中心网站首页图片制作在线制作免费

天津建设厅 注册中心网站首页,图片制作在线制作免费,怎么做网站海报轮播图,每天三分钟新闻天下事防止表单重复提交的几种方式#xff0c;演示一个自定义注解方式的实现 一、防止表单重复提交的几种方式方式一#xff1a;Token 机制方式二#xff1a;去重表#xff08;主要是利用 MySQL 的唯一索引机制来实现的#xff09;方式三#xff1a;Redis 的 setnx方式四#… 防止表单重复提交的几种方式演示一个自定义注解方式的实现 一、防止表单重复提交的几种方式方式一Token 机制方式二去重表主要是利用 MySQL 的唯一索引机制来实现的方式三Redis 的 setnx方式四设置状态字段方式五锁机制方式六自定义注解 二、自定义注解方式的实现1. 准备工作解决请求参数为JSON时采用IO流读取只能请求一次的问题2. 封住一个RedisCache简化使用3. 完善RepeatSubmitInterceptor拦截器解析注解判断是否重复提交4. 测试注解 一、防止表单重复提交的几种方式 方式一Token 机制 客户端请求服务端获取一个 token每一次请求都获取到一个全新的 token token 会有一个超时时间将 token 存入 redis 中然后将 token 返回给客户端。客户端将来携带刚刚返回的 token 去请求一个接口。服务端收到请求后分为两种情况 如果 token 在 redis 中直接删除该 token然后继续处理业务请求。如果 token 不在 redis 中说明 token 过期或者当前业务已经执行过了那么此时就不执行业务逻辑。 特点实现简单但是多了一个获取 token 的过程。 方式二去重表主要是利用 MySQL 的唯一索引机制来实现的 客户端请求服务端服务端将这次的请求信息请求地址、参数等存入到一个 MySQL 去重表中这个去重表要根据这次请求的某个特殊字段建立唯一索引或者主键索引。判断是否插入成功 成功继续完成业务功能。失败表示业务已经执行过了这次就不执行业务了。 问题MySQL 的容错性会影响业务、高并发环境可能效率低。 方式三Redis 的 setnx 客户端请求服务端服务端将能代表本次请求唯一性的业务字段通过 setnx 的方式存入 redis并设置超时时间。判断 setnx 是否成功 成功继续处理业务。失败表示业务已经执行过了。 方式四设置状态字段 给要处理的数据设置一个状态字段。 方式五锁机制 乐观锁数据库中增加版本号字段每次更新都根据版本号来判断。更新之前先去查询要更新记录的版本号第二步更新的时候将版本号也作为查询条件。 select version from xxx where id xxx; update xxx set xxxxxx where xxxxxx and versionxxx;悲观锁 假设每一次拿数据都会被修改所以直接上排他锁就行了。 start; select * from xxx where xxx for update; update xxx commit;方式六自定义注解 将当前请求的地址参数缓存起来下次再来一个请求时去判断和缓存中的请求是否完全一样一样的话并且小于规定的时间间隔则认为是重复提交。 二、自定义注解方式的实现 1. 准备工作解决请求参数为JSON时采用IO流读取只能请求一次的问题 我们现在要使用拦截器拦截请求缓存的地址参数等信息但是如果请求参数为JSON拦截器拦截之后接口就无法再一次获取了所以先要解决这个问题。前边文章已经写过点击跳转如何解决请求参数为JSON时采用IO流读取只能请求一次的问题 2. 封住一个RedisCache简化使用 Component public class RedisCache {AutowiredRedisTemplate redisTemplate;public T void setCacheObject(final String key, final T value, Integer timeout, final TimeUnit timeUnit) {redisTemplate.opsForValue().set(key, value, timeout, timeUnit);}public T T getCacheObject(final String key) {ValueOperationsString,T valueOperations redisTemplate.opsForValue();return valueOperations.get(key);} }3. 完善RepeatSubmitInterceptor拦截器解析注解判断是否重复提交 详细步骤见代码注释 Component public class RepeatSubmitInterceptor implements HandlerInterceptor {public static final String REPEAT_PARAMS repeat_params;public static final String REPEAT_TIME repeat_time;public static final String REPEAT_SUBMIT_KEY repeat_submit_key;public static final String HEADER Authorization;AutowiredRedisCache redisCache;Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//所以的controller方法都会被封装成HandlerMethodif (handler instanceof HandlerMethod){//分析注解HandlerMethod handlerMethod (HandlerMethod) handler;Method method handlerMethod.getMethod();RepeatSubmit repeatSubmit method.getAnnotation(RepeatSubmit.class);//如果注解存在请求重复if (repeatSubmit ! null){if (isRepeatSubmit(request,repeatSubmit)){//拦截返回错误信息HashMapString, Object map new HashMap();map.put(status,500);map.put(message,repeatSubmit.message());response.setContentType(application/json;charsetutf-8);response.getWriter().write(new ObjectMapper().writeValueAsString(map));return false;}}}return true;}private boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit repeatSubmit) {//获取请求参数字符串String nowParams ;//RepeatableReadRequestWrapper 说明是JSON格式if (request instanceof RepeatableReadRequestWrapper){try {nowParams ((RepeatableReadRequestWrapper) request).getReader().readLine();} catch (IOException e) {e.printStackTrace();}}//否则说明参数是key-value格式if (StringUtils.isEmpty(nowParams)){try {nowParams new ObjectMapper().writeValueAsString(request.getParameterMap());} catch (JsonProcessingException e) {e.printStackTrace();}}//包装参数和当前时间HashMapString, Object nowDataMap new HashMap();nowDataMap.put(REPEAT_PARAMS,nowParams);nowDataMap.put(REPEAT_TIME,System.currentTimeMillis());//获取请求信息组装keyString requestURI request.getRequestURI();String header request.getHeader(HEADER);String cacheKey REPEAT_SUBMIT_KEY requestURI header.replace(Bearer ,);//根据key查找redisObject cacheObject redisCache.getCacheObject(cacheKey);if (cacheObject ! null){//这里说明不是第一次判断是否为重复请求参数、时间MapString, Object cacheMap (MapString, Object) cacheObject;if (compareParams(cacheMap, nowDataMap) compareTime(cacheMap, nowDataMap, repeatSubmit.interval())){return true;}}//到这里说明是第一次访问redisCache.setCacheObject(cacheKey,nowDataMap,repeatSubmit.interval(), TimeUnit.MILLISECONDS);return false;}private boolean compareTime(MapString, Object cacheMap, HashMapString, Object nowDataMap, int interval) {Long nowTime (Long) nowDataMap.get(REPEAT_TIME);Long cacheTime (Long) cacheMap.get(REPEAT_TIME);if (nowTime - cacheTime interval) {return true;}return false;}private boolean compareParams(MapString, Object cacheMap, HashMapString, Object nowDataMap) {String cacheParams (String) cacheMap.get(REPEAT_PARAMS);String nowParams (String) nowDataMap.get(REPEAT_PARAMS);return nowParams.equals(cacheParams);}}4. 测试注解 到这里一个自定义注解方式的防重就实现完了点击跳转源码仓库地址。
http://www.hkea.cn/news/14402048/

相关文章:

  • 沈阳网站备案拼多多网站策划书
  • 建自己的网站腾讯企业邮箱官网登录入口
  • 深圳开发网站的公司哪家好广告设计怎么接单
  • 网站名称需要注册吗js获取网站域名
  • 如何做自己的网站百度推广简单建优化网站无需技术
  • 酷站网站开发需要的工具
  • asp网站 攻击公司怎么开网站
  • iis网站ip律所网站建设方案书怎么写
  • 花生壳 建设网站设计电子商务网站
  • .net 网站地图优化大师官网下载
  • 网站漂浮物怎么做wordpress头像自定义
  • 网站建设的技术电子商务网站租用服务器费用
  • 网站上传程序流程wordpress减肥主题
  • html5手机网站源码下载苏州百度推广服务中心
  • 供求网站建设企业网站建设与管理简述
  • 个人营销网站网站建设常识
  • 免费dedecms企业网站模板微网站建设找哪家
  • dw网站建设基本流程小企业怎么建网站平台
  • 网站抽奖模板自己做的网站怎么放上网
  • 农业网站建设方案上海网站建设优化
  • wordpress调用网站最新文章wordpress 网站 上传
  • 建站行业都扁平化设计网站开发 工作量
  • 把手机网站做成app产品网站别人是如何做优化的
  • 建立一个做笔记的网站网站流量利用
  • 建设网站及域名费用wordpress qq空间
  • 大气的企业网站设计WordPress说说心情
  • 丽水市莲都建设分局网站东莞证券
  • m开头的手机网站怎么做营销平台是什么意思
  • 网站换域名要怎么做怎么在百度建设一个网站
  • 环保材料 技术支持 东莞网站建设上海专业建设网站制作