赞
踩
select version from xxx where id = xxx;
update xxx set xxx=xxx where xxx=xxx and version=xxx;
start;
select * from xxx where xxx for update;
update xxx
commit;
@Component
public class RedisCache {
@Autowired
RedisTemplate 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) {
ValueOperations<String,T> valueOperations = redisTemplate.opsForValue();
return valueOperations.get(key);
}
}
详细步骤见代码注释:
@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";
@Autowired
RedisCache redisCache;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//所以的controller方法都会被封装成HandlerMethod
if (handler instanceof HandlerMethod){
//分析注解
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
RepeatSubmit repeatSubmit = method.getAnnotation(RepeatSubmit.class);
//如果注解存在&&请求重复
if (repeatSubmit != null){
if (isRepeatSubmit(request,repeatSubmit)){
//拦截返回错误信息
HashMap<String, Object> map = new HashMap<>();
map.put("status",500);
map.put("message",repeatSubmit.message());
response.setContentType("application/json;charset=utf-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();
}
}
//包装参数和当前时间
HashMap<String, Object> nowDataMap = new HashMap<>();
nowDataMap.put(REPEAT_PARAMS,nowParams);
nowDataMap.put(REPEAT_TIME,System.currentTimeMillis());
//获取请求信息,组装key
String requestURI = request.getRequestURI();
String header = request.getHeader(HEADER);
String cacheKey = REPEAT_SUBMIT_KEY + requestURI + header.replace("Bearer ","");
//根据key查找redis
Object cacheObject = redisCache.getCacheObject(cacheKey);
if (cacheObject != null){
//这里说明不是第一次,判断是否为重复请求(参数、时间)
Map<String, Object> cacheMap = (Map<String, 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(Map<String, Object> cacheMap, HashMap<String, 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(Map<String, Object> cacheMap, HashMap<String, Object> nowDataMap) {
String cacheParams = (String) cacheMap.get(REPEAT_PARAMS);
String nowParams = (String) nowDataMap.get(REPEAT_PARAMS);
return nowParams.equals(cacheParams);
}
}
到这里,一个自定义注解方式的防重就实现完了,点击跳转源码仓库地址。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。