在我们的业务系统中,可能因为某种原因,用户会不断的点击表单提交按钮,为了较少对系统的 无意义访问、暴力提交
以及用户体验,我们利用redis的过期时间简单的实现了一种Redis锁
当用户提交表单的时候,我们通过对表单数据以及用户唯一标识例如userNo
进行加密,当做我们缓存的唯一key
import java.security.MessageDigest;
public static String genLockKey(String formData, String userNo){
StringBuilder builder = new StringBuilder();
MessageDigest md;
try {
md = MessageDigest.getInstance("MD5");
StringBuffer lockKey = new StringBuffer("");
lockKey.append(userNo);
lockKey.append(formData);
md.update( lockKey.toString().getBytes() );
for ( byte b : md.digest() ){
builder.append( Integer.toHexString( (b >> 4) & 0xf ) );
builder.append( Integer.toHexString( b & 0xf ) );
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return builder.toString();
}
然后我们判断判断redis 中是否缓存了这个key,如果有缓存,则提醒用户不要重复提交,否则我们做redis缓存
String lockKey = CryptUtils.genLockKey(formData, user.getNo());
if (RedisLock.isLock(lockKey)) {
// 不能重复提交
logger.error("提交出错 - 不能重复提交报销单!");
returnVo.setMsg("温馨提示 - 不能重复提交报销单!");
return JsonUtils.toJson(returnVo);
}
RedisLock.lock(lockKey, 2);
//.....剩余的业务逻辑
接下来上我们RedisLock
的实现
import java.util.concurrent.TimeUnit;
import org.springframework.data.redis.core.RedisTemplate;
import com.ys.tools.common.SpringContextHolder;
public class RedisLock {
/**
* 加锁
*
* @param key
* @param minutes
* 失效的分钟数
*/
public static void lock(String key, int seconds) {
getRedisTemplate().opsForValue().set(key, key, seconds,
TimeUnit.SECONDS);
}
/**
* 判断是否还在锁定状态
*
* @param key
* @return true 锁定 false 已经解除锁定
*/
public static boolean isLock(String key) {
Long flag = getRedisTemplate().getExpire(key);
return flag > 0;
}
/**
* 解锁
* @param key
*/
public static void unLock(String key) {
getRedisTemplate().delete(key);
}
private static RedisTemplate<String, String> getRedisTemplate() {
return SpringContextHolder.getBean("redisTemplate");
}
}
其实业务逻辑很简单,思想也很简单。
对表单数据进行缓存并设置过期时间,如果过期时间内点击按钮 缓存存在 ,则进行页面提示,如果不存在缓存则进行业务处理以及增加缓存防止重复点击 So Easy~~