当前位置:   article > 正文

redis防止表单重复提交

redis防止表单重复提交

1. 对于前后端传递token验证的方式,每次都需要页面加载才能在后端存放token,这样会导致用户在第一次提交表单失败后就无法提交成功,需要刷新页面。 
2. 利用session去给前后端的token存放获取,这对于APP来说不协调,适合用redis。

使用哪种方法要根据自己项目去考虑,比如单纯做网页的用session也不错。 我这里后台是提供给微信端和APP端,所以使用了第四种方法:使用Redis和AOP自定义切入实现 

 

参考文章:

https://blog.csdn.net/wangdengyang/article/details/81095734

https://www.cnblogs.com/huanghuizhou/p/9153837.html

实现原理:

  1. 自定义防止重复提交标记(@AvoidRepeatableCommit)。
  2. 对需要防止重复提交的Congtroller里的mapping方法加上该注解。
  3. 新增Aspect切入点,为@AvoidRepeatableCommit加入切入点。
  4. 每次提交表单时,Aspect都会保存当前key到reids(须设置过期时间)。
  5. 重复提交时Aspect会判断当前redis是否有该key,若有则拦截。

自定义标签

  1. import java.lang.annotation.ElementType;
  2. import java.lang.annotation.Retention;
  3. import java.lang.annotation.RetentionPolicy;
  4. import java.lang.annotation.Target;
  5. /**
  6. * 避免重复提交
  7. *
  8. * @author hhz
  9. * @version
  10. * @since
  11. */
  12. @Target(ElementType.METHOD)
  13. @Retention(RetentionPolicy.RUNTIME)
  14. public @interface Resubmit {
  15. /**
  16. * 指定时间内不可重复提交,单位秒
  17. *
  18. * @return
  19. */
  20. long timeout() default 3;
  21. }

自定义切入点Aspect

  1. package com.panda.sdk.aspect;
  2. import org.apache.catalina.connector.RequestFacade;
  3. import org.apache.poi.ss.formula.functions.T;
  4. import org.aspectj.lang.ProceedingJoinPoint;
  5. import org.aspectj.lang.annotation.Around;
  6. import org.aspectj.lang.annotation.Aspect;
  7. import org.aspectj.lang.reflect.MethodSignature;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.context.annotation.EnableAspectJAutoProxy;
  10. import org.springframework.core.annotation.Order;
  11. import org.springframework.stereotype.Component;
  12. import org.springframework.web.context.request.RequestContextHolder;
  13. import org.springframework.web.context.request.ServletRequestAttributes;
  14. import com.alibaba.fastjson.JSONObject;
  15. import com.panda.sdk.annotation.Resubmit;
  16. import com.panda.sdk.constant.ErrorCode;
  17. import com.panda.sdk.constant.RedisKeyEnum;
  18. import com.panda.sdk.response.Result;
  19. import com.panda.sdk.util.RedisUtils;
  20. import com.panda.sdk.util.RequestUtils;
  21. import javax.servlet.http.HttpServletRequest;
  22. import java.lang.reflect.Method;
  23. /**
  24. * 重复提交aop
  25. *
  26. * @author
  27. * @date
  28. */
  29. @Aspect
  30. @Order
  31. @Component
  32. @EnableAspectJAutoProxy(exposeProxy = true)
  33. public class ResubmitAspect {
  34. @Autowired
  35. HttpServletRequest request; // 这里可以获取到request
  36. @Autowired
  37. RedisUtils redisUtils;
  38. private static final String SPLIT = "#";
  39. /**
  40. * @param point
  41. */
  42. @SuppressWarnings("unchecked")
  43. @Around("@annotation(com.panda.sdk.annotation.Resubmit)")
  44. public Result<T> around(ProceedingJoinPoint point) throws Throwable {
  45. HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
  46. .getRequest();
  47. MethodSignature methodSignature = (org.aspectj.lang.reflect.MethodSignature) point.getSignature();
  48. Method method = methodSignature.getMethod();
  49. String accesstoken = request.getHeader("access-token");
  50. String userAgent = request.getHeader("User-Agent");
  51. String ip = RequestUtils.getIpAddr(request);
  52. String uri = request.getRequestURI();
  53. String methodName = request.getMethod();
  54. String className = method.getDeclaringClass().getName();
  55. String name = method.getName();
  56. StringBuilder sb = new StringBuilder();
  57. sb.append(className)
  58. .append(SPLIT).append(uri)
  59. .append(SPLIT).append(ip)
  60. .append(SPLIT).append(methodName)
  61. .append(SPLIT).append(name)
  62. .append(SPLIT).append(accesstoken)
  63. .append(SPLIT).append(userAgent);
  64. // 请求参数
  65. if (point.getArgs() != null) {
  66. for (Object obj : point.getArgs()) {
  67. if (obj instanceof RequestFacade) {
  68. continue;
  69. }
  70. sb.append(SPLIT).append(JSONObject.toJSONString(obj));
  71. }
  72. }
  73. String key = String.format(RedisKeyEnum.RESUBMIT, sb.toString().hashCode());
  74. Resubmit resubmit = method.getAnnotation(Resubmit.class);
  75. int timeout = resubmit.timeout();
  76. if (timeout < 0) {
  77. timeout = 3;
  78. }
  79. long count = redisUtils.incrBy(key, 1);
  80. // 设置有效期
  81. if (count == 1) {
  82. redisUtils.expire(key, timeout);
  83. Object object = point.proceed();
  84. return (Result<T>) object;
  85. } else {
  86. return Result.fail(ErrorCode.RESUBMIT);
  87. }
  88. }
  89. }

