实现方案一:
数据库创建唯一索引或者创建主键
实现方案二:
防重复token令牌,
针对客户端连续点击或者调用方的超时重试等情况,例如提交订单,此种操作就可以用 Token 的机制实现防止重复提交。简单的说就是调用方在调用接口的时候先向后端请求一个全局 ID(Token),请求的时候携带这个全局 ID 一起请求(Token 最好将其放到 Headers 中),后端需要对这个 Token 作为 Key,用户信息作为 Value 到 Redis 中进行键值内容校验,如果 Key 存在且 Value 匹配就执行删除命令,然后正常执行后面的业务逻辑。如果不存在对应的 Key 或 Value 不匹配就返回重复执行的错误信息,这样来保证幂等操作。实现如下:
ample.zhujie.util;slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.UUID;@Component
@Slf4j
public class TokenUtilService {@Autowiredprivate RedisUtils redisUtils;/*** 存入 Redis 的 Token 键的前缀*/private static final String IDEMPOTENT_TOKEN_PREFIX = "token:";/*** 创建 Token 存入 Redis,并返回该 Token* @param value 用于辅助验证的 value 值* @return 生成的 Token 串*/public String generateToken(String value) {// 实例化生成 ID 工具对象String token = UUID.randomUUID().toString();// 设置存入 Redis 的 KeyString key = IDEMPOTENT_TOKEN_PREFIX + token;// 存储 Token 到 Redis,且设置过期时间为60分钟redisUtils.set(key, value,3600l);// 返回 Tokenreturn token;}/*** 验证 Token 正确性* @param token token 字符串* @param value value 存储在Redis中的辅助验证信息* @return 验证结果*/public boolean validToken(String token,String value) {// 根据 Key 前缀拼接 KeyString key = IDEMPOTENT_TOKEN_PREFIX + token;Object o = null;synchronized (TokenUtilService.class){o = (key);if(o != null && value.String())) {// 删除该命令ve(key);log.info("验证tooken={},key={},value={} 成功",token,key,value);return true;}log.info("验证tooken={},key={},value={} 失败",token,key,value);}return false;}
}
开始测试:
ller;ample.zhujie.util.TokenUtilService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping(value = "/idempotent")
public class TokenController {private static final Logger logger = Logger(TokenController.class);@Autowiredprivate TokenUtilService tokenUtilService;/*** 拿到生成token* @return*/@RequestMapping(value = "/getToken")public String getToken() {// 正式环境可以填写用户信息String info = "userinfo";String token = ateToken(info);return token;}/*** 验证token* @param token*/@RequestMapping(value = "/testToken")public void testToken(@RequestHeader(value = "token") String token) {// 正式环境可以填写用户信息String info = "userinfo";// 根据 Token 和与用户相关的信息到 Redis 验证是否存在对应的信息boolean b = tokenUtilService.validToken(token, info);if(b) {("处理成功,走下面的逻辑");}("处理失败");}}
}
本文发布于:2024-02-02 03:30:49,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170681688341090.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |