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

网页设计与网站规划创意设计公司名字大全

网页设计与网站规划,创意设计公司名字大全,长安网站建设多少钱,企业建立网站主要包括那些流程目录 一、前言二、主流实现方案介绍2.1、前端按钮做加载状态限制(必备)2.2、客户端使用唯一标识符2.3、服务端通过检测请求参数进行幂等校验(本文使用) 三、代码实现3.1、POM3.2、application.yml3.3、Redis配置类3.4、自定义注解…

目录

    • 一、前言
    • 二、主流实现方案介绍
      • 2.1、前端按钮做加载状态限制(必备)
      • 2.2、客户端使用唯一标识符
      • 2.3、服务端通过检测请求参数进行幂等校验(本文使用)
    • 三、代码实现
      • 3.1、POM
      • 3.2、application.yml
      • 3.3、Redis配置类
      • 3.4、自定义注解
      • 3.5、AOP切面实现
      • 3.6、接口测试幂等效果
    • 四、总结

一、前言

      接口幂等性是指在相同的条件下,对一个接口的多次调用所产生的效果与单次调用的效果相同。简而言之,无论调用一个接口多少次,系统的状态都应该保持一致,不会因为多次调用而产生不同的结果。
      在Web开发中,特别是在RESTful API设计中,幂等性是一个重要的概念。具有幂等性的接口在面对网络不稳定、消息重复发送或者其他异常情况时更容易处理,因为它们能够保证多次相同的请求不会导致意外的副作用。

二、主流实现方案介绍

2.1、前端按钮做加载状态限制(必备)

      对于前端而言在处理下单提交按钮时一定要加上加载状态,在调用接口时如果还没有响应不允许再次点击,如果服务端没做幂等判断那么用户快速点击多次提交按钮就可能产生多比一样的订单,而且就算服务端做了幂等判断这样可以快速点击调用多次下单接口的操作也是有问题的。

2.2、客户端使用唯一标识符

      在每次发送请求时,客户端生成一个唯一的请求RequestId并将这个RequestId放在请求的头部或参数中。服务器端在接收到请求时,先验证RequestId是否已经被使用过。如果已经被使用过,说明请求重复,直接返回结果。否则,处理请求并标记该RequestId为已使用。

2.3、服务端通过检测请求参数进行幂等校验(本文使用)

      这种方式不需要前端配合,具体实现方式是获取到接口的请求参数,对请求参数进行hash或者md5,然后将这个hash之后的请求参数作为key存储在Redis中并且设置一个过期时间,每次请求时都会先判断缓存中是否存在这个key,如果存在则代表是重复提交,这种方式也是用的最多的,会结合AOP+自定义注解实现,使用分页非常灵活。

三、代码实现

3.1、POM

    <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.12.RELEASE</version><relativePath/></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><!--springboot中的redis依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- lettuce pool 缓存连接池--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version><optional>true</optional></dependency></dependencies>

3.2、application.yml

server:port: 8000spring:#redis配置信息redis:## Redis数据库索引(默认为0)database: 0## Redis服务器地址host: 127.0.0.1## Redis服务器连接端口port: 6379## Redis服务器连接密码(默认为空)password: '123456'## 连接超时时间(毫秒)timeout: 5000lettuce:pool:## 连接池最大连接数(使用负值表示没有限制)max-active: 10## 连接池最大阻塞等待时间(使用负值表示没有限制)max-wait: -1## 连接池中的最大空闲连接max-idle: 10## 连接池中的最小空闲连接min-idle: 1

3.3、Redis配置类

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;@Configuration
public class RedisConfig{@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();// 配置连接工厂template.setConnectionFactory(factory);//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om = new ObjectMapper();// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和publicom.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jacksonSeial.setObjectMapper(om);// 值采用json序列化template.setValueSerializer(jacksonSeial);//使用StringRedisSerializer来序列化和反序列化redis的key值template.setKeySerializer(new StringRedisSerializer());// 设置hash key 和value序列化模式template.setHashKeySerializer(new StringRedisSerializer());template.setHashValueSerializer(jacksonSeial);template.afterPropertiesSet();return template;}
}

3.4、自定义注解

import java.lang.annotation.*;/*** 自定义注解防止表单重复提交*/
@Target(ElementType.METHOD) // 注解只能用于方法
@Retention(RetentionPolicy.RUNTIME) // 修饰注解的生命周期
@Documented
public @interface RepeatSubmitCheck {/*** 业务标识,不传默认ALL,便于区分业务*/String key() default "ALL";/*** 防重复提交保持时间,默认1s*/int keepSeconds() default 1;
}

3.5、AOP切面实现