测试使用案例代码:

  1. @Resubmit
  2. @PostMapping
  3. public Result<ClassSchVO> insertSelective(@RequestBody ClassSchVO vo)
  4. throws BizException, ParseException, IOException {
  5. int ret = classSchService.insertSelective(vo);
  6. return ret == 1 ? Result.success() : Result.fail("添加失败");
  7. }

 

涉及到的获得ip工具类:

  1. public class HttpUtils {
  2. /*
  3. * 通过request得到IP地址 参数: X-Forwarded-For:Squid 服务代理 Proxy-Client-IP:apache 服务代理
  4. * WL-Proxy-Client-IP:weblogic 服务代理 HTTP_CLIENT_IP:有些代理服务器 X-Real-IP:nginx服务代理
  5. */
  6. public static String getIPAddress(HttpServletRequest request) {
  7. String ip = null;
  8. // X-Forwarded-For:Squid 服务代理
  9. String ipAddresses = request.getHeader("X-Forwarded-For");
  10. if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
  11. // Proxy-Client-IP:apache 服务代理
  12. ipAddresses = request.getHeader("Proxy-Client-IP");
  13. }
  14. if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
  15. // WL-Proxy-Client-IP:weblogic 服务代理
  16. ipAddresses = request.getHeader("WL-Proxy-Client-IP");
  17. }
  18. if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
  19. // HTTP_CLIENT_IP:有些代理服务器
  20. ipAddresses = request.getHeader("HTTP_CLIENT_IP");
  21. }
  22. if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
  23. // X-Real-IP:nginx服务代理
  24. ipAddresses = request.getHeader("X-Real-IP");
  25. }
  26. // 有些网络通过多层代理,那么获取到的ip就会有多个,一般都是通过逗号(,)分割开来,并且第一个ip为客户端的真实IP
  27. if (ipAddresses != null && ipAddresses.length() != 0) {
  28. ip = ipAddresses.split(",")[0];
  29. }
  30. // 还是不能获取到,最后再通过request.getRemoteAddr();获取
  31. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
  32. ip = request.getRemoteAddr();
  33. }
  34. return ip;
  35. }
  36. }

