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

物流建设网站总结制作壁纸的软件

物流建设网站总结,制作壁纸的软件,北京工程建设协会网站,加工外包网目录 一、前言二、主流实现方案介绍2.1、前端按钮做加载状态限制#xff08;必备#xff09;2.2、客户端使用唯一标识符2.3、服务端通过检测请求参数进行幂等校验#xff08;本文使用#xff09; 三、代码实现3.1、POM3.2、application.yml3.3、Redis配置类3.4、自定义注解… 目录 一、前言二、主流实现方案介绍2.1、前端按钮做加载状态限制必备2.2、客户端使用唯一标识符2.3、服务端通过检测请求参数进行幂等校验本文使用 三、代码实现3.1、POM3.2、application.yml3.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 parentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.3.12.RELEASE/versionrelativePath//parentdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-aop/artifactId/dependency!--springboot中的redis依赖--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId/dependency!-- lettuce pool 缓存连接池--dependencygroupIdorg.apache.commons/groupIdartifactIdcommons-pool2/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion1.18.12/versionoptionaltrue/optional/dependency/dependencies3.2、application.yml server:port: 8000spring:#redis配置信息redis:## Redis数据库索引默认为0database: 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: 13.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 RedisTemplateString, Object redisTemplate(RedisConnectionFactory factory) {RedisTemplateString, 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 RedisTemplateString, 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?param1niceparam2helloRepeatSubmitCheckGetMapping(/t1)public String t1(String param1,String param2){log.info(t1 param1{} param2{},param1,param2);return timeLocalDateTime.now() t1;}// curl -X POST -H token: A001 -H Content-Type: application/json -d {name:kerwin} http://127.0.0.1:8000/t2RepeatSubmitCheck(key T2,keepSeconds 5)PostMapping(/t2)public String t2(RequestBody String body){log.info(t2 body{},body);return timeLocalDateTime.now() t2;} }这里提供两个测试接口我这里会使用curl进行测试可以直接在cmd命令行执行也可以自己使用postman等工具测试。 t1 方法测试 curl -X GET -H token: A001 http://127.0.0.1:8000/t1?param1niceparam2hello这里可以看到两次调用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.pierceye.com/news/913613/

相关文章:

  • 淘宝网站建设单子好接吗朝阳区办公
  • html5网站建设平台怎么给网站添加图标
  • 中文域名网站网站制作wap页面
  • wordpress站内全文检索一个人完成网站建设
  • wordpress自定义重用结构北京seo怎么优化
  • 苏州做网站专业的公司vs2008怎么做网站
  • 效果好的徐州网站建设休闲食品网站建设策划书
  • 如何发布自己的网站wordpress 4.9.6 下载
  • 织梦网站打开慢企业咨询师资格证
  • 蓬莱网站建设哪家好广州白云网站建设
  • 网站建设得花多少钱做购物网站能否生存
  • 多语言网站 用什么cms深圳Wordpress网站
  • 常州市建设工程质量监督站网站开发公司设计管理岗位述职
  • 国外网站顶部菜单设计谷歌seo文章
  • 梅州网站开发外国自适应企业网站
  • 大型网站建设动力无限哪个公司的装饰设计公司
  • 网站建设与管理自考wordpress替换默认的编辑器
  • 企业在网站推广咸阳做网站开发公司
  • 从美洲开始做皇帝免费阅读网站wordpress嵌入优酷视频播放
  • 长沙 外贸网站建设国际足联世界排名
  • 辽宁省建设执业继续教育协会网站深圳网站制作建设服务公司
  • 个人网站备案都需要什么运营seo是什么意思
  • 局域网内部网站建设app下载苏州网络推广企业
  • 重庆美邦 网站建设保定最新消息发布
  • 东莞手机建网站旅游网站 分析
  • 网站seo优化技术入门做网站怎样实现网上支付
  • 陕西西安网站建设公司源码编程器
  • 网站开发的前端技术有哪些软件制作是什么专业
  • 淘宝网站建设目标是什么意思厦门seo计费
  • 高端网站建设注意简述网络营销的基本方法