生成令牌接口
public class TokenUtils { private static Map<String, Object> tokenMap = new ConcurrentHashMap<String, Object>(); // 获取token public static synchronized String getToken() { // 1.生成令牌 String token = "token-" + System.currentTimeMillis(); // 2.存入tokenMap tokenMap.put(token, token); return token; } // 验证token,并且删除对应的token public static Boolean exisToken(String token) { // 1.从集合中获取token Object result = tokenMap.get(token); if (result == null) { return false; } // 2.删除对应的token tokenMap.remove(token); return true; } }接口中获取令牌验证
@RestController public class OrderController { @Autowired private OrderMapper orderMapper; // 获取Token @RequestMapping("/getToken") public String getToken() { return TokenUtils.getToken(); } // 验证Token @RequestMapping(value = "/addOrder", produces = "application/json; charset=utf-8") public String addOrder(@RequestBody OrderEntity orderEntity, HttpServletRequest request) { String token = request.getHeader("token"); if (StringUtils.isEmpty(token)) { return "参数错误!"; } if (!TokenUtils.exisToken(token)) { return "请勿重复提交!"; } int result = orderMapper.addOrder(orderEntity); return result > 0 ? "添加成功" : "添加失败" + ""; } }BaseRedisService封装Redis
@Component public class BaseRedisService { @Autowired private StringRedisTemplate stringRedisTemplate; public void setString(String key, Object data, Long timeout) { if (data instanceof String) { String value = (String) data; stringRedisTemplate.opsForValue().set(key, value); } if (timeout != null) { stringRedisTemplate.expire(key, timeout, TimeUnit.SECONDS); } } public Object getString(String key) { return stringRedisTemplate.opsForValue().get(key); } public void delKey(String key) { stringRedisTemplate.delete(key); } }RedisTokenUtils工具类
@Component public class RedisTokenUtils { private long timeout = 60 * 60; @Autowired private BaseRedisService baseRedisService; // 将token存入在redis public String getToken() { String token = "token" + System.currentTimeMillis(); baseRedisService.setString(token, token, timeout); return token; } public boolean findToken(String tokenKey) { String token = (String) baseRedisService.getString(tokenKey); if (StringUtils.isEmpty(token)) { return false; } // token 获取成功后 删除对应tokenMapstoken baseRedisService.delKey(token); return true; } }自定义Api幂等注解和切面
@Target(value = ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface ExtApiIdempotent { String value(); } @Aspect @Component public class ExtApiAopIdempotent { @Autowired private RedisTokenUtils redisTokenUtils; @Pointcut("execution(public * com.hao.controller.*.*(..))") public void rlAop() { } @Around("rlAop()") public Object doBefore(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature(); ExtApiIdempotent extApiIdempotent = signature.getMethod().getDeclaredAnnotation(ExtApiIdempotent.class); if (extApiIdempotent == null) { // 直接执行程序 Object proceed = proceedingJoinPoint.proceed(); return proceed; } // 代码步骤: // 1.获取令牌 存放在请求头中 HttpServletRequest request = getRequest(); String token = request.getHeader("token"); if (StringUtils.isEmpty(token)) { response("参数错误!"); return null; } // 2.判断令牌是否在缓存中有对应的令牌 // 3.如何缓存没有该令牌的话,直接报错(请勿重复提交) // 4.如何缓存有该令牌的话,直接执行该业务逻辑 // 5.执行完业务逻辑之后,直接删除该令牌。 if (!redisTokenUtils.findToken(token)) { response("请勿重复提交!"); return null; } Object proceed = proceedingJoinPoint.proceed(); return proceed; } public HttpServletRequest getRequest() { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); return request; } public void response(String msg) throws IOException { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletResponse response = attributes.getResponse(); response.setHeader("Content-type", "text/html;charset=UTF-8"); PrintWriter writer = response.getWriter(); try { writer.println(msg); } catch (Exception e) { } finally { writer.close(); } } }