涉及到的redis工具类

  1. package com.ac.sdk.util;
  2. import java.util.Collection;
  3. import java.util.Date;
  4. import java.util.List;
  5. import java.util.Map;
  6. import java.util.Set;
  7. import java.util.concurrent.TimeUnit;
  8. import javax.annotation.Resource;
  9. import org.springframework.data.redis.core.RedisTemplate;
  10. import org.springframework.data.redis.serializer.RedisSerializer;
  11. import org.springframework.stereotype.Service;
  12. /**
  13. * redis工具类,方法定义:http://doc.redisfans.com
  14. *
  15. * @author caiLinFeng
  16. * @date 2018年1月30日
  17. */
  18. @Service
  19. public class RedisUtils {
  20. @Resource
  21. private RedisTemplate<String, Object> redisTemplate;
  22. /**
  23. * 从列表左边添加
  24. *
  25. * @param k
  26. * @param v
  27. */
  28. public void lPush(String k, Object v) {
  29. redisTemplate.opsForList().leftPush(k, v);
  30. }
  31. /**
  32. * 列表获取
  33. *
  34. * @param k
  35. * @param l
  36. * @param l1
  37. * @return
  38. */
  39. public List<Object> lRange(String k, long l, long l1) {
  40. return redisTemplate.opsForList().range(k, l, l1);
  41. }
  42. /**
  43. * 保持链表只有N位
  44. *
  45. * @param k
  46. * @param N
  47. */
  48. public void lTrim(String k, int N) {
  49. redisTemplate.opsForList().trim(k, 0, N - 1);
  50. }
  51. /**
  52. * 删除key
  53. *
  54. * @author caiLinFeng
  55. * @date 2018年1月30日
  56. *
  57. */
  58. public void del(String key) {
  59. redisTemplate.delete(key);
  60. }
  61. /**
  62. * 批量删除key
  63. *
  64. * @author caiLinFeng
  65. * @date 2018年1月30日
  66. */
  67. public void del(Collection<String> keys) {
  68. redisTemplate.delete(keys);
  69. }
  70. /**
  71. * 检查给定 key是否存在
  72. *
  73. * @author caiLinFeng
  74. * @date 2018年1月30日
  75. */
  76. public Boolean exists(String key) {
  77. return redisTemplate.hasKey(key);
  78. }
  79. /**
  80. * 设置过期时间
  81. *
  82. * @author caiLinFeng
  83. * @date 2018年1月30日
  84. * @param timeout
  85. * 单位秒
  86. *
  87. *
  88. */
  89. public Boolean expire(String key, long timeout) {
  90. return redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
  91. }
  92. /**
  93. * 设置过期时间
  94. *
  95. * @author caiLinFeng
  96. * @date 2018年1月30日
  97. * @param
  98. */
  99. public Boolean expire(String key, long timeout, TimeUnit timeUtit) {
  100. return redisTemplate.expire(key, timeout, timeUtit);
  101. }
  102. /**
  103. * 设置过期时间
  104. *
  105. * @author caiLinFeng
  106. * @date 2018年1月30日
  107. * @param
  108. */
  109. public Boolean expireAt(String key, Date date) {
  110. return redisTemplate.expireAt(key, date);
  111. }
  112. /**
  113. * 返回给定 key 的剩余生存时间,以秒为单位
  114. *
  115. * @author caiLinFeng
  116. * @date 2018年1月30日
  117. * @param
  118. */
  119. public Long ttl(String key) {
  120. return redisTemplate.getExpire(key);
  121. }
  122. /******************* String **********************/
  123. /**
  124. * 将 key所储存的值加上增量 delta,返回增加后的值
  125. *
  126. * @author caiLinFeng
  127. * @date 2018年1月30日
  128. * @param
  129. */
  130. public Long incrBy(String key, long delta) {
  131. return redisTemplate.opsForValue().increment(key, delta);
  132. }
  133. /**
  134. * 将字符串值 value 关联到 key
  135. *
  136. * @author caiLinFeng
  137. * @date 2018年1月30日
  138. * @param
  139. */
  140. public void set(String key, Object value) {
  141. redisTemplate.opsForValue().set(key, value);
  142. }
  143. /**
  144. * 将字符串值 value 关联到 key
  145. *
  146. * @author caiLinFeng
  147. * @date 2018年1月30日
  148. * @param
  149. */
  150. public void setex(String key, Object value, long timeout, TimeUnit unit) {
  151. redisTemplate.opsForValue().set(key, value, timeout, unit);
  152. }
  153. /**
  154. * 将 key的值设为 value ,当且仅当 key 不存在
  155. *
  156. * @author caiLinFeng
  157. * @date 2018年1月30日
  158. * @param
  159. */
  160. public Boolean setnx(String key, Object value) {
  161. return redisTemplate.opsForValue().setIfAbsent(key, value);
  162. }
  163. /**
  164. * 关联到 key
  165. *
  166. * @author caiLinFeng
  167. * @date 2018年1月30日
  168. * @param
  169. */
  170. public void mset(Map<String, Object> map) {
  171. redisTemplate.opsForValue().multiSet(map);
  172. }
  173. /**
  174. * 返回 key所关联的字符串
  175. *
  176. * @author caiLinFeng
  177. * @date 2018年1月30日
  178. * @param
  179. */
  180. public Object get(String key) {
  181. return redisTemplate.opsForValue().get(key);
  182. }
  183. /******************* Hash **********************/
  184. /**
  185. * 删除哈希表 key中的一个或多个指定域,不存在的域将被忽略
  186. *
  187. * @author caiLinFeng
  188. * @date 2018年1月30日
  189. * @param
  190. */
  191. public Long hdel(String key, Object... hashKeys) {
  192. return redisTemplate.opsForHash().delete(key, hashKeys);
  193. }
  194. /**
  195. * 将哈希表 key中的域 field 的值设为 value
  196. *
  197. * @author caiLinFeng
  198. * @Description
  199. * @date 2018年1月30日
  200. * @param
  201. */
  202. public void hset(String key, String hashKey, Object hashValue) {
  203. redisTemplate.opsForHash().put(key, hashKey, hashValue);
  204. }
  205. /**
  206. * 同时将多个 field-value (域-值)对设置到哈希表 key 中
  207. *
  208. * @author caiLinFeng
  209. * @date 2018年1月30日
  210. * @param
  211. */
  212. public void hmset(String key, Map<String, Object> map) {
  213. redisTemplate.opsForHash().putAll(key, map);
  214. }
  215. /**
  216. * 将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在
  217. *
  218. * @author caiLinFeng
  219. * @date 2018年1月30日
  220. * @param
  221. */
  222. public Boolean hsetnx(String key, String hashKey, Object hashValue) {
  223. return redisTemplate.opsForHash().putIfAbsent(key, hashKey, hashValue);
  224. }
  225. /**
  226. * 返回哈希表 key 中给定域 field 的值
  227. *
  228. * @author caiLinFeng
  229. * @date 2018年1月30日
  230. * @param
  231. */
  232. public Object hget(String key, String hashKey) {
  233. return redisTemplate.opsForHash().get(key, hashKey);
  234. }
  235. /**
  236. * 返回哈希表 key 中,所有的域和值
  237. *
  238. * @author caiLinFeng
  239. * @date 2018年1月30日
  240. * @param
  241. */
  242. public Map<Object, Object> hgetAll(String key) {
  243. return redisTemplate.opsForHash().entries(key);
  244. }
  245. /**
  246. * 返回哈希表 key 中的所有域
  247. *
  248. * @author caiLinFeng
  249. * @date 2018年1月30日
  250. * @param
  251. */
  252. public Set<Object> hkeys(String key) {
  253. return redisTemplate.opsForHash().keys(key);
  254. }
  255. /**
  256. * 返回哈希表 key 中所有域的值
  257. *
  258. * @author caiLinFeng
  259. * @date 2018年1月30日
  260. * @param
  261. */
  262. public List<Object> hvals(String key) {
  263. return redisTemplate.opsForHash().values(key);
  264. }
  265. /**
  266. * 为哈希表 key 中的域 field 的值加上增量 delta
  267. *
  268. * @author caiLinFeng
  269. * @date 2018年1月30日
  270. * @param
  271. */
  272. public Long hincrBy(String key, String hashKey, long delta) {
  273. return redisTemplate.opsForHash().increment(key, hashKey, delta);
  274. }
  275. /**
  276. * 查看哈希表 key 中,给定域 field 是否存在
  277. *
  278. * @author caiLinFeng
  279. * @date 2018年1月30日
  280. * @param
  281. */
  282. public Boolean hexists(final String key, String hashKey) {
  283. return redisTemplate.opsForHash().hasKey(key, hashKey);
  284. }
  285. /******************* List **********************/
  286. /**
  287. * 删除并获取列表中的第一个元素
  288. *
  289. * @author caiLinFeng
  290. * @date 2018年1月30日
  291. * @param
  292. */
  293. public Object lpop(String key) {
  294. return redisTemplate.opsForList().leftPop(key);
  295. }
  296. /**
  297. * 删除并获取列表中的第一个元素,或阻塞,直到有一个元素可用
  298. *
  299. * @author caiLinFeng
  300. * @date 2018年1月30日
  301. * @param
  302. */
  303. public Object blpop(String key, long timeout, TimeUnit unit) {
  304. return redisTemplate.opsForList().leftPop(key, timeout, unit);
  305. }
  306. /**
  307. * 删除并获取列表中的最后一个元素
  308. *
  309. * @author caiLinFeng
  310. * @date 2018年1月30日
  311. * @param
  312. */
  313. public Object rpop(String key) {
  314. return redisTemplate.opsForList().rightPop(key);
  315. }
  316. /**
  317. * 删除并获取列表中的最后一个元素,或阻塞,直到有一个元素可用
  318. *
  319. * @author caiLinFeng
  320. * @date 2018年1月30日
  321. * @param
  322. */
  323. public Object brpop(String key, long timeout, TimeUnit unit) {
  324. return redisTemplate.opsForList().rightPop(key, timeout, unit);
  325. }
  326. /**
  327. * 返回列表 key 的长度
  328. *
  329. * @author caiLinFeng
  330. * @date 2018年1月30日
  331. * @param
  332. */
  333. public Long llen(String key) {
  334. return redisTemplate.opsForList().size(key);
  335. }
  336. /**
  337. * 将value 插入到列表 key 的表头
  338. *
  339. * @author caiLinFeng
  340. * @date 2018年1月30日
  341. * @param
  342. */
  343. public Long lpush(String key, Object value) {
  344. return redisTemplate.opsForList().leftPush(key, value);
  345. }
  346. /**
  347. * 将值 value 插入到列表 key 的表头,当且仅当 key 存在并且是一个列表
  348. *
  349. * @author caiLinFeng
  350. * @date 2018年1月30日
  351. * @param
  352. */
  353. public Long lpushx(String key, Object value) {
  354. return redisTemplate.opsForList().leftPushIfPresent(key, value);
  355. }
  356. /**
  357. * 将value 插入到列表 key 的表尾
  358. *
  359. * @author caiLinFeng
  360. * @date 2018年1月30日
  361. * @param
  362. */
  363. public Long rpush(String key, Object value) {
  364. return redisTemplate.opsForList().rightPush(key, value);
  365. }
  366. /**
  367. * 将值 value 插入到列表 key 的表尾,当且仅当 key 存在并且是一个列表
  368. *
  369. * @author caiLinFeng
  370. * @date 2018年1月30日
  371. * @param
  372. */
  373. public Long rpushx(String key, Object value) {
  374. return redisTemplate.opsForList().rightPushIfPresent(key, value);
  375. }
  376. /******************* Set **********************/
  377. /**
  378. * 将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略
  379. *
  380. * @author caiLinFeng
  381. * @date 2018年1月30日
  382. * @param
  383. */
  384. public Long sadd(String key, Object... values) {
  385. return redisTemplate.opsForSet().add(key, values);
  386. }
  387. /**
  388. * 返回集合 key 的基数(集合中元素的数量)
  389. *
  390. * @author caiLinFeng
  391. * @date 2018年1月30日
  392. * @param
  393. */
  394. public Long scard(String key) {
  395. return redisTemplate.opsForSet().size(key);
  396. }
  397. /**
  398. * 返回一个集合的全部成员,该集合是所有给定集合之间的差集
  399. *
  400. * @author caiLinFeng
  401. * @date 2018年1月30日
  402. * @param
  403. */
  404. public Set<Object> sdiff(String key, String otherKey) {
  405. return redisTemplate.opsForSet().difference(key, otherKey);
  406. }
  407. /**
  408. * 返回一个集合的全部成员,该集合是所有给定集合之间的差集
  409. *
  410. * @author caiLinFeng
  411. * @date 2018年1月30日
  412. * @param
  413. */
  414. public Set<Object> sdiff(String key, Collection<String> otherKeys) {
  415. return redisTemplate.opsForSet().difference(key, otherKeys);
  416. }
  417. /**
  418. * 返回一个集合的全部成员,该集合是所有给定集合的交集
  419. *
  420. * @author caiLinFeng
  421. * @date 2018年1月30日
  422. * @param
  423. */
  424. public Set<Object> sinter(String key, String otherKey) {
  425. return redisTemplate.opsForSet().intersect(key, otherKey);
  426. }
  427. /**
  428. * 返回一个集合的全部成员,该集合是所有给定集合的交集
  429. *
  430. * @author caiLinFeng
  431. * @date 2018年1月30日
  432. * @param
  433. */
  434. public Set<Object> sinter(String key, Collection<String> otherKeys) {
  435. return redisTemplate.opsForSet().intersect(key, otherKeys);
  436. }
  437. /**
  438. * 判断 member 元素是否集合 key 的成员
  439. *
  440. * @author caiLinFeng
  441. * @date 2018年1月30日
  442. * @param
  443. */
  444. public Boolean sismember(String key, Object member) {
  445. return redisTemplate.opsForSet().isMember(key, member);
  446. }
  447. /**
  448. * 返回集合 key 中的所有成员
  449. *
  450. * @author caiLinFeng
  451. * @date 2018年1月30日
  452. * @param
  453. */
  454. public Set<Object> smembers(String key) {
  455. return redisTemplate.opsForSet().members(key);
  456. }
  457. /**
  458. * 移除集合 key 中的一个或多个 member 元素,不存在的 member 元素会被忽略
  459. *
  460. * @author caiLinFeng
  461. * @date 2018年1月30日
  462. * @param
  463. */
  464. public Long srem(String key, Object... values) {
  465. return redisTemplate.opsForSet().remove(key, values);
  466. }
  467. /**
  468. * 返回一个集合的全部成员,该集合是所有给定集合的并集
  469. *
  470. * @author caiLinFeng
  471. * @date 2018年1月30日
  472. * @param
  473. */
  474. public Set<Object> sunion(String key, String otherKey) {
  475. return redisTemplate.opsForSet().union(key, otherKey);
  476. }
  477. /**
  478. * 返回一个集合的全部成员,该集合是所有给定集合的并集
  479. *
  480. * @author caiLinFeng
  481. * @date 2018年1月30日
  482. * @param
  483. */
  484. public Set<Object> sunion(String key, Collection<String> otherKeys) {
  485. return redisTemplate.opsForSet().union(key, otherKeys);
  486. }
  487. /******************* Zset **********************/
  488. /**
  489. * 将一个或多个 member 元素及其 score 值加入到有序集 key 当中v
  490. *
  491. * @author caiLinFeng
  492. * @date 2018年1月30日
  493. * @param
  494. */
  495. public Boolean zadd(String key, Object value, double score) {
  496. return redisTemplate.opsForZSet().add(key, value, score);
  497. }
  498. /**
  499. * 返回有序集 key 的基数
  500. *
  501. * @author caiLinFeng
  502. * @date 2018年1月30日
  503. * @param
  504. */
  505. public Long zcard(String key) {
  506. return redisTemplate.opsForZSet().zCard(key);
  507. }
  508. /**
  509. * 返回有序集 key 中, score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max)的成员的数量
  510. *
  511. * @author caiLinFeng
  512. * @date 2018年1月30日
  513. * @param
  514. */
  515. public Long zcount(String key, double min, double max) {
  516. return redisTemplate.opsForZSet().count(key, min, max);
  517. }
  518. /**
  519. * 为有序集 key 的成员 member 的 score 值加上增量 delta
  520. *
  521. * @author caiLinFeng
  522. * @date 2018年1月30日
  523. * @param
  524. */
  525. public Double zincrby(String key, Object value, double delta) {
  526. return redisTemplate.opsForZSet().incrementScore(key, value, delta);
  527. }
  528. /**
  529. * 返回有序集 key 中,指定区间内的成员,其中成员的位置按 score 值递增(从小到大)来排序
  530. *
  531. * @author caiLinFeng
  532. * @date 2018年1月30日
  533. * @param
  534. */
  535. public Set<Object> zrange(String key, long start, long end) {
  536. return redisTemplate.opsForZSet().range(key, start, end);
  537. }
  538. /**
  539. * 返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max)的成员。有序集成员按
  540. * score,值递增(从小到大)次序排列
  541. *
  542. * @author caiLinFeng
  543. * @date 2018年1月30日
  544. * @param
  545. */
  546. public Set<Object> zrangeByScore(String key, double min, double max) {
  547. return redisTemplate.opsForZSet().rangeByScore(key, min, max);
  548. }
  549. /**
  550. * 返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递增(从小到大)顺序排列。排名以 0 为底
  551. *
  552. * @author caiLinFeng
  553. * @date 2018年1月30日
  554. * @param
  555. */
  556. public Long zrank(String key, String member) {
  557. return redisTemplate.opsForZSet().rank(key, member);
  558. }
  559. /**
  560. * 移除有序集 key 中,指定排名(rank)区间内的所有成员
  561. *
  562. * @author caiLinFeng
  563. * @date 2018年1月30日
  564. * @param
  565. */
  566. public Long zremrangeByRank(String key, long start, long end) {
  567. return redisTemplate.opsForZSet().removeRange(key, start, end);
  568. }
  569. /**
  570. * 移除有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员
  571. *
  572. * @author caiLinFeng
  573. * @date 2018年1月30日
  574. * @param
  575. */
  576. public Long zremrangeByScore(String key, double min, double max) {
  577. return redisTemplate.opsForZSet().removeRangeByScore(key, min, max);
  578. }
  579. /**
  580. * 返回有序集 key 中,指定区间内的成员。其中成员的位置按 score 值递减(从大到小)来排列。
  581. *
  582. * @author caiLinFeng
  583. * @date 2018年1月30日
  584. * @param
  585. */
  586. public Set<Object> zrevrange(String key, long start, long end) {
  587. return redisTemplate.opsForZSet().reverseRange(key, start, end);
  588. }
  589. /**
  590. * 返回有序集 key 中, score 值介于 max 和 min 之间(默认包括等于 max 或 min)的所有的成员。有序集成员按
  591. * score,值递减(从大到小)的次序排列
  592. *
  593. * @author caiLinFeng
  594. * @date 2018年1月30日
  595. * @param
  596. */
  597. public Set<Object> zrevrangeByScore(String key, double min, double max) {
  598. return redisTemplate.opsForZSet().reverseRangeByScore(key, min, max);
  599. }
  600. /**
  601. * 返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递减(从大到小)排序。排名以 0 为底
  602. *
  603. * @author caiLinFeng
  604. * @date 2018年1月30日
  605. * @param
  606. */
  607. public Long zrevrank(String key, String member) {
  608. return redisTemplate.opsForZSet().reverseRank(key, member);
  609. }
  610. /**
  611. * 返回有序集 key 中,成员 member 的 score 值
  612. *
  613. * @author caiLinFeng
  614. * @date 2018年1月30日
  615. * @param
  616. */
  617. public Double zscore(String key, String member) {
  618. return redisTemplate.opsForZSet().score(key, member);
  619. }
  620. /******************* Pub/Sub **********************/
  621. /**
  622. * 将信息 message 发送到指定的频道 channel
  623. *
  624. * @author caiLinFeng
  625. * @date 2018年1月30日
  626. * @param chanel
  627. */
  628. public void publish(String channel, Object message) {
  629. redisTemplate.convertAndSend(channel, message);
  630. }
  631. /******************* serial **********************/
  632. /**
  633. * 获取redisTemplate的序列化
  634. *
  635. * @author caiLinFeng
  636. * @date 2018年1月30日
  637. * @param
  638. */
  639. public RedisSerializer<?> getDefaultSerializer() {
  640. return redisTemplate.getDefaultSerializer();
  641. }
  642. public RedisSerializer<?> getStringSerializer() {
  643. return redisTemplate.getStringSerializer();
  644. }
  645. public RedisSerializer<?> getValueSerializer() {
  646. return redisTemplate.getValueSerializer();
  647. }
  648. }

