项目场景:
项目场景:项目中部分接口需要避免用户重复操作
实现描述
考虑使用接口+参数作为一个操作锁,操作前获取锁,操作后释放锁。使用Function,定义方法作为入参。
APP 中接收数据代码:
工具类:
/**
* @Author: zhx
* @Date: 2022/6/30 16:27
* @Description: IdempotenceTemplate
* @Version 1.0.0
*/
@Component
@Slf4j
public class IdempotenceTemplate {
@Value("${spring.application.name}")
private String appName;
public <T, R> R execute(Function<T, R> function, T param, String lockKey, String lockFailMsg) {
if (StringUtils.isBlank(lockKey)) {
throw new ServiceBizException("当前操作不合法,lockKey为空");
}
String appLockKey = appName + ":" + lockKey;
boolean lock = false;
try {
lock =RedisUtil.tryLock(appLockKey, 0, 5);
if (lock) {
R result = function.apply(param);
return result;
} else {
throw new ServiceBizException(lockFailMsg);
}
} finally {
if (lock) {
RedisUtil.unlock(appLockKey);
}
}
}
}
使用类:
/**
* @Author: zhx
* @Date: 2022/6/30 16:25
* @Description: WorksUserServiceImpl
* @Version 1.0.0
*/
@Service
public class WorksUserServiceImpl implements IWorksUserService {
@Autowired
private IdempotenceTemplate idempotenceTemplate;
@Override
public String save(String name) {
String lockKey = "IWorksUserService:save:" + name;
return idempotenceTemplate.execute(this::saveHandle,name, lockKey,"添加用户过于频繁请稍后重试");
}
private String saveHandle(String name) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if ("xiaoming".equals(name)) {
throw new RuntimeException("当前名称已经存在");
}
System.out.println("saving");
return "save success";
}
}