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

学校网站建设的软件环境昆明网络营销公司哪家好

学校网站建设的软件环境,昆明网络营销公司哪家好,做文件的网站,虚拟币网站建设看本篇博客前应当先看完前面三篇#xff0c;这一篇是基于前面三篇的知识点的整合。所以很多重复的代码这里就不写出了 后台通过拦截器和redis实现防重复提交#xff0c;避免因为网络原因导致多次请求同时进入业务系统#xff0c;导致数据错乱#xff0c;也可以防止对外暴露…看本篇博客前应当先看完前面三篇这一篇是基于前面三篇的知识点的整合。所以很多重复的代码这里就不写出了 后台通过拦截器和redis实现防重复提交避免因为网络原因导致多次请求同时进入业务系统导致数据错乱也可以防止对外暴露给第三方的接口在业务尚未处理完的情况下重复调用。 首先引入fastjson dependencygroupIdcom.alibaba/groupIdartifactIdfastjson/artifactIdversion1.2.35/version /dependency新增一个幂等校验的注解 package com.xxx.util.core.annotation;import javax.ws.rs.NameBinding; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;Target({ElementType.TYPE, ElementType.METHOD}) Retention(value RetentionPolicy.RUNTIME) NameBinding public interface Idempotent {/*** 是否把body数据用来计算幂等key。如果没有登录信息请设置这个值为true。主要用于第三方接入。** return*/boolean body() default false;/*** body里的哪些字段用来计算幂等key。body()为true时才有生效。如果这个为空则计算整个body。主要用于第三方接入。br/* p* 字段命名规则br/* path: Like xpath, to find the specific value via path. Use :(Colon) to separate different key name or index.* For example:* JSON content:* {* name: One Guy,* details: [* {education_first: xx school},* {education_second: yy school},* {education_third: zz school},* ...* ],* loan: {loanNumber:1234567810,loanAmount:1000000},* }** To find the value of name, the pathname.* To find the value of education_second, the pathdetails:0:education_second.* To find the value of loanNumber , the pathloan:loanNumber.* To find the value of name and loanNumber , the pathname,loan:loanNumber.** return*/String[] bodyVals() default {};/*** idempotent lock失效时间in milliseconds。一些处理时间较长或者数据重复敏感的接口可以适当设置长点时间。** return*/int expiredTime() default 60000;}默认不去读取body中的内容去做幂等可以Idempotent(body true) 将body设为true开启 实现拦截器 package com.xxx.core.filter;import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONException; import com.alibaba.fastjson.JSONObject; import com.xxx.common.exception.FastRuntimeException; import com.xxx.core.annotation.Idempotent; import com.xxx.core.filter.request.HttpHelper; import com.xxx.core.filter.request.RequestReaderHttpServletRequestWrapper;import com.xxx.util.core.utils.SpringContextUtil; import com.xxx.util.redis.SimpleLock; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import redis.clients.jedis.JedisCluster;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Objects; import java.util.regex.Pattern;public class IdempotentFilter extends HandlerInterceptorAdapter {private final Logger logger LoggerFactory.getLogger(IdempotentFilter.class);private static final String IDEMPOTENT idempotent.info;private static final String NAMESPACE idempotent;private static final String NAMESPACE_LOCK idempotent.lock;Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {logger.info(request请求地址path[{}] uri[{}], request.getServletPath(),request.getRequestURI());HandlerMethod handlerMethod (HandlerMethod) handler;Method method handlerMethod.getMethod();Idempotent ra method.getAnnotation(Idempotent.class);if (Objects.nonNull(ra)) {logger.debug(Start doIdempotent);int liveTime getIdempotentLockExpiredTime(ra);String key generateKey(request, ra);logger.debug(Finish generateKey:[{}],key);JedisCluster jedisCluster getJedisCluster();//上分布式锁 避免相同的请求同时进入调用jedisCluster.get(key) 都为null的情况new SimpleLock(NAMESPACE_LOCK key,jedisCluster).wrap(new Runnable() {Overridepublic void run() {//判断key是否存在如存在抛出重复提交异常如果不存在 则新增if (jedisCluster.get(key) null){jedisCluster.setex(key,liveTime,true);request.setAttribute(IDEMPOTENT, key);}else {logger.debug(the key exist : {}, will be expired after {} mils if not be cleared, key, liveTime);throw new FastRuntimeException(20001,请勿重复提交);}}});}return true;}private int getIdempotentLockExpiredTime(Idempotent ra){return ra.expiredTime();}Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {}Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {try{//业务处理完成 删除redis中的keyafterIdempotent(request);}catch (Exception e){// ignore it when exceptionlogger.error(Error after Idempotent, e);}}private void afterIdempotent(HttpServletRequest request) throws IOException{Object obj request.getAttribute(IDEMPOTENT);if (obj ! null){logger.debug(Start afterIdempotent);String key obj.toString();JedisCluster jedisCluster getJedisCluster();if (StringUtils.isNotBlank(key) jedisCluster.del(key) 0){logger.debug(afterIdempotent error Prepared to delete the key:[{}] ,key);}logger.debug(End afterIdempotent);}}/*** generate key** param request* param ra* return*/public String generateKey(HttpServletRequest request, Idempotent ra){String requestURI request.getRequestURI();String requestMethod request.getMethod();StringBuilder result new StringBuilder(NAMESPACE);String token request.getHeader(H-User-Token);append(result, requestURI);append(result, requestMethod);append(result, token);appendBodyData( request, result, ra);logger.debug(The raw data to be generated key: {}, result.toString());return DigestUtils.sha1Hex(result.toString());}private void appendBodyData(HttpServletRequest request, StringBuilder src,Idempotent ra){if (Objects.nonNull(ra)){boolean shouldHashBody (boolean) ra.body();logger.debug(Found attr for body in Idempotent, the value is {}, shouldHashBody);if (shouldHashBody){String data null;try {data HttpHelper.getBodyString(new RequestReaderHttpServletRequestWrapper(request));} catch (IOException e) {logger.warn(Found attr for body in Idempotent, but the body is blank);return;}if (StringUtils.isBlank(data)){logger.warn(Found attr for body in Idempotent, but the body is blank);return;}String[] bodyVals ra.bodyVals();// bodyVals优先if (Objects.nonNull(bodyVals) bodyVals.length ! 0){logger.debug(Found attr for bodyVals in Idempotent, the value is {}, Arrays.asList(bodyVals));final String finalData data;Arrays.asList(bodyVals).stream().sorted().forEach(e - {String val getEscapedVal(finalData, e);append(src, val);});}else{append(src, data);}}}}private String getEscapedVal(String json, String path){String[] paths path.split(:);JSONObject jsonObject null;JSONArray jsonArray null;String nodeVal json;for (String fieldName : paths){if (isInteger(fieldName)){try {jsonArray JSONObject.parseArray(nodeVal);nodeVal jsonArray.get(Integer.parseInt(fieldName)).toString();} catch (JSONException e) {//如果无法转为jsonArray 则说明不是数组尝试转为jsonObject去取值logger.warn(getEscapedVal JSONObject.parseArray error nodeVal:[{}] fieldName:[{}],nodeVal,nodeVal);jsonObject JSONObject.parseObject(nodeVal);nodeVal jsonObject.get(fieldName).toString();}}else {jsonObject JSONObject.parseObject(nodeVal);nodeVal jsonObject.get(fieldName).toString();}}return nodeVal;}public static boolean isInteger(String str) {Pattern pattern Pattern.compile(^[-\\]?[\\d]*$);return pattern.matcher(str).matches();}private void append(StringBuilder src, String str){if (!StringUtils.isBlank(str)){src.append(#).append(str);}}//手动注入public JedisCluster getJedisCluster() {return SpringContextUtil.getBean(JedisCluster.class);} }新建SpringContextUtil工具类 package com.xxx.util.core.utils;import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component;Component public class SpringContextUtil implements ApplicationContextAware {private static ApplicationContext applicationContext; // Spring应用上下文环境public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {SpringContextUtil.applicationContext applicationContext;}public static ApplicationContext getApplicationContext() {return applicationContext;}SuppressWarnings(unchecked)public static T T getBean(String name) throws BeansException {return (T) applicationContext.getBean(name);}SuppressWarnings(unchecked)public static T T getBean(Class? clz) throws BeansException {return (T) applicationContext.getBean(clz);} }使用方式异常简单如果可以根据请求头的内容做区分是否重复提交则直接使用Idempotent 即可如果是提供给第三方的接口 请求头无法哦按段需要指定body则Idempotent(body true,bodyVals {“loan:loanNumber”})即可 案例代码如下 Idempotent(body true,bodyVals {loan:loanNumber})PostMapping(Urls.Test.V1_ADD)ResponseBodyApiOperation(value Urls.UserProfiles.V1_GET_USER_PROFILES_BY_PAGE_DESC)public Response add(RequestBody Test test) {return null;}
http://www.hkea.cn/news/14482108/

