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