23 changed files with 712 additions and 77 deletions
@ -0,0 +1,34 @@ |
|||||
|
package com.bnyer.img.config; |
||||
|
|
||||
|
import lombok.Getter; |
||||
|
import org.springframework.beans.factory.annotation.Value; |
||||
|
import org.springframework.boot.context.properties.ConfigurationProperties; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
|
||||
|
/** |
||||
|
* @author chengkun |
||||
|
* @date 2022/4/21 17:43 |
||||
|
*/ |
||||
|
@Configuration |
||||
|
@ConfigurationProperties(prefix = "bnyer.img.tiktok") |
||||
|
@Getter |
||||
|
public class TiktokConfig { |
||||
|
|
||||
|
@Value("${bnyer.img.tiktok.appId}") |
||||
|
private String appId; |
||||
|
|
||||
|
@Value("${bnyer.img.tiktok.secret}") |
||||
|
public String secret; |
||||
|
|
||||
|
@Value("${bnyer.img.tiktok.sessionInfoUrl}") |
||||
|
public String sessionInfoUrl; |
||||
|
|
||||
|
@Value("${bnyer.img.tiktok.tokenUrl}") |
||||
|
public String tokenUrl; |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
package com.bnyer.img.constants; |
||||
|
|
||||
|
/** |
||||
|
* @author chengkun |
||||
|
* @date 2022/4/21 18:12 |
||||
|
*/ |
||||
|
public class TiktokConstant { |
||||
|
|
||||
|
/** |
||||
|
* 抖音接口成功响应码 |
||||
|
*/ |
||||
|
public static final String SUCCESS = "0"; |
||||
|
} |
||||
@ -1,17 +0,0 @@ |
|||||
package com.bnyer.img.controller; |
|
||||
|
|
||||
import com.bnyer.common.core.web.controller.BaseController; |
|
||||
import com.bnyer.img.service.TiktokCollectionService; |
|
||||
import io.swagger.annotations.Api; |
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||
import org.springframework.web.bind.annotation.RequestMapping; |
|
||||
import org.springframework.web.bind.annotation.RestController; |
|
||||
|
|
||||
@Api("img-tiktokCollection-【后端】接口") |
|
||||
@RestController |
|
||||
@RequestMapping("/tiktokCollection") |
|
||||
public class TiktokCollectionController extends BaseController { |
|
||||
|
|
||||
@Autowired |
|
||||
private TiktokCollectionService tiktokCollectionService; |
|
||||
} |
|
||||
@ -0,0 +1,57 @@ |
|||||
|
package com.bnyer.img.domain; |
||||
|
|
||||
|
import com.baomidou.mybatisplus.annotation.IdType; |
||||
|
import com.baomidou.mybatisplus.annotation.TableField; |
||||
|
import com.baomidou.mybatisplus.annotation.TableId; |
||||
|
import com.baomidou.mybatisplus.annotation.TableName; |
||||
|
import io.swagger.annotations.ApiModel; |
||||
|
import io.swagger.annotations.ApiModelProperty; |
||||
|
import lombok.*; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
|
||||
|
/** |
||||
|
* @author chengkun |
||||
|
* @date 2022/4/21 9:50 |
||||
|
*/ |
||||
|
/** |
||||
|
* img平台点赞表 |
||||
|
*/ |
||||
|
@ApiModel(value="com-bnyer-img-domain-TiktokLike") |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@ToString |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@TableName(value = "img_tiktok_like") |
||||
|
public class TiktokLike extends BaseDomain { |
||||
|
/** |
||||
|
* 主键 |
||||
|
*/ |
||||
|
@TableId(value = "id", type = IdType.AUTO) |
||||
|
@ApiModelProperty(value="主键") |
||||
|
private Long id; |
||||
|
|
||||
|
/** |
||||
|
* 用户id |
||||
|
*/ |
||||
|
@TableField(value = "user_id") |
||||
|
@ApiModelProperty(value="用户id") |
||||
|
private Long userId; |
||||
|
|
||||
|
/** |
||||
|
* 图片id |
||||
|
*/ |
||||
|
@TableField(value = "img_id") |
||||
|
@ApiModelProperty(value="图片id") |
||||
|
private Long imgId; |
||||
|
|
||||
|
/** |
||||
|
* 是否显示 (0->隐藏;1->显示) |
||||
|
*/ |
||||
|
@TableField(value = "is_show") |
||||
|
@ApiModelProperty(value="是否显示 (0->隐藏;1->显示)") |
||||
|
private String isShow; |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
package com.bnyer.img.dto; |
||||
|
|
||||
|
import io.swagger.annotations.ApiModel; |
||||
|
import io.swagger.annotations.ApiModelProperty; |
||||
|
import lombok.Getter; |
||||
|
import lombok.Setter; |
||||
|
|
||||
|
import javax.validation.constraints.NotNull; |
||||
|
import java.io.Serializable; |
||||
|
|
||||
|
|
||||
|
@Getter |
||||
|
@Setter |
||||
|
@ApiModel("用户收藏接收类") |
||||
|
public class CollectionUserDto implements Serializable { |
||||
|
|
||||
|
@NotNull(message = "用户id不能为空!") |
||||
|
@ApiModelProperty(value="用户id") |
||||
|
private Long userId; |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
package com.bnyer.img.feign; |
||||
|
|
||||
|
import com.alibaba.fastjson.JSONObject; |
||||
|
import org.springframework.cloud.openfeign.FeignClient; |
||||
|
import org.springframework.web.bind.annotation.GetMapping; |
||||
|
import org.springframework.web.bind.annotation.RequestParam; |
||||
|
|
||||
|
import java.util.Map; |
||||
|
|
||||
|
/** |
||||
|
* @author chengkun |
||||
|
* @date 2022/4/21 18:04 |
||||
|
*/ |
||||
|
@FeignClient(name = "tiktok-service", url = "${bnyer.img.tiktok.sessionInfoUrl}") |
||||
|
public interface TiktokFeign { |
||||
|
|
||||
|
/** |
||||
|
* 获取抖音sessionInfo |
||||
|
* @param params 授权参数 |
||||
|
* @return - |
||||
|
*/ |
||||
|
@GetMapping("/cash_account/total") |
||||
|
JSONObject getSessionInfo(@RequestParam Map<String, String> params); |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
package com.bnyer.img.mapper; |
||||
|
|
||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
|
import com.bnyer.img.domain.TiktokLike; |
||||
|
import org.apache.ibatis.annotations.Mapper; |
||||
|
|
||||
|
/** |
||||
|
* @author chengkun |
||||
|
* @date 2022/4/21 9:50 |
||||
|
*/ |
||||
|
@Mapper |
||||
|
public interface TiktokLikeMapper extends BaseMapper<TiktokLike> { |
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
package com.bnyer.img.service.impl; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface TiktokLikeService { |
||||
|
|
||||
|
/** |
||||
|
* 同步redis点赞到db中 |
||||
|
*/ |
||||
|
void insertRecord(); |
||||
|
|
||||
|
/** |
||||
|
* 同步redis点赞数量到db中 |
||||
|
*/ |
||||
|
void insertNum(); |
||||
|
|
||||
|
/** |
||||
|
* 批量删除点赞 |
||||
|
* @param ids 主键ids |
||||
|
* @return - |
||||
|
*/ |
||||
|
int delete(List<Long> ids); |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 点赞 |
||||
|
* @param userId 用户Id |
||||
|
* @param imgId 图片Id |
||||
|
*/ |
||||
|
void like(Long userId, Long imgId); |
||||
|
|
||||
|
/** |
||||
|
* 取消点赞 |
||||
|
* @param userId 用户Id |
||||
|
* @param imgId 图片Id |
||||
|
*/ |
||||
|
void unLike(Long userId, Long imgId); |
||||
|
|
||||
|
/** |
||||
|
* 判断是否进行过点赞 |
||||
|
* @param userId 用户id |
||||
|
* @param imgId 图片id |
||||
|
* @return - |
||||
|
*/ |
||||
|
boolean judgeLike(Long userId, Long imgId); |
||||
|
} |
||||
@ -0,0 +1,141 @@ |
|||||
|
package com.bnyer.img.service.impl; |
||||
|
|
||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
||||
|
import com.bnyer.common.redis.service.RedisService; |
||||
|
import com.bnyer.img.constants.RedisKeyConstant; |
||||
|
import com.bnyer.img.domain.TiktokImg; |
||||
|
import com.bnyer.img.domain.TiktokLike; |
||||
|
import com.bnyer.img.enums.TiktokLikeEnum; |
||||
|
import com.bnyer.img.mapper.TiktokImgMapper; |
||||
|
import com.bnyer.img.mapper.TiktokLikeMapper; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.data.redis.core.Cursor; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
import java.util.Date; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
@Service |
||||
|
@Slf4j |
||||
|
public class TiktokLikeServiceImpl implements TiktokLikeService { |
||||
|
|
||||
|
@Autowired |
||||
|
private TiktokLikeMapper tiktokLikeMapper; |
||||
|
|
||||
|
@Autowired |
||||
|
private RedisService redisService; |
||||
|
|
||||
|
@Autowired |
||||
|
private TiktokImgMapper tiktokImgMapper; |
||||
|
|
||||
|
private String getHashKey(Long userId, Long imgId){ |
||||
|
return userId+":"+imgId; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void insertRecord() { |
||||
|
log.info("==============redis同步点赞记录到db数据开始!==============="); |
||||
|
long startTime = System.currentTimeMillis(); |
||||
|
//拿缓存
|
||||
|
String redisKey = RedisKeyConstant.TIKTOK_USER_LIKE_KEY; |
||||
|
Cursor<Map.Entry<Object, Object>> like = redisService.getHashScan(redisKey); |
||||
|
while (like.hasNext()){ |
||||
|
Map.Entry<Object, Object> next = like.next(); |
||||
|
String key = (String) next.getKey(); |
||||
|
//分离出 userId,imgId
|
||||
|
String[] split = key.split(":"); |
||||
|
String userId = split[0]; |
||||
|
Long userLongId = Long.parseLong(userId); |
||||
|
String imgId = split[1]; |
||||
|
Long imgLongId = Long.parseLong(imgId); |
||||
|
TiktokLike tiktokLike = new TiktokLike(); |
||||
|
tiktokLike.setUserId(userLongId); |
||||
|
tiktokLike.setImgId(imgLongId); |
||||
|
tiktokLike.setCreateTime(new Date()); |
||||
|
tiktokLike.setUpdateTime(new Date()); |
||||
|
tiktokLikeMapper.insert(tiktokLike); |
||||
|
//保存后从 Redis 中删除
|
||||
|
redisService.deleteHashKey(redisKey,key); |
||||
|
} |
||||
|
log.info("==============redis同步点赞记录到db数据完成,耗时【{}】毫秒!===============",System.currentTimeMillis() - startTime); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void insertNum() { |
||||
|
log.info("==============redis同步图片点赞数量到db数据开始!==============="); |
||||
|
long startTime = System.currentTimeMillis(); |
||||
|
String imgLikeNumKey = RedisKeyConstant.TIKTOK_IMG_LIKE_NUM_KEY; |
||||
|
Cursor<Map.Entry<Object, Object>> likeNum = redisService.getHashScan(imgLikeNumKey); |
||||
|
while (likeNum.hasNext()){ |
||||
|
Map.Entry<Object, Object> next = likeNum.next(); |
||||
|
String imgId = (String) next.getKey(); |
||||
|
Long imgLongId = Long.parseLong(imgId); |
||||
|
Integer greatNum = (Integer) next.getValue(); |
||||
|
TiktokImg tiktokImg = new TiktokImg(); |
||||
|
tiktokImg.setId(imgLongId); |
||||
|
tiktokImg.setUpdateTime(new Date()); |
||||
|
tiktokImg.setGreatNum(greatNum); |
||||
|
tiktokImgMapper.updateById(tiktokImg); |
||||
|
//保存后从 Redis 中删除
|
||||
|
redisService.deleteHashKey(imgLikeNumKey,imgId); |
||||
|
} |
||||
|
log.info("==============redis同步图片点赞数量到db数据完成,耗时【{}】毫秒!===============",System.currentTimeMillis() - startTime); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public int delete(List<Long> ids) { |
||||
|
return tiktokLikeMapper.deleteBatchIds(ids); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void like(Long userId, Long imgId) { |
||||
|
String hashKey = getHashKey(userId,imgId); |
||||
|
String redisKey = RedisKeyConstant.TIKTOK_USER_LIKE_KEY; |
||||
|
String imgLikeNumKey = RedisKeyConstant.TIKTOK_IMG_LIKE_NUM_KEY; |
||||
|
//插入redis,状态置为1,图片数量+1
|
||||
|
redisService.setCacheMapValue(redisKey,hashKey, TiktokLikeEnum.LIKE.getCode()); |
||||
|
redisService.hashIncr(imgLikeNumKey,String.valueOf(imgId), 1); |
||||
|
log.info("用户【{}】点赞了图片【{}】,点赞量增加1",userId,imgId); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void unLike(Long userId, Long imgId) { |
||||
|
String hashKey = getHashKey(userId,imgId); |
||||
|
String redisKey = RedisKeyConstant.TIKTOK_USER_LIKE_KEY; |
||||
|
String imgLikeNumKey = RedisKeyConstant.TIKTOK_IMG_LIKE_NUM_KEY; |
||||
|
redisService.deleteHashKey(redisKey,hashKey); |
||||
|
redisService.hashIncr(imgLikeNumKey,String.valueOf(imgId), -1); |
||||
|
log.info("用户【{}】取消点赞了图片【{}】,点赞量减少1",userId,imgId); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean judgeLike(Long userId, Long imgId) { |
||||
|
//判断redis中是否存在点赞记录
|
||||
|
String hashKey = getHashKey(userId,imgId); |
||||
|
String redisKey = RedisKeyConstant.TIKTOK_USER_LIKE_KEY; |
||||
|
Integer value = (Integer) redisService.getCacheMapValue(redisKey, hashKey); |
||||
|
//缓存存在的情况下
|
||||
|
if(value != null){ |
||||
|
if(TiktokLikeEnum.LIKE.getCode().equals(value)){ |
||||
|
//redis中存在该记录
|
||||
|
return true; |
||||
|
}else if(TiktokLikeEnum.UN_LIKE.getCode().equals(value)){ |
||||
|
//redis中不存在该记录
|
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
//缓存不存在,同时解决重复点赞情况,此时查询数据库
|
||||
|
LambdaQueryWrapper<TiktokLike> wrapper = new LambdaQueryWrapper<>(); |
||||
|
wrapper.eq(TiktokLike::getUserId, userId).eq(TiktokLike::getImgId, imgId); |
||||
|
TiktokLike tiktokLike = tiktokLikeMapper.selectOne(wrapper); |
||||
|
if(tiktokLike != null){ |
||||
|
//存在则点赞过
|
||||
|
return true; |
||||
|
}else{ |
||||
|
//否则未点赞过
|
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,44 @@ |
|||||
|
package com.bnyer.img.vo; |
||||
|
|
||||
|
import io.swagger.annotations.ApiModel; |
||||
|
import io.swagger.annotations.ApiModelProperty; |
||||
|
import lombok.Getter; |
||||
|
import lombok.Setter; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
|
||||
|
|
||||
|
@Getter |
||||
|
@Setter |
||||
|
@ApiModel("抖音收藏响应类") |
||||
|
public class TiktokCollectionVo implements Serializable { |
||||
|
|
||||
|
@ApiModelProperty(value="id") |
||||
|
private Long id; |
||||
|
|
||||
|
@ApiModelProperty(value="图片id") |
||||
|
private Long imgId; |
||||
|
|
||||
|
@ApiModelProperty(value="图片地址") |
||||
|
private String imgUrl; |
||||
|
|
||||
|
@ApiModelProperty(value="用户id") |
||||
|
private Long userId; |
||||
|
|
||||
|
@ApiModelProperty(value="分类id") |
||||
|
private Long typeId; |
||||
|
|
||||
|
@ApiModelProperty(value="分类名称") |
||||
|
private String typeName; |
||||
|
|
||||
|
@ApiModelProperty(value="下载量") |
||||
|
private Integer downloadNum; |
||||
|
|
||||
|
@ApiModelProperty(value="点赞量") |
||||
|
private Integer greatNum; |
||||
|
|
||||
|
@ApiModelProperty(value="收藏量") |
||||
|
private Integer collectionNum; |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
package com.bnyer.img.vo; |
||||
|
|
||||
|
import io.swagger.annotations.ApiModel; |
||||
|
import io.swagger.annotations.ApiModelProperty; |
||||
|
import lombok.Getter; |
||||
|
import lombok.Setter; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
|
||||
|
|
||||
|
@Getter |
||||
|
@Setter |
||||
|
@ApiModel("抖音sessionInfo响应类") |
||||
|
public class TiktokSessionInfoVo implements Serializable { |
||||
|
|
||||
|
@ApiModelProperty(value="sessionKey") |
||||
|
private String sessionKey; |
||||
|
|
||||
|
@ApiModelProperty(value="openId") |
||||
|
private String openId; |
||||
|
|
||||
|
@ApiModelProperty(value="unionId") |
||||
|
private String unionId; |
||||
|
|
||||
|
@ApiModelProperty(value="anonymousOpenid") |
||||
|
private String anonymousOpenid; |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
|
<mapper namespace="com.bnyer.img.mapper.TiktokLikeMapper"> |
||||
|
<resultMap id="BaseResultMap" type="com.bnyer.img.domain.TiktokLike"> |
||||
|
<!--@mbg.generated--> |
||||
|
<!--@Table img_tiktok_like--> |
||||
|
<id column="id" jdbcType="BIGINT" property="id" /> |
||||
|
<result column="user_id" jdbcType="BIGINT" property="userId" /> |
||||
|
<result column="img_id" jdbcType="BIGINT" property="imgId" /> |
||||
|
<result column="is_show" jdbcType="CHAR" property="isShow" /> |
||||
|
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" /> |
||||
|
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime" /> |
||||
|
<result column="sort" jdbcType="INTEGER" property="sort" /> |
||||
|
</resultMap> |
||||
|
<sql id="Base_Column_List"> |
||||
|
<!--@mbg.generated--> |
||||
|
id, user_id, img_id, is_show, create_time, update_time, sort |
||||
|
</sql> |
||||
|
</mapper> |
||||
Loading…
Reference in new issue