相关文章:

  • 商城站时刻表秦皇岛正在建设的医院
  • DMZ做网站广州网站建设策划书
  • 商城网站开发的完整流程php网站开发 招聘
  • 义乌 外贸网站 开发南京网站设南京网站设计计
  • 东莞微信网站建设信息和平网站制作
  • 微信公众号做特效的网站seo门户网站建设
  • 淘宝客网站建好了没有数据库永久免费的自助建站
  • 网站404错误来源网站怎么做万词
  • 广州商城网站建设wordpress 找不到文件路径
  • 重庆网站开发工资物流wap网站模板
  • 广 做网站蓝光电影下载城市生活网官方网站app
  • 东莞中小企业网站制作教你如何建网站视频
  • 郫县网站制作刚做外贸最好用哪个网站
  • 凡科建设网站的步骤长沙房产交易中心官网
  • 做医院网站公司电话电子商务营销策略有哪些
  • 购物网站php模板网站备案怎么换
  • 网站备案率是什么网站说明书的详细说明
  • 我做的网站怎么是危险网站没建网站 备案
  • 宁波网站建设caiyiduo最好的网站建设推广
  • 中国服装设计网站做网站常用哪种语言
  • 做网站推广对电脑有什么要求怎样上传网站程序
  • 秋长网站建设杭州网站优化咨询
  • 做视频开头的网站o2o网站建设最好公司
  • 长沙seo网站建设门户网站建设思维导图
  • 网站不设置关键词描述全网是哪些平台
  • js特效网站企业门户网站源码
  • 一起买买买网站建设张家口网站建设公司
  • 一个完整网站制作的实例排名公式
  • 网站内容通过服务器会不会被更改暖色系网站模板
  • 西安做网站微信公司app界面设计尺寸规范