import com.redisscene.annotation.RepeatSubmitCheck;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;@Slf4j
@Aspect
@Component
public class RepeatSubmitAspect {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Autowiredprivate HttpServletRequest request;// 重复提交锁keyprivate String RP_LOCK_RESTS = "RP_LOCK_RESTS:";@Pointcut("@annotation(com.redisscene.annotation.RepeatSubmitCheck)")public void requestPointcut() {}@Around("requestPointcut() && @annotation(repeatSubmitCheck)")public Object interceptor(ProceedingJoinPoint pjp, RepeatSubmitCheck repeatSubmitCheck) throws Throwable {final String lockKey = RP_LOCK_RESTS + repeatSubmitCheck.key() + ":" + generateKey(pjp);// 上锁 类似setnx,并且是原子性的设置过期时间Boolean lock = redisTemplate.opsForValue().setIfAbsent(lockKey, "0", repeatSubmitCheck.keepSeconds(), TimeUnit.SECONDS);if (!lock) {// 这里也可以改为自己项目自定义的异常抛出 也可以直接return
//            throw new RuntimeException("重复提交");return "time="+ LocalDateTime.now() + " 重复提交";}return pjp.proceed();}private String generateKey(ProceedingJoinPoint pjp) {StringBuilder sb = new StringBuilder();Signature signature = pjp.getSignature();MethodSignature methodSignature = (MethodSignature) signature;Method method = methodSignature.getMethod();sb.append(pjp.getTarget().getClass().getName())//类名.append(method.getName());//方法名for (Object o : pjp.getArgs()) {if (o != null) {sb.append(o.toString());//参数}}String token = request.getHeader("token") == null ? "" : request.getHeader("token");sb.append(token);//tokenlog.info("RP_LOCK generateKey() called with parameters => 【sb = {}】", sb);return DigestUtils.md5DigestAsHex(sb.toString().getBytes(Charset.defaultCharset()));}
}

3.6、接口测试幂等效果

import com.redisscene.annotation.RepeatSubmitCheck;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;@Slf4j
@RestController
public class RepeatSubmitTestControlller {// curl -X GET -H "token: A001" "http://127.0.0.1:8000/t1?param1=nice&param2=hello"@RepeatSubmitCheck@GetMapping("/t1")public String t1(String param1,String param2){log.info("t1 param1={} param2={}",param1,param2);return "time="+LocalDateTime.now() + " t1";}// curl -X POST -H "token: A001" -H "Content-Type: application/json" -d "{'name':'kerwin'}" "http://127.0.0.1:8000/t2"@RepeatSubmitCheck(key = "T2",keepSeconds = 5)@PostMapping("/t2")public String t2(@RequestBody String body){log.info("t2 body={}",body);return "time="+LocalDateTime.now() + " t2";}
}

这里提供两个测试接口,我这里会使用curl进行测试可以直接在cmd命令行执行,也可以自己使用postman等工具测试。

  • t1 方法测试

    curl -X GET -H "token: A001" "http://127.0.0.1:8000/t1?param1=nice&param2=hello"
    

    在这里插入图片描述
    这里可以看到两次调用t1接口时如果在1s内再次调用会出现重复提交,过了1s后可以再次调用成功。

  • t2 方法测试

    curl -X POST -H "token: A001" -H "Content-Type: application/json" -d "{'name':'kerwin'}" "http://127.0.0.1:8000/t2"
    

    在这里插入图片描述
    这里可以看到两次调用t2接口时如果在5s内再次调用会出现重复提交,过了5s后可以再次调用成功。

四、总结

      通过Redis + AOP + 自定义注解实现接口幂等性灵活性很高,只对需要进行幂等判断的接口加上注解即可,本文只是做了核心逻辑实现,对于实际项目中使用只要进行简单改造即可。

http://www.sczhlp.com/news/80395/

相关文章:

  • 搭建网站大概需要多少钱手机自适应的网站怎么做
  • 常州建站费用网站源码分享平台
  • 网站文章不收录网页制作动态模板
  • php学校网站建设wordpress 免密码破解
  • 园区做网站的好处wordpress+推荐插件
  • 游戏平台网站制作wordpress的主题是什么意思
  • 可信网站认证不做做竞价的网站有利于优化吗
  • 平利县城乡建设局网站网络类黄页
  • JS之变更URL的传参但不刷新页面
  • 朋友圈刷屏的「AI手办」原来这么做!免费教程,1分钟让你的照片“活”起来!
  • 国产芯片处理板卡:7-基于国产化FT-M6678+JFM7K325T的6U CPCI信号处理卡
  • 2025本土平台如何重塑企业级代码托管市场格局
  • 设计模式-装饰器
  • 网站首页快照更新快最好的淘宝网站建设
  • 机电网站模板wordpress登录样式
  • 两人做性视频网站个人网站有哪些
  • 网站建设方案应急处置html5搭建手机网站
  • 高端大气网站欣赏定制摄影app和摄影网站的区别
  • 南阳做网站价格西安网站建设排名
  • 企业网站备案 优帮云wordpress输出
  • 广西建设工程协会网站查询系统网站标题作弊
  • 网站建设外链怎么改wordpress的html
  • 附近做app的公司中山市企业网站seo哪里好
  • 南昌做网站软件重庆建设工程安全网
  • 嘉兴备案网站wordpress 文章位置
  • 计算机网站建设实验总结软件app开发培训
  • 镇江教育云网站建设怎么做一个网站 免费
  • 北京专业制作网站公司广州网站推广费用
  • 企业应该如何进行网站建设建筑设计公司招聘
  • 护肤品网站建设前的行业分析wordpress安装幻灯片插件