返回结果工具类

  1. package com.ac.sdk.response;
  2. import java.io.Serializable;
  3. import java.util.Date;
  4. import com.ac.sdk.constant.ErrorCodeEnum;
  5. import com.fasterxml.jackson.annotation.JsonFormat;
  6. import lombok.Data;
  7. /**
  8. * API返回类
  9. *
  10. * @author caiLinFeng
  11. * @date 2018年1月11日
  12. */
  13. @Data
  14. public class Result<T> implements Serializable {
  15. private final static long serialVersionUID = 1L;
  16. /**
  17. * 错误码
  18. */
  19. private int errorCode;
  20. /**
  21. * 错误提示
  22. */
  23. private String errorMessage;
  24. /**
  25. * 数据
  26. */
  27. private T data;
  28. /**
  29. * 总数
  30. */
  31. private Integer total;
  32. /**
  33. * 当前时间
  34. */
  35. @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8")
  36. private Date currentTime = new Date();
  37. /**
  38. * 额外数据
  39. */
  40. private Object attach;
  41. public static <T> Result<T> success() {
  42. Result<T> result = new Result<T>();
  43. result.setErrorCode(ErrorCodeEnum.OK.getCode());
  44. return result;
  45. }
  46. public static <T> Result<T> success(T data) {
  47. Result<T> result = success();
  48. result.setData(data);
  49. return result;
  50. }
  51. public static <T> Result<T> success(T data, int total) {
  52. Result<T> result = success(data);
  53. result.setTotal(total);
  54. return result;
  55. }
  56. public static <T> Result<T> fail() {
  57. Result<T> result = new Result<T>();
  58. result.setErrorCode(ErrorCodeEnum.UNDEFINE_ERROR.getCode());
  59. result.setErrorMessage(ErrorCodeEnum.UNDEFINE_ERROR.getMessage());
  60. return result;
  61. }
  62. public static <T> Result<T> fail(String errorMessag) {
  63. Result<T> result = fail();
  64. result.setErrorMessage(errorMessag);
  65. return result;
  66. }
  67. public static <T> Result<T> fail(ErrorCodeEnum errorCodeEnum) {
  68. Result<T> result = fail();
  69. result.setErrorCode(errorCodeEnum.getCode());
  70. result.setErrorMessage(errorCodeEnum.getMessage());
  71. return result;
  72. }
  73. public boolean isSuccess() {
  74. return ErrorCodeEnum.OK.getCode() == errorCode;
  75. }
  76. @Override
  77. public String toString() {
  78. return "Result [errorCode=" + errorCode + ", errorMessage=" + errorMessage + ", data=" + data + ", total="
  79. + total + ", attach=" + attach + "]";
  80. }
  81. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/234568
推荐阅读
相关标签
  

闽ICP备14008679号