提交 ee7c9152 编写于 作者: yubinCloud's avatar yubinCloud

11-3 通过每次点赞后在 redis 中存放一个 ip + docID 从而限制24小时内只能对一个文档点赞一次

上级 b12c806b
...@@ -2,6 +2,7 @@ package io.github.yubincloud.fairywiki.aspect; ...@@ -2,6 +2,7 @@ package io.github.yubincloud.fairywiki.aspect;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.support.spring.PropertyPreFilters; import com.alibaba.fastjson.support.spring.PropertyPreFilters;
import io.github.yubincloud.fairywiki.utils.RequestContext;
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature; import org.aspectj.lang.Signature;
...@@ -46,6 +47,8 @@ public class LogAspect { ...@@ -46,6 +47,8 @@ public class LogAspect {
LOG.info("类名方法: {}.{}", signature.getDeclaringTypeName(), name); LOG.info("类名方法: {}.{}", signature.getDeclaringTypeName(), name);
LOG.info("远程地址: {}", request.getRemoteAddr()); LOG.info("远程地址: {}", request.getRemoteAddr());
RequestContext.setRemoteAddr(getRemoteIp(request));
// 打印请求参数 // 打印请求参数
Object[] args = joinPoint.getArgs(); Object[] args = joinPoint.getArgs();
// LOG.info("请求参数: {}", JSONObject.toJSONString(args)); // LOG.info("请求参数: {}", JSONObject.toJSONString(args));
......
...@@ -7,6 +7,7 @@ public enum BusinessExceptionCode { ...@@ -7,6 +7,7 @@ public enum BusinessExceptionCode {
USER_LOGIN_NAME_EXIST("登录名已存在"), USER_LOGIN_NAME_EXIST("登录名已存在"),
LOGIN_USER_ERROR("用户名不存在或密码错误"), LOGIN_USER_ERROR("用户名不存在或密码错误"),
VOTE_REPEAT("您已点赞过,请于 24 小时后再次操作"),
; ;
private String desc; private String desc;
......
...@@ -9,10 +9,14 @@ import io.github.yubincloud.fairywiki.dto.req.DocQueryReqDto; ...@@ -9,10 +9,14 @@ import io.github.yubincloud.fairywiki.dto.req.DocQueryReqDto;
import io.github.yubincloud.fairywiki.dto.req.DocSaveReqDto; import io.github.yubincloud.fairywiki.dto.req.DocSaveReqDto;
import io.github.yubincloud.fairywiki.dto.resp.DocQueryRespDto; import io.github.yubincloud.fairywiki.dto.resp.DocQueryRespDto;
import io.github.yubincloud.fairywiki.dto.resp.PageRespDto; import io.github.yubincloud.fairywiki.dto.resp.PageRespDto;
import io.github.yubincloud.fairywiki.exception.BusinessException;
import io.github.yubincloud.fairywiki.exception.BusinessExceptionCode;
import io.github.yubincloud.fairywiki.mapper.ContentMapper; import io.github.yubincloud.fairywiki.mapper.ContentMapper;
import io.github.yubincloud.fairywiki.mapper.DocMapper; import io.github.yubincloud.fairywiki.mapper.DocMapper;
import io.github.yubincloud.fairywiki.mapper.DocMapperCustom; import io.github.yubincloud.fairywiki.mapper.DocMapperCustom;
import io.github.yubincloud.fairywiki.utils.CopyUtil; import io.github.yubincloud.fairywiki.utils.CopyUtil;
import io.github.yubincloud.fairywiki.utils.RedisUtil;
import io.github.yubincloud.fairywiki.utils.RequestContext;
import io.github.yubincloud.fairywiki.utils.SnowFlake; import io.github.yubincloud.fairywiki.utils.SnowFlake;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -39,6 +43,9 @@ public class DocService { ...@@ -39,6 +43,9 @@ public class DocService {
@Resource @Resource
private SnowFlake snowFlake; private SnowFlake snowFlake;
@Resource
private RedisUtil redisUtil;
/** /**
* 获取全部 Doc * 获取全部 Doc
*/ */
...@@ -129,6 +136,21 @@ public class DocService { ...@@ -129,6 +136,21 @@ public class DocService {
* @param docId 文档的 id * @param docId 文档的 id
*/ */
public void vote(Long docId) { public void vote(Long docId) {
String ip = RequestContext.getRemoteAddr();
String ipKey = constructIpKeyInRedis(docId, ip);
if (redisUtil.validateRepeatedKey(ipKey, 3600 * 24)) {
docMapperCustom.increaseVoteCount(docId);
} else {
throw new BusinessException(BusinessExceptionCode.VOTE_REPEAT);
}
docMapperCustom.increaseVoteCount(docId); docMapperCustom.increaseVoteCount(docId);
} }
/**
* 构造 IP + docID 作为存放于 redis 中的 key,24小时内不能重复
* @return 构造生成的 key
*/
private String constructIpKeyInRedis(Long docId, String ip) {
return "ODC_VOTE_" + docId + "_" + ip;
}
} }
package io.github.yubincloud.fairywiki.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
@Component
public class RedisUtil {
private static final Logger LOG = LoggerFactory.getLogger(RedisUtil.class);
@Resource
private RedisTemplate<String, String> redisTemplate;
/**
* 检测 Redis 中的 key 是否重复,若不重复则存入该 key
* @param second 过期时间(秒)
* @return 重复则返回 false,若新增 key 则返回 true
*/
public boolean validateRepeatedKey(String key, long second) {
if (redisTemplate.hasKey(key)) {
LOG.info("key已存在:{}", key);
return false;
} else {
LOG.info("key 不存在,放入 key:{},过期时间:{}秒", key, second);
redisTemplate.opsForValue().set(key, key, second, TimeUnit.SECONDS);
return true;
}
}
}
package io.github.yubincloud.fairywiki.utils;
import java.io.Serializable;
public class RequestContext implements Serializable {
private static final ThreadLocal<String> remoteAddr = new ThreadLocal<>();
public static String getRemoteAddr() {
return remoteAddr.get();
}
public static void setRemoteAddr(String remoteAddr) {
RequestContext.remoteAddr.set(remoteAddr);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册