订阅分类、兴趣推送、热度排行榜
This commit is contained in:
parent
300f326281
commit
b0a09142ae
|
@ -2,7 +2,7 @@
|
||||||
<module version="4">
|
<module version="4">
|
||||||
<component name="NewModuleRootManager">
|
<component name="NewModuleRootManager">
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/test" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/xubx-blog-api/src/main/test" isTestSource="true" />
|
||||||
</content>
|
</content>
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
|
@ -4,6 +4,7 @@ import org.mybatis.spring.annotation.MapperScan;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.cache.annotation.EnableCaching;
|
import org.springframework.cache.annotation.EnableCaching;
|
||||||
|
import org.springframework.scheduling.annotation.EnableAsync;
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||||
|
|
||||||
|
@ -12,6 +13,7 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||||
@MapperScan("com.xubx.springboot_01demo.mapper")
|
@MapperScan("com.xubx.springboot_01demo.mapper")
|
||||||
@EnableScheduling //开启定时任务
|
@EnableScheduling //开启定时任务
|
||||||
@EnableSwagger2 //开启Swagger2
|
@EnableSwagger2 //开启Swagger2
|
||||||
|
@EnableAsync // 开启异步任务
|
||||||
public class Springboot01DemoApplication {
|
public class Springboot01DemoApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|
|
@ -6,40 +6,47 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.xubx.springboot_01demo.configuration.constantConfiguration;
|
import com.xubx.springboot_01demo.configuration.constantConfiguration;
|
||||||
|
import com.xubx.springboot_01demo.entity.pojo.TopK;
|
||||||
|
import com.xubx.springboot_01demo.entity.vo.HotBlog;
|
||||||
import com.xubx.springboot_01demo.mapper.BlogLikeMapper;
|
import com.xubx.springboot_01demo.mapper.BlogLikeMapper;
|
||||||
import com.xubx.springboot_01demo.mapper.BlogsMapper;
|
import com.xubx.springboot_01demo.mapper.BlogsMapper;
|
||||||
import com.xubx.springboot_01demo.mapper.UserFavoriteBlogMapper;
|
import com.xubx.springboot_01demo.mapper.UserFavoriteBlogMapper;
|
||||||
import com.xubx.springboot_01demo.pojo.BlogLike;
|
import com.xubx.springboot_01demo.entity.pojo.BlogLike;
|
||||||
import com.xubx.springboot_01demo.pojo.Blogs;
|
import com.xubx.springboot_01demo.entity.pojo.Blogs;
|
||||||
import com.xubx.springboot_01demo.pojo.UserFavoriteBlog;
|
import com.xubx.springboot_01demo.entity.pojo.UserFavoriteBlog;
|
||||||
|
import com.xubx.springboot_01demo.service.BlogService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.RedisCallback;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class DataSync {
|
public class DataSync {
|
||||||
@Resource
|
@Resource
|
||||||
RedisTemplate redisTemplate;
|
private RedisTemplate redisTemplate;
|
||||||
@Resource
|
@Resource
|
||||||
BlogsMapper blogsMapper;
|
private BlogsMapper blogsMapper;
|
||||||
@Resource
|
@Resource
|
||||||
BlogLikeMapper blogLikeMapper;
|
private BlogLikeMapper blogLikeMapper;
|
||||||
@Resource
|
@Resource
|
||||||
UserFavoriteBlogMapper userFavoriteBlogMapper;
|
private UserFavoriteBlogMapper userFavoriteBlogMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
ObjectMapper objectMapper;
|
private BlogService blogService;
|
||||||
|
@Autowired
|
||||||
|
private ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 博客浏览数的数据同步 ,每小时执行一次
|
* 博客浏览数的数据同步 ,每小时执行一次
|
||||||
|
@ -97,6 +104,7 @@ public class DataSync {
|
||||||
try {
|
try {
|
||||||
Set<String> likeCountKeys = redisTemplate.keys(constantConfiguration.BLOG_LIKE_COUNT + "*");
|
Set<String> likeCountKeys = redisTemplate.keys(constantConfiguration.BLOG_LIKE_COUNT + "*");
|
||||||
if (likeCountKeys != null) {
|
if (likeCountKeys != null) {
|
||||||
|
likeCountKeys = likeCountKeys.stream().filter(key -> !key.endsWith(":expired")).collect(Collectors.toSet());
|
||||||
for (String key : likeCountKeys) {
|
for (String key : likeCountKeys) {
|
||||||
String blogIdStr = key.split(":")[2];
|
String blogIdStr = key.split(":")[2];
|
||||||
String likeCountExpireKey = constantConfiguration.BLOG_LIKE_COUNT + blogIdStr + ":expired";
|
String likeCountExpireKey = constantConfiguration.BLOG_LIKE_COUNT + blogIdStr + ":expired";
|
||||||
|
@ -139,6 +147,7 @@ public class DataSync {
|
||||||
try {
|
try {
|
||||||
Set<String> likeUserKeys = redisTemplate.keys(constantConfiguration.BLOG_LIKE_HASH + "*");
|
Set<String> likeUserKeys = redisTemplate.keys(constantConfiguration.BLOG_LIKE_HASH + "*");
|
||||||
if (likeUserKeys != null) {
|
if (likeUserKeys != null) {
|
||||||
|
likeUserKeys = likeUserKeys.stream().filter(key -> !key.endsWith(":expired")).collect(Collectors.toSet());
|
||||||
for (String key : likeUserKeys) {
|
for (String key : likeUserKeys) {
|
||||||
String blogIdStr = key.split(":")[2];
|
String blogIdStr = key.split(":")[2];
|
||||||
String likeUserExpireKey = constantConfiguration.BLOG_LIKE_HASH + blogIdStr + ":expired";
|
String likeUserExpireKey = constantConfiguration.BLOG_LIKE_HASH + blogIdStr + ":expired";
|
||||||
|
@ -160,10 +169,10 @@ public class DataSync {
|
||||||
|
|
||||||
if (blogLike == null) {
|
if (blogLike == null) {
|
||||||
BlogLike newBlogLike = new BlogLike();
|
BlogLike newBlogLike = new BlogLike();
|
||||||
newBlogLike.setBlogId(Integer.valueOf(blogIdStr));
|
newBlogLike.setBlogId(Long.valueOf(blogIdStr));
|
||||||
newBlogLike.setUserId(Integer.valueOf(userId));
|
newBlogLike.setUserId(Long.valueOf(userId));
|
||||||
newBlogLike.setCreatedTime(Timestamp.valueOf(LocalDateTime.now()));
|
newBlogLike.setCreatedTime(Timestamp.valueOf(LocalDateTime.now()));
|
||||||
blogLikeMapper.insert(newBlogLike);
|
blogLikeMapper.addData(newBlogLike);
|
||||||
}
|
}
|
||||||
} else if ("false".equals(likeStatus)) {
|
} else if ("false".equals(likeStatus)) {
|
||||||
// 用户取消点赞 则删除记录
|
// 用户取消点赞 则删除记录
|
||||||
|
@ -190,7 +199,7 @@ public class DataSync {
|
||||||
/**
|
/**
|
||||||
* 博客收藏数的数据同步定时任务
|
* 博客收藏数的数据同步定时任务
|
||||||
*/
|
*/
|
||||||
@Scheduled(cron = "0 * * * * ?") //TODO 每小时执行一次
|
@Scheduled(cron = "0 * * * * ?") //TODO 每小时执行一次,需要隔开,不能同一时间全部执行
|
||||||
public void collectCountSync() {
|
public void collectCountSync() {
|
||||||
log.info("博客收藏数的数据同步定时任务执行");
|
log.info("博客收藏数的数据同步定时任务执行");
|
||||||
String lockKey = constantConfiguration.BLOG_COLLECT_COUNT_SYNC_LOCK;
|
String lockKey = constantConfiguration.BLOG_COLLECT_COUNT_SYNC_LOCK;
|
||||||
|
@ -200,6 +209,7 @@ public class DataSync {
|
||||||
try {
|
try {
|
||||||
Set<String> collectCountKeys = redisTemplate.keys(constantConfiguration.BLOG_COLLECT_COUNT + "*");
|
Set<String> collectCountKeys = redisTemplate.keys(constantConfiguration.BLOG_COLLECT_COUNT + "*");
|
||||||
if (collectCountKeys != null) {
|
if (collectCountKeys != null) {
|
||||||
|
collectCountKeys = collectCountKeys.stream().filter(key -> !key.endsWith(":expired")).collect(Collectors.toSet());
|
||||||
for (String key : collectCountKeys) {
|
for (String key : collectCountKeys) {
|
||||||
String blogIdStr = key.split(":")[2];
|
String blogIdStr = key.split(":")[2];
|
||||||
String collectCountExpireKey = constantConfiguration.BLOG_COLLECT_COUNT + blogIdStr + ":expired";
|
String collectCountExpireKey = constantConfiguration.BLOG_COLLECT_COUNT + blogIdStr + ":expired";
|
||||||
|
@ -245,6 +255,7 @@ public class DataSync {
|
||||||
// TODO 应该是同时获取到了逻辑过期标志的Key,需要进行去除
|
// TODO 应该是同时获取到了逻辑过期标志的Key,需要进行去除
|
||||||
Set<String> collectUserKeys = redisTemplate.keys(constantConfiguration.BLOG_COLLECT_HASH + "*");
|
Set<String> collectUserKeys = redisTemplate.keys(constantConfiguration.BLOG_COLLECT_HASH + "*");
|
||||||
if (collectUserKeys != null) {
|
if (collectUserKeys != null) {
|
||||||
|
collectUserKeys = collectUserKeys.stream().filter(key -> !key.contains(":expired")).collect(Collectors.toSet());
|
||||||
for (String key : collectUserKeys) {
|
for (String key : collectUserKeys) {
|
||||||
String favoriteIdStr = key.split(":")[2];
|
String favoriteIdStr = key.split(":")[2];
|
||||||
String collectUserExpireKey = constantConfiguration.BLOG_COLLECT_HASH + favoriteIdStr + ":expired";
|
String collectUserExpireKey = constantConfiguration.BLOG_COLLECT_HASH + favoriteIdStr + ":expired";
|
||||||
|
@ -291,4 +302,77 @@ public class DataSync {
|
||||||
log.warn("无法获取分布式锁,跳过此次收藏用户Hash集合的数据同步任务");
|
log.warn("无法获取分布式锁,跳过此次收藏用户Hash集合的数据同步任务");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 热度排行榜,全表分片扫描
|
||||||
|
*/
|
||||||
|
@Scheduled(cron = "0 * * * * ?") //TODO 每小时执行一次
|
||||||
|
public void hotRank() {
|
||||||
|
log.info("热度排行榜刷新定时任务执行");
|
||||||
|
|
||||||
|
final TopK topK = new TopK(10);
|
||||||
|
long limit = 1000;
|
||||||
|
long id = 0;
|
||||||
|
|
||||||
|
List<Blogs> blogs = blogService.list(new LambdaQueryWrapper<Blogs>()
|
||||||
|
.select(Blogs::getId, Blogs::getTitle, Blogs::getLikeCount, Blogs::getViewCount, Blogs::getCollectCount, Blogs::getCommentCount,
|
||||||
|
Blogs::getShareCount, Blogs::getCreatedTime).gt(Blogs::getId, id)
|
||||||
|
.eq(Blogs::getStatus, "公开")
|
||||||
|
.last("limit " + limit));
|
||||||
|
|
||||||
|
while (!ObjectUtils.isEmpty(blogs)) {
|
||||||
|
for (Blogs blog : blogs) {
|
||||||
|
Long likeCount = blog.getLikeCount();
|
||||||
|
Double viewCount = blog.getViewCount() * 0.8;
|
||||||
|
Double collectCount = blog.getCollectCount() * 1.5;
|
||||||
|
Long commentCount = blog.getCommentCount();
|
||||||
|
Long shareCount = blog.getShareCount();
|
||||||
|
final Date date = new Date();
|
||||||
|
long decayTime = date.getTime() - blog.getCreatedTime().getTime();
|
||||||
|
// 防止出现热度完全相同的情况,加入0.1-1.0之间的随机小数
|
||||||
|
final double v = Math.random() * 0.9 + 0.1;
|
||||||
|
final double hot = hot(likeCount + viewCount + collectCount + commentCount + shareCount + v, TimeUnit.MILLISECONDS.toDays(decayTime));
|
||||||
|
final HotBlog hotBlog = new HotBlog(blog.getId(), hot, blog.getTitle());
|
||||||
|
|
||||||
|
// add过程中,已存入热度最大的十个博客
|
||||||
|
topK.add(hotBlog);
|
||||||
|
}
|
||||||
|
id = blogs.get(blogs.size() - 1).getId();
|
||||||
|
blogs = blogService.list(new LambdaQueryWrapper<Blogs>().gt(Blogs::getId, id).eq(Blogs::getStatus, "公开").last("limit " + limit));
|
||||||
|
}
|
||||||
|
// 通过redis管道进行数据更新
|
||||||
|
final byte[] key = constantConfiguration.HOT_RANK.getBytes();
|
||||||
|
final List<HotBlog> hotBlogs = topK.get();// 已从大到小排序
|
||||||
|
final Double minHot = hotBlogs.get(hotBlogs.size() - 1).getHot();
|
||||||
|
redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
|
||||||
|
for (HotBlog hotBlog : hotBlogs) {
|
||||||
|
final Double hot = hotBlog.getHot();
|
||||||
|
// 由于只有十条数据,直接存实体类
|
||||||
|
try {
|
||||||
|
hotBlog.setHot(null);
|
||||||
|
connection.zAdd(key, hot, objectMapper.writeValueAsString(hotBlog).getBytes());
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 删除热度低于minHot的元素
|
||||||
|
redisTemplate.opsForZSet().removeRangeByScore(constantConfiguration.HOT_RANK, minHot, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 控制衰减速度的常数,a 值越大,时间对热度的影响越强,意味着热度衰减得越快
|
||||||
|
*/
|
||||||
|
static double a = 0.011;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 热度半衰期公式
|
||||||
|
*/
|
||||||
|
public static double hot(double weight, double t) {
|
||||||
|
// Math.exp用于计算e的次方
|
||||||
|
// 指数衰减函数,随着 t 增大,Math.exp(-a * t) 的值逐渐变小
|
||||||
|
return weight * Math.exp(-a * t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
package com.xubx.springboot_01demo.Task;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
@Slf4j
|
|
||||||
public class Test {
|
|
||||||
@Scheduled(cron = "0/5 * * * * ?")
|
|
||||||
public void test() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,15 +1,12 @@
|
||||||
package com.xubx.springboot_01demo.WebSocket;
|
package com.xubx.springboot_01demo.WebSocket;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.xubx.springboot_01demo.dto.SendMesDto;
|
import com.xubx.springboot_01demo.entity.dto.SendMesDto;
|
||||||
import com.xubx.springboot_01demo.service.MessagesService;
|
import com.xubx.springboot_01demo.service.MessagesService;
|
||||||
import com.xubx.springboot_01demo.utils.token.RequestHolder;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.websocket.OnClose;
|
|
||||||
import javax.websocket.OnMessage;
|
import javax.websocket.OnMessage;
|
||||||
import javax.websocket.OnOpen;
|
import javax.websocket.OnOpen;
|
||||||
import javax.websocket.Session;
|
import javax.websocket.Session;
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.xubx.springboot_01demo.configuration;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.scheduling.annotation.EnableAsync;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableAsync
|
||||||
|
public class AsyncConfig {
|
||||||
|
//开启异步配置
|
||||||
|
@Bean(name = "asyncExecutor")
|
||||||
|
public Executor asyncExecutor() {
|
||||||
|
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||||
|
executor.setCorePoolSize(10);//核心线程数
|
||||||
|
executor.setMaxPoolSize(50);//最大线程数
|
||||||
|
executor.setQueueCapacity(100);//队列大小
|
||||||
|
executor.setKeepAliveSeconds(60);//线程空闲时间
|
||||||
|
executor.setThreadNamePrefix("Async-Executor-");//线程前缀
|
||||||
|
|
||||||
|
// 处理任务拒绝策略(这里选择丢弃最旧的任务)
|
||||||
|
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
|
||||||
|
executor.initialize();
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,4 +56,10 @@ public class constantConfiguration {
|
||||||
|
|
||||||
// 用户的总粉丝数量
|
// 用户的总粉丝数量
|
||||||
public static final String USER_TOTAL_FOLLOWER_COUNT = "user:totalFollowerCount:";
|
public static final String USER_TOTAL_FOLLOWER_COUNT = "user:totalFollowerCount:";
|
||||||
|
|
||||||
|
// 用户模型
|
||||||
|
public static final String USER_MODEL = "user:model:";
|
||||||
|
//各标签下的视频列表
|
||||||
|
public static final String TAG_BLOGS = "tag:blogs:";
|
||||||
|
public static final String HOT_RANK = "hot:rank:";
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,13 @@ package com.xubx.springboot_01demo.controller;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.xubx.springboot_01demo.dto.blog.AddBlogDto;
|
import com.xubx.springboot_01demo.entity.dto.blog.AddBlogDto;
|
||||||
import com.xubx.springboot_01demo.dto.blog.CollectBlogDto;
|
import com.xubx.springboot_01demo.entity.dto.blog.CollectBlogDto;
|
||||||
import com.xubx.springboot_01demo.dto.blog.GetUserBlogsDto;
|
import com.xubx.springboot_01demo.entity.dto.blog.GetUserBlogsDto;
|
||||||
import com.xubx.springboot_01demo.dto.user.NewFavoritesDto;
|
import com.xubx.springboot_01demo.entity.pojo.Blogs;
|
||||||
import com.xubx.springboot_01demo.pojo.Blogs;
|
import com.xubx.springboot_01demo.entity.vo.HotBlog;
|
||||||
import com.xubx.springboot_01demo.service.BlogService;
|
import com.xubx.springboot_01demo.service.BlogService;
|
||||||
import com.xubx.springboot_01demo.vo.GetBlogDetailVo;
|
import com.xubx.springboot_01demo.entity.vo.GetBlogDetailVo;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
@ -99,6 +99,7 @@ public class BlogsController {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 收藏博客
|
* 收藏博客
|
||||||
|
*
|
||||||
* @param collectBlogDto
|
* @param collectBlogDto
|
||||||
* @return {@link ResponseEntity }<{@link String }>
|
* @return {@link ResponseEntity }<{@link String }>
|
||||||
*/
|
*/
|
||||||
|
@ -137,6 +138,7 @@ public class BlogsController {
|
||||||
try {
|
try {
|
||||||
blogService.addBlogs(blogs);
|
blogService.addBlogs(blogs);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
log.error("博客新增失败", e);
|
||||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("博客新增失败");
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("博客新增失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,9 +169,16 @@ public class BlogsController {
|
||||||
return ResponseEntity.ok("博客删除成功");
|
return ResponseEntity.ok("博客删除成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取该用户的博客列表
|
||||||
|
*
|
||||||
|
* @param getUserBlogsDto
|
||||||
|
* @param bindingResult
|
||||||
|
* @return {@link ResponseEntity }<{@link Page }<{@link Blogs }>>
|
||||||
|
*/
|
||||||
@PostMapping("/getUserBlogs")
|
@PostMapping("/getUserBlogs")
|
||||||
@ApiOperation("获取用户博客")
|
@ApiOperation("获取用户博客")
|
||||||
public ResponseEntity<Page<Blogs>> getUserBlogs(@Valid @RequestBody GetUserBlogsDto getUserBlogsDto, BindingResult bindingResult) {
|
public ResponseEntity<?> getUserBlogs(@Valid @RequestBody GetUserBlogsDto getUserBlogsDto, BindingResult bindingResult) {
|
||||||
log.info("获取用户博客,{}", getUserBlogsDto);
|
log.info("获取用户博客,{}", getUserBlogsDto);
|
||||||
|
|
||||||
if (bindingResult.hasErrors()) {
|
if (bindingResult.hasErrors()) {
|
||||||
|
@ -180,7 +189,42 @@ public class BlogsController {
|
||||||
Page<Blogs> blogs = blogService.findBlogsByUserId(getUserBlogsDto);
|
Page<Blogs> blogs = blogService.findBlogsByUserId(getUserBlogsDto);
|
||||||
return ResponseEntity.ok(blogs);
|
return ResponseEntity.ok(blogs);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
|
log.error("获取用户博客失败", e);
|
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("获取用户博客失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 兴趣推送
|
||||||
|
* @return {@link ResponseEntity }<{@link List }<{@link Blogs }>>
|
||||||
|
*/
|
||||||
|
@GetMapping("/pushBlogs")
|
||||||
|
@ApiOperation("兴趣推送博客")
|
||||||
|
public ResponseEntity<?> pushBlogs() {
|
||||||
|
log.info("兴趣推送博客");
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<Blogs> blogs = blogService.pushBlogs();
|
||||||
|
return ResponseEntity.ok(blogs);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("兴趣推送博客失败", e);
|
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("兴趣推送博客失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取热度排行榜
|
||||||
|
* @return {@link List }<{@link HotBlog }>
|
||||||
|
*/
|
||||||
|
@GetMapping("/listHotRank")
|
||||||
|
public ResponseEntity<?> listHotRank() {
|
||||||
|
log.info("获取热度排行榜");
|
||||||
|
|
||||||
|
try{
|
||||||
|
return ResponseEntity.ok(blogService.listHotRank());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取热度排行榜失败", e);
|
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("获取热度排行榜失败");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package com.xubx.springboot_01demo.controller;
|
package com.xubx.springboot_01demo.controller;
|
||||||
|
|
||||||
import com.xubx.springboot_01demo.pojo.Comment;
|
import com.xubx.springboot_01demo.entity.pojo.Comment;
|
||||||
import com.xubx.springboot_01demo.service.CommentService;
|
import com.xubx.springboot_01demo.service.CommentService;
|
||||||
import com.xubx.springboot_01demo.vo.CommentVo;
|
import com.xubx.springboot_01demo.entity.vo.CommentVo;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import org.springframework.cache.annotation.CacheEvict;
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
|
|
|
@ -1,16 +1,13 @@
|
||||||
package com.xubx.springboot_01demo.controller;
|
package com.xubx.springboot_01demo.controller;
|
||||||
|
|
||||||
import com.xubx.springboot_01demo.dto.SendMesDto;
|
import com.xubx.springboot_01demo.entity.dto.SendMesDto;
|
||||||
import com.xubx.springboot_01demo.service.MessagesService;
|
import com.xubx.springboot_01demo.service.MessagesService;
|
||||||
import com.xubx.springboot_01demo.utils.api.Result;
|
import com.xubx.springboot_01demo.utils.api.Result;
|
||||||
import com.xubx.springboot_01demo.utils.token.RequestHolder;
|
|
||||||
import com.xubx.springboot_01demo.vo.historyMessagesVo;
|
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@RestController //注解标识这是一个控制器类
|
@RestController //注解标识这是一个控制器类
|
||||||
@CrossOrigin //加上CrossOrigin可解决跨域问题
|
@CrossOrigin //加上CrossOrigin可解决跨域问题
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
package com.xubx.springboot_01demo.controller;
|
package com.xubx.springboot_01demo.controller;
|
||||||
|
|
||||||
import com.xubx.springboot_01demo.dto.RelationshipDto;
|
import com.xubx.springboot_01demo.entity.dto.RelationshipDto;
|
||||||
import com.xubx.springboot_01demo.pojo.User;
|
|
||||||
import com.xubx.springboot_01demo.service.RelationshipService;
|
import com.xubx.springboot_01demo.service.RelationshipService;
|
||||||
import com.xubx.springboot_01demo.utils.api.Result;
|
import com.xubx.springboot_01demo.utils.api.Result;
|
||||||
import com.xubx.springboot_01demo.utils.token.RequestHolder;
|
import com.xubx.springboot_01demo.utils.token.RequestHolder;
|
||||||
import com.xubx.springboot_01demo.vo.UserListVo;
|
import com.xubx.springboot_01demo.entity.vo.UserVo;
|
||||||
import com.xubx.springboot_01demo.vo.UserVo;
|
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
|
@ -2,15 +2,14 @@ package com.xubx.springboot_01demo.controller;
|
||||||
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.xubx.springboot_01demo.dto.user.EditMaterialDto;
|
import com.xubx.springboot_01demo.entity.dto.user.EditMaterialDto;
|
||||||
import com.xubx.springboot_01demo.dto.user.NewFavoritesDto;
|
import com.xubx.springboot_01demo.entity.dto.user.NewFavoritesDto;
|
||||||
import com.xubx.springboot_01demo.pojo.Blogs;
|
import com.xubx.springboot_01demo.entity.pojo.Blogs;
|
||||||
import com.xubx.springboot_01demo.pojo.User;
|
import com.xubx.springboot_01demo.entity.pojo.User;
|
||||||
import com.xubx.springboot_01demo.pojo.UserFavorite;
|
import com.xubx.springboot_01demo.entity.pojo.UserFavorite;
|
||||||
import com.xubx.springboot_01demo.service.UserService;
|
import com.xubx.springboot_01demo.service.UserService;
|
||||||
import com.xubx.springboot_01demo.utils.token.RequestHolder;
|
import com.xubx.springboot_01demo.utils.token.RequestHolder;
|
||||||
import com.xubx.springboot_01demo.utils.token.TokenGenerate;
|
import com.xubx.springboot_01demo.entity.vo.getUserInfoVo;
|
||||||
import com.xubx.springboot_01demo.vo.getUserInfoVo;
|
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
@ -18,13 +17,9 @@ import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.validation.BindingResult;
|
import org.springframework.validation.BindingResult;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpSession;
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@RestController //注解标识这是一个控制器类
|
@RestController //注解标识这是一个控制器类
|
||||||
|
@ -193,6 +188,11 @@ public class UserController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改用户资料
|
||||||
|
* @param editMaterialDto
|
||||||
|
* @return {@link ResponseEntity }<{@link String }>
|
||||||
|
*/
|
||||||
@PostMapping("/editMaterial")
|
@PostMapping("/editMaterial")
|
||||||
@ApiOperation("修改用户资料")
|
@ApiOperation("修改用户资料")
|
||||||
public ResponseEntity<String> editMaterial(@RequestBody EditMaterialDto editMaterialDto) {
|
public ResponseEntity<String> editMaterial(@RequestBody EditMaterialDto editMaterialDto) {
|
||||||
|
@ -271,4 +271,78 @@ public class UserController {
|
||||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("根据收藏夹id获取收藏夹内的博客失败");
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("根据收藏夹id获取收藏夹内的博客失败");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户粉丝列表
|
||||||
|
* @param userId
|
||||||
|
* @return {@link ResponseEntity }<{@link ? }>
|
||||||
|
*/
|
||||||
|
@GetMapping("/getUserFans")
|
||||||
|
@ApiOperation("获取用户粉丝列表")
|
||||||
|
public ResponseEntity<?> getUserFans(@RequestParam("userId") String userId) {
|
||||||
|
log.info("获取用户粉丝列表: {}", userId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return ResponseEntity.ok(userService.getUserFans(userId));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取用户粉丝列表失败", e);
|
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("获取用户粉丝列表失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户关注列表
|
||||||
|
* @param userId
|
||||||
|
* @return {@link ResponseEntity }<{@link ? }>
|
||||||
|
*/
|
||||||
|
@GetMapping("/getUserFollowList")
|
||||||
|
@ApiOperation("获取用户关注列表")
|
||||||
|
public ResponseEntity<?> getUserFollowList(@RequestParam("userId") String userId) {
|
||||||
|
log.info("获取用户关注列表: {}", userId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return ResponseEntity.ok(userService.getUserFollowList(userId));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取用户关注列表失败", e);
|
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("获取用户关注列表失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关注/取消关注用户
|
||||||
|
* @param followedId
|
||||||
|
* @return {@link ResponseEntity }<{@link ? }>
|
||||||
|
*/
|
||||||
|
@GetMapping("/followUser")
|
||||||
|
@ApiOperation("关注/取消关注用户")
|
||||||
|
public ResponseEntity<?> followUser(@RequestParam("userId") String followedId) {
|
||||||
|
log.info("关注/取消关注用户: {}", followedId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return ResponseEntity.ok(userService.followUser(followedId));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("关注/取消关注用户失败", e);
|
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("关注/取消关注用户失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户订阅分类,初始化用户模型
|
||||||
|
* @param categories
|
||||||
|
* @return {@link ResponseEntity }<{@link ? }>
|
||||||
|
*/
|
||||||
|
@PostMapping("/subscribe")
|
||||||
|
@ApiOperation("订阅分类")
|
||||||
|
public ResponseEntity<?> subscribe(@RequestBody List<String> categories) {
|
||||||
|
log.info("订阅分类: {}", categories);
|
||||||
|
|
||||||
|
try {
|
||||||
|
userService.subscribe(categories);
|
||||||
|
return ResponseEntity.ok("订阅分类成功");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("订阅分类失败", e);
|
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("订阅分类失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
package com.xubx.springboot_01demo.dto;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用于拼接用户头像
|
|
||||||
*/
|
|
||||||
public class FriendsRequestDto {
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.xubx.springboot_01demo.dto;
|
package com.xubx.springboot_01demo.entity.dto;
|
||||||
|
|
||||||
public class FriendsDto {
|
public class FriendsDto {
|
||||||
private String FriendName;
|
private String FriendName;
|
|
@ -1,4 +1,4 @@
|
||||||
package com.xubx.springboot_01demo.dto;
|
package com.xubx.springboot_01demo.entity.dto;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -1,4 +1,4 @@
|
||||||
package com.xubx.springboot_01demo.dto;
|
package com.xubx.springboot_01demo.entity.dto;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author xubx
|
* @Author xubx
|
|
@ -1,4 +1,4 @@
|
||||||
package com.xubx.springboot_01demo.dto.blog;
|
package com.xubx.springboot_01demo.entity.dto.blog;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
@ -19,12 +19,20 @@ public class AddBlogDto {
|
||||||
@NotBlank
|
@NotBlank
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
@NotBlank
|
/**
|
||||||
private List<String> categories;
|
*标签
|
||||||
|
*/
|
||||||
|
private List<String> tags;
|
||||||
|
|
||||||
@NotBlank
|
@NotBlank
|
||||||
private String content;
|
private String content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*分类id
|
||||||
|
*/
|
||||||
|
@NotBlank
|
||||||
|
private Integer categoryId;
|
||||||
|
|
||||||
private String coverImage;
|
private String coverImage;
|
||||||
|
|
||||||
private String status;
|
private String status;
|
|
@ -1,4 +1,4 @@
|
||||||
package com.xubx.springboot_01demo.dto.blog;
|
package com.xubx.springboot_01demo.entity.dto.blog;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.xubx.springboot_01demo.dto.blog;
|
package com.xubx.springboot_01demo.entity.dto.blog;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.xubx.springboot_01demo.dto.user;
|
package com.xubx.springboot_01demo.entity.dto.user;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.xubx.springboot_01demo.entity.dto.user;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关注 / 取消关注用户实体类
|
||||||
|
* @author Xubx
|
||||||
|
* @date 2024/11/19
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class FollowUserDto {
|
||||||
|
/**
|
||||||
|
*关注者id
|
||||||
|
*/
|
||||||
|
@NotBlank
|
||||||
|
private String followerId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*被关注id
|
||||||
|
*/
|
||||||
|
@NotBlank
|
||||||
|
private String followedId;
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package com.xubx.springboot_01demo.dto.user;
|
package com.xubx.springboot_01demo.entity.dto.user;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.xubx.springboot_01demo.entity.dto.user;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户订阅分类表
|
||||||
|
* @author Xubx
|
||||||
|
* @date 2024/11/22
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class UserSubscription {
|
||||||
|
private Integer userId;
|
||||||
|
|
||||||
|
private Integer categoryId;
|
||||||
|
}
|
|
@ -1,8 +1,7 @@
|
||||||
package com.xubx.springboot_01demo.pojo;
|
package com.xubx.springboot_01demo.entity.pojo;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import io.swagger.annotations.ApiModel;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
|
@ -10,14 +9,13 @@ import java.sql.Timestamp;
|
||||||
@Data
|
@Data
|
||||||
@TableName("blog_like")
|
@TableName("blog_like")
|
||||||
public class BlogLike {
|
public class BlogLike {
|
||||||
@TableField("id")
|
private Long id;
|
||||||
private int id;
|
|
||||||
|
|
||||||
@TableField("blog_id")
|
@TableField("blog_id")
|
||||||
private Integer blogId;
|
private Long blogId;
|
||||||
|
|
||||||
@TableField("user_id")
|
@TableField("user_id")
|
||||||
private Integer userId;
|
private Long userId;
|
||||||
|
|
||||||
@TableField("created_time")
|
@TableField("created_time")
|
||||||
private Timestamp createdTime;
|
private Timestamp createdTime;
|
|
@ -1,4 +1,4 @@
|
||||||
package com.xubx.springboot_01demo.pojo;
|
package com.xubx.springboot_01demo.entity.pojo;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
@ -36,6 +36,9 @@ public class Blogs implements Serializable {
|
||||||
@ApiModelProperty(value = "内容")
|
@ApiModelProperty(value = "内容")
|
||||||
private String content;
|
private String content;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "分类id")
|
||||||
|
private Integer categoryId;
|
||||||
|
|
||||||
@ApiModelProperty(value = "封面图片")
|
@ApiModelProperty(value = "封面图片")
|
||||||
private String coverImage;
|
private String coverImage;
|
||||||
|
|
||||||
|
@ -43,19 +46,19 @@ public class Blogs implements Serializable {
|
||||||
private Integer authorId;
|
private Integer authorId;
|
||||||
|
|
||||||
@ApiModelProperty(value = "点赞数")
|
@ApiModelProperty(value = "点赞数")
|
||||||
private int likeCount;
|
private Long likeCount;
|
||||||
|
|
||||||
@ApiModelProperty(value = "浏览数")
|
@ApiModelProperty(value = "浏览数")
|
||||||
private int viewCount;
|
private Long viewCount;
|
||||||
|
|
||||||
@ApiModelProperty(value = "评论数")
|
@ApiModelProperty(value = "评论数")
|
||||||
private int commentCount;
|
private Long commentCount;
|
||||||
|
|
||||||
@ApiModelProperty(value = "收藏数")
|
@ApiModelProperty(value = "收藏数")
|
||||||
private int collectCount;
|
private Long collectCount;
|
||||||
|
|
||||||
@ApiModelProperty(value = "分享数")
|
@ApiModelProperty(value = "分享数")
|
||||||
private int shareCount;
|
private Long shareCount;
|
||||||
|
|
||||||
@ApiModelProperty(value = "状态")
|
@ApiModelProperty(value = "状态")
|
||||||
private String status;
|
private String status;
|
|
@ -1,9 +1,6 @@
|
||||||
package com.xubx.springboot_01demo.pojo;
|
package com.xubx.springboot_01demo.entity.pojo;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.sql.Date;
|
|
||||||
import java.sql.Time;
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 评论实体类
|
* 评论实体类
|
|
@ -1,10 +1,10 @@
|
||||||
package com.xubx.springboot_01demo.pojo;
|
package com.xubx.springboot_01demo.entity.pojo;
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
public class Messages {
|
public class Messages {
|
||||||
|
|
||||||
private int id;
|
private Integer id;
|
||||||
/**发送人*/
|
/**发送人*/
|
||||||
private String sender;
|
private String sender;
|
||||||
/**接收人*/
|
/**接收人*/
|
|
@ -1,4 +1,4 @@
|
||||||
package com.xubx.springboot_01demo.pojo;
|
package com.xubx.springboot_01demo.entity.pojo;
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.xubx.springboot_01demo.entity.pojo;
|
||||||
|
|
||||||
|
import com.xubx.springboot_01demo.entity.vo.HotBlog;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Xubx
|
||||||
|
* @date 2024/12/02
|
||||||
|
*/
|
||||||
|
public class TopK {
|
||||||
|
private int k = 0;
|
||||||
|
private PriorityQueue<HotBlog> queue;
|
||||||
|
|
||||||
|
public TopK(int k) {
|
||||||
|
this.k = k;
|
||||||
|
// 使用一个最大堆,根据热度从大到小排序
|
||||||
|
this.queue = new PriorityQueue<>((hv1, hv2) -> Double.compare(hv1.getHot(), hv2.getHot()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向TopK队列中添加一个HotVideo对象
|
||||||
|
* @param hotBlog 热度视频
|
||||||
|
*/
|
||||||
|
public void add(HotBlog hotBlog) {
|
||||||
|
if (queue.size() < k) {
|
||||||
|
queue.add(hotBlog);
|
||||||
|
} else if (queue.peek().getHot() < hotBlog.getHot()) {
|
||||||
|
queue.poll(); // 移除最小的热度
|
||||||
|
queue.add(hotBlog); // 添加新的HotVideo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取排序后的TopK视频列表
|
||||||
|
* @return 按热度降序排列的视频列表
|
||||||
|
*/
|
||||||
|
public List<HotBlog> get() {
|
||||||
|
// 转换为List并按热度降序排序
|
||||||
|
List<HotBlog> list = new ArrayList<>(queue);
|
||||||
|
// 由于PriorityQueue是小根堆,需要手动倒序排列
|
||||||
|
Collections.reverse(list);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package com.xubx.springboot_01demo.pojo;
|
package com.xubx.springboot_01demo.entity.pojo;
|
||||||
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
|
@ -1,4 +1,4 @@
|
||||||
package com.xubx.springboot_01demo.pojo;
|
package com.xubx.springboot_01demo.entity.pojo;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
@ -13,7 +13,7 @@ import java.sql.Timestamp;
|
||||||
@ApiModel(value = "UserFavorite", description = "用户收藏")
|
@ApiModel(value = "UserFavorite", description = "用户收藏")
|
||||||
@TableName("user_favorite")
|
@TableName("user_favorite")
|
||||||
public class UserFavorite implements Serializable {
|
public class UserFavorite implements Serializable {
|
||||||
private int id;
|
private Integer id;
|
||||||
|
|
||||||
@TableField("name")
|
@TableField("name")
|
||||||
@ApiModelProperty(value = "收藏名称")
|
@ApiModelProperty(value = "收藏名称")
|
|
@ -1,4 +1,4 @@
|
||||||
package com.xubx.springboot_01demo.pojo;
|
package com.xubx.springboot_01demo.entity.pojo;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
@ -9,7 +9,7 @@ import lombok.Data;
|
||||||
@ApiModel(value = "UserFavorite", description = "用户收藏夹博客中间表")
|
@ApiModel(value = "UserFavorite", description = "用户收藏夹博客中间表")
|
||||||
@TableName("user_favorite_blog")
|
@TableName("user_favorite_blog")
|
||||||
public class UserFavoriteBlog {
|
public class UserFavoriteBlog {
|
||||||
private int id;
|
private Integer id;
|
||||||
|
|
||||||
@TableField("favorite_id")
|
@TableField("favorite_id")
|
||||||
private Integer favoriteId;
|
private Integer favoriteId;
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.xubx.springboot_01demo.entity.pojo;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@ApiModel(value = "UserFollow", description = "用户关注粉丝")
|
||||||
|
@TableName("user_follow")
|
||||||
|
public class UserFollow {
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
@TableField("follower_id")
|
||||||
|
private Integer followerId;
|
||||||
|
|
||||||
|
@TableField("followed_id")
|
||||||
|
private Integer followedId;
|
||||||
|
|
||||||
|
@TableField("created_time")
|
||||||
|
@ApiModelProperty(value = "创建时间")
|
||||||
|
private Timestamp createdTime;
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package com.xubx.springboot_01demo.vo;
|
package com.xubx.springboot_01demo.entity.vo;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.xubx.springboot_01demo.vo;
|
package com.xubx.springboot_01demo.entity.vo;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
|
@ -0,0 +1,65 @@
|
||||||
|
package com.xubx.springboot_01demo.entity.vo;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Xubx
|
||||||
|
* @date 2024/12/02
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@ToString
|
||||||
|
public class HotBlog implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private String hotFormat; // 格式化后的热度字符串(例如:500.0万)
|
||||||
|
private Double hot; // 视频的热度数值
|
||||||
|
private Integer blogId; // 视频ID
|
||||||
|
private String title; // 视频标题
|
||||||
|
|
||||||
|
public HotBlog(Integer blogId, Double hot, String title){
|
||||||
|
this.blogId = blogId;
|
||||||
|
this.hot = hot;
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化热度值为 "X万" 形式,例如 5000000 -> "500.0万"
|
||||||
|
*/
|
||||||
|
public void formatHot() {
|
||||||
|
if (hot != null) {
|
||||||
|
// 使用 BigDecimal 处理精度问题,避免浮动误差
|
||||||
|
BigDecimal bigDecimal = new BigDecimal(hot);
|
||||||
|
BigDecimal decimal = bigDecimal.divide(new BigDecimal("10000"), 1, RoundingMode.HALF_UP); // 除以10000并保留一位小数
|
||||||
|
this.hotFormat = String.format("%.1f万", decimal.doubleValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重写 equals() 方法,根据 videoId 和 title 判断对象是否相等
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
HotBlog hotBlog = (HotBlog) o;
|
||||||
|
return Objects.equals(blogId, hotBlog.blogId) && Objects.equals(title, hotBlog.title);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重写 hashCode() 方法,根据 videoId 和 title 生成唯一的哈希值
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(blogId, title);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package com.xubx.springboot_01demo.vo;
|
package com.xubx.springboot_01demo.entity.vo;
|
||||||
|
|
||||||
public class UserListVo {
|
public class UserListVo {
|
||||||
/**
|
/**
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.xubx.springboot_01demo.entity.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class UserModelVo {
|
||||||
|
private Integer userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*订阅的标签
|
||||||
|
*/
|
||||||
|
private List<String> lableNames;
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package com.xubx.springboot_01demo.vo;
|
package com.xubx.springboot_01demo.entity.vo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*用于屏蔽用户密码
|
*用于屏蔽用户密码
|
|
@ -1,4 +1,4 @@
|
||||||
package com.xubx.springboot_01demo.vo;
|
package com.xubx.springboot_01demo.entity.vo;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
|
@ -1,4 +1,4 @@
|
||||||
package com.xubx.springboot_01demo.vo;
|
package com.xubx.springboot_01demo.entity.vo;
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
package com.xubx.springboot_01demo.mapper;
|
package com.xubx.springboot_01demo.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.xubx.springboot_01demo.pojo.BlogLike;
|
import com.xubx.springboot_01demo.entity.pojo.BlogLike;
|
||||||
|
|
||||||
public interface BlogLikeMapper extends BaseMapper<BlogLike> {
|
public interface BlogLikeMapper extends BaseMapper<BlogLike> {
|
||||||
|
void addData(BlogLike newBlogLike);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package com.xubx.springboot_01demo.mapper;
|
package com.xubx.springboot_01demo.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.xubx.springboot_01demo.dto.blog.AddBlogDto;
|
import com.xubx.springboot_01demo.entity.dto.blog.AddBlogDto;
|
||||||
import com.xubx.springboot_01demo.dto.blog.CollectBlogDto;
|
import com.xubx.springboot_01demo.entity.dto.blog.CollectBlogDto;
|
||||||
import com.xubx.springboot_01demo.pojo.Blogs;
|
import com.xubx.springboot_01demo.entity.pojo.Blogs;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -20,11 +20,11 @@ public interface BlogsMapper extends BaseMapper<Blogs> {
|
||||||
void deleteBlogs(int id);
|
void deleteBlogs(int id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 插入博客分类中间表
|
* 插入博客标签中间表
|
||||||
* @param blogId
|
* @param blogId
|
||||||
* @param categoryId
|
* @param tagId
|
||||||
*/
|
*/
|
||||||
void insertCategory(int blogId, String categoryId);
|
void insertTags(int blogId, String tagId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取该用户总访问量
|
* 获取该用户总访问量
|
||||||
|
@ -126,4 +126,6 @@ public interface BlogsMapper extends BaseMapper<Blogs> {
|
||||||
* @return {@link List }<{@link String }>
|
* @return {@link List }<{@link String }>
|
||||||
*/
|
*/
|
||||||
List<String> getUserIdsByBlogId(String blogId);
|
List<String> getUserIdsByBlogId(String blogId);
|
||||||
|
|
||||||
|
List<String> getTagsByBlogId(Integer blogId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package com.xubx.springboot_01demo.mapper;
|
package com.xubx.springboot_01demo.mapper;
|
||||||
|
|
||||||
import com.xubx.springboot_01demo.pojo.Comment;
|
import com.xubx.springboot_01demo.entity.pojo.Comment;
|
||||||
import com.xubx.springboot_01demo.vo.CommentVo;
|
import com.xubx.springboot_01demo.entity.vo.CommentVo;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package com.xubx.springboot_01demo.mapper;
|
package com.xubx.springboot_01demo.mapper;
|
||||||
|
|
||||||
import com.xubx.springboot_01demo.pojo.Messages;
|
import com.xubx.springboot_01demo.entity.pojo.Messages;
|
||||||
import com.xubx.springboot_01demo.vo.historyMessagesVo;
|
import com.xubx.springboot_01demo.entity.vo.historyMessagesVo;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package com.xubx.springboot_01demo.mapper;
|
package com.xubx.springboot_01demo.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.xubx.springboot_01demo.pojo.Relationship;
|
import com.xubx.springboot_01demo.entity.pojo.Relationship;
|
||||||
import com.xubx.springboot_01demo.pojo.User;
|
import com.xubx.springboot_01demo.entity.pojo.User;
|
||||||
import com.xubx.springboot_01demo.vo.UserListVo;
|
import com.xubx.springboot_01demo.entity.vo.UserListVo;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package com.xubx.springboot_01demo.mapper;
|
package com.xubx.springboot_01demo.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.xubx.springboot_01demo.pojo.UserFavoriteBlog;
|
import com.xubx.springboot_01demo.entity.pojo.UserFavoriteBlog;
|
||||||
|
|
||||||
public interface UserFavoriteBlogMapper extends BaseMapper<UserFavoriteBlog> {
|
public interface UserFavoriteBlogMapper extends BaseMapper<UserFavoriteBlog> {
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package com.xubx.springboot_01demo.mapper;
|
package com.xubx.springboot_01demo.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.xubx.springboot_01demo.pojo.UserFavorite;
|
import com.xubx.springboot_01demo.entity.pojo.UserFavorite;
|
||||||
|
|
||||||
public interface UserFavoriteMapper extends BaseMapper<UserFavorite> {
|
public interface UserFavoriteMapper extends BaseMapper<UserFavorite> {
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.xubx.springboot_01demo.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.xubx.springboot_01demo.entity.pojo.UserFollow;
|
||||||
|
|
||||||
|
public interface UserFollowMapper extends BaseMapper<UserFollow> {
|
||||||
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
package com.xubx.springboot_01demo.mapper;
|
package com.xubx.springboot_01demo.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.xubx.springboot_01demo.pojo.User;
|
import com.xubx.springboot_01demo.entity.pojo.User;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface UserMapper extends BaseMapper<User> {
|
public interface UserMapper extends BaseMapper<User> {
|
||||||
//2.添加用户接口
|
//2.添加用户接口
|
||||||
|
@ -18,4 +20,9 @@ public interface UserMapper extends BaseMapper<User> {
|
||||||
String getPasswordByname(String username);
|
String getPasswordByname(String username);
|
||||||
|
|
||||||
|
|
||||||
|
List<User> getUserFans(String userId);
|
||||||
|
|
||||||
|
List<User> getUserFollowList(String userId);
|
||||||
|
|
||||||
|
Object subscribe(Integer currentUserId, List<String> categories);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.xubx.springboot_01demo.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.xubx.springboot_01demo.entity.dto.user.UserSubscription;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface UserSubscriptionMapper extends BaseMapper<UserSubscription> {
|
||||||
|
List<String> gettagsByCategoryId(Integer categoryId);
|
||||||
|
}
|
|
@ -1,17 +1,19 @@
|
||||||
package com.xubx.springboot_01demo.service;
|
package com.xubx.springboot_01demo.service;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.xubx.springboot_01demo.dto.blog.AddBlogDto;
|
import com.xubx.springboot_01demo.entity.dto.blog.AddBlogDto;
|
||||||
import com.xubx.springboot_01demo.dto.blog.CollectBlogDto;
|
import com.xubx.springboot_01demo.entity.dto.blog.CollectBlogDto;
|
||||||
import com.xubx.springboot_01demo.dto.blog.GetUserBlogsDto;
|
import com.xubx.springboot_01demo.entity.dto.blog.GetUserBlogsDto;
|
||||||
import com.xubx.springboot_01demo.dto.user.NewFavoritesDto;
|
import com.xubx.springboot_01demo.entity.pojo.Blogs;
|
||||||
import com.xubx.springboot_01demo.pojo.Blogs;
|
import com.xubx.springboot_01demo.entity.vo.GetBlogDetailVo;
|
||||||
import com.xubx.springboot_01demo.vo.GetBlogDetailVo;
|
import com.xubx.springboot_01demo.entity.vo.HotBlog;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface BlogService {
|
public interface BlogService extends IService<Blogs> {
|
||||||
//获取所有博客
|
//获取所有博客
|
||||||
List<Blogs> findAllBlogs();
|
List<Blogs> findAllBlogs();
|
||||||
|
|
||||||
|
@ -24,12 +26,37 @@ public interface BlogService {
|
||||||
//删除博客
|
//删除博客
|
||||||
void deleteBlogs(int id);
|
void deleteBlogs(int id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查看某个用户的所有博客
|
||||||
|
* @param getUserBlogsDto
|
||||||
|
* @return {@link Page }<{@link Blogs }>
|
||||||
|
*/
|
||||||
Page<Blogs> findBlogsByUserId(GetUserBlogsDto getUserBlogsDto);
|
Page<Blogs> findBlogsByUserId(GetUserBlogsDto getUserBlogsDto);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 浏览博客
|
||||||
|
* @param blogId
|
||||||
|
*/
|
||||||
void viewBlog(int blogId);
|
void viewBlog(int blogId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点赞博客
|
||||||
|
* @param blogId
|
||||||
|
*/
|
||||||
void likeBlog(int blogId);
|
void likeBlog(int blogId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 收藏博客
|
||||||
|
* @param collectBlogDto
|
||||||
|
* @throws JsonProcessingException
|
||||||
|
*/
|
||||||
void collectBlog(CollectBlogDto collectBlogDto) throws JsonProcessingException;
|
void collectBlog(CollectBlogDto collectBlogDto) throws JsonProcessingException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主页兴趣推送 -> 推荐
|
||||||
|
* @return {@link List }<{@link Blogs }>
|
||||||
|
*/
|
||||||
|
List<Blogs> pushBlogs();
|
||||||
|
|
||||||
|
List<HotBlog> listHotRank();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package com.xubx.springboot_01demo.service;
|
package com.xubx.springboot_01demo.service;
|
||||||
|
|
||||||
import com.xubx.springboot_01demo.pojo.Comment;
|
import com.xubx.springboot_01demo.entity.pojo.Comment;
|
||||||
import com.xubx.springboot_01demo.vo.CommentVo;
|
import com.xubx.springboot_01demo.entity.vo.CommentVo;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.xubx.springboot_01demo.service;
|
||||||
|
|
||||||
|
import com.xubx.springboot_01demo.entity.pojo.User;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 兴趣推送
|
||||||
|
* @author Xubx
|
||||||
|
* @date 2024/11/22
|
||||||
|
*/
|
||||||
|
public interface InterestPushService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化用户模型 --> 订阅分类
|
||||||
|
* @param userId
|
||||||
|
* @param tags
|
||||||
|
*/
|
||||||
|
void initUserModel(Integer userId, List<String> tags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户模型修改概率 : 可分批次发送
|
||||||
|
* 修改场景:
|
||||||
|
* 1.观看浏览量到达总时长1/5 +0.5概率
|
||||||
|
* 2.观看浏览量未到总时长1/5 -0.5概率
|
||||||
|
* 3.点赞视频 +1概率
|
||||||
|
* 4.收藏视频 +2概率
|
||||||
|
*/
|
||||||
|
void updateUserModel(Integer userId, Integer blogId, Double score);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*根据用户模型推送博客 -> 兴趣推送
|
||||||
|
* @param user
|
||||||
|
* @return {@link List }<{@link String }>
|
||||||
|
*/
|
||||||
|
List<String> listBlogsByUserModel(User user);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推入系统标签库
|
||||||
|
*
|
||||||
|
* @param bligId
|
||||||
|
* @param tags
|
||||||
|
*/
|
||||||
|
void pushTagsStockIn(Integer bligId, List<String> tags);
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
package com.xubx.springboot_01demo.service;
|
package com.xubx.springboot_01demo.service;
|
||||||
|
|
||||||
import com.xubx.springboot_01demo.dto.SendMesDto;
|
import com.xubx.springboot_01demo.entity.dto.SendMesDto;
|
||||||
import com.xubx.springboot_01demo.vo.historyMessagesVo;
|
import com.xubx.springboot_01demo.entity.vo.historyMessagesVo;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
package com.xubx.springboot_01demo.service;
|
package com.xubx.springboot_01demo.service;
|
||||||
|
|
||||||
import com.xubx.springboot_01demo.pojo.User;
|
import com.xubx.springboot_01demo.entity.vo.UserListVo;
|
||||||
import com.xubx.springboot_01demo.vo.UserListVo;
|
import com.xubx.springboot_01demo.entity.vo.UserVo;
|
||||||
import com.xubx.springboot_01demo.vo.UserVo;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,12 @@ package com.xubx.springboot_01demo.service;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.xubx.springboot_01demo.dto.user.EditMaterialDto;
|
import com.xubx.springboot_01demo.entity.dto.user.EditMaterialDto;
|
||||||
import com.xubx.springboot_01demo.dto.user.NewFavoritesDto;
|
import com.xubx.springboot_01demo.entity.dto.user.NewFavoritesDto;
|
||||||
import com.xubx.springboot_01demo.pojo.Blogs;
|
import com.xubx.springboot_01demo.entity.pojo.Blogs;
|
||||||
import com.xubx.springboot_01demo.pojo.User;
|
import com.xubx.springboot_01demo.entity.pojo.User;
|
||||||
import com.xubx.springboot_01demo.pojo.UserFavorite;
|
import com.xubx.springboot_01demo.entity.pojo.UserFavorite;
|
||||||
import com.xubx.springboot_01demo.vo.getUserInfoVo;
|
import com.xubx.springboot_01demo.entity.vo.getUserInfoVo;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -55,4 +55,32 @@ public interface UserService {
|
||||||
* @return {@link List }<{@link Blogs }>
|
* @return {@link List }<{@link Blogs }>
|
||||||
*/
|
*/
|
||||||
List<Blogs> getBlogsByFavoriteId(String favoriteId) throws JsonProcessingException;
|
List<Blogs> getBlogsByFavoriteId(String favoriteId) throws JsonProcessingException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户的粉丝列表
|
||||||
|
* @param userId
|
||||||
|
* @return {@link List }<{@link User }>
|
||||||
|
*/
|
||||||
|
List<User> getUserFans(String userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户关注列表
|
||||||
|
* @param userId
|
||||||
|
* @return {@link List }<{@link User }>
|
||||||
|
*/
|
||||||
|
List<User> getUserFollowList(String userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关注 / 取关用户
|
||||||
|
* @param followedId
|
||||||
|
* @return {@link Object }
|
||||||
|
*/
|
||||||
|
Object followUser(String followedId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅分类
|
||||||
|
* @param categories
|
||||||
|
* @return {@link Object }
|
||||||
|
*/
|
||||||
|
void subscribe(List<String> categories);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.xubx.springboot_01demo.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.xubx.springboot_01demo.entity.dto.user.UserSubscription;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*用户订阅分类
|
||||||
|
* @author Xubx
|
||||||
|
* @date 2024/11/22
|
||||||
|
*/
|
||||||
|
public interface UserSubscriptionService extends IService<UserSubscription> {
|
||||||
|
List<String> gettagsByCategoryId(Integer categoryId);
|
||||||
|
}
|
|
@ -2,35 +2,42 @@ package com.xubx.springboot_01demo.service.impl;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.xubx.springboot_01demo.configuration.constantConfiguration;
|
import com.xubx.springboot_01demo.configuration.constantConfiguration;
|
||||||
import com.xubx.springboot_01demo.dto.blog.AddBlogDto;
|
import com.xubx.springboot_01demo.entity.dto.blog.AddBlogDto;
|
||||||
import com.xubx.springboot_01demo.dto.blog.CollectBlogDto;
|
import com.xubx.springboot_01demo.entity.dto.blog.CollectBlogDto;
|
||||||
import com.xubx.springboot_01demo.dto.blog.GetUserBlogsDto;
|
import com.xubx.springboot_01demo.entity.dto.blog.GetUserBlogsDto;
|
||||||
|
import com.xubx.springboot_01demo.entity.vo.HotBlog;
|
||||||
import com.xubx.springboot_01demo.mapper.BlogsMapper;
|
import com.xubx.springboot_01demo.mapper.BlogsMapper;
|
||||||
import com.xubx.springboot_01demo.pojo.Blogs;
|
import com.xubx.springboot_01demo.entity.pojo.Blogs;
|
||||||
import com.xubx.springboot_01demo.pojo.User;
|
import com.xubx.springboot_01demo.entity.pojo.User;
|
||||||
import com.xubx.springboot_01demo.service.BlogService;
|
import com.xubx.springboot_01demo.service.BlogService;
|
||||||
|
import com.xubx.springboot_01demo.service.InterestPushService;
|
||||||
import com.xubx.springboot_01demo.service.UserService;
|
import com.xubx.springboot_01demo.service.UserService;
|
||||||
import com.xubx.springboot_01demo.utils.token.RequestHolder;
|
import com.xubx.springboot_01demo.utils.token.RequestHolder;
|
||||||
import com.xubx.springboot_01demo.vo.GetBlogDetailVo;
|
import com.xubx.springboot_01demo.entity.vo.GetBlogDetailVo;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.BeanUtils;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.data.redis.core.ZSetOperations;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class BlogsServiceImpl implements BlogService {
|
public class BlogsServiceImpl extends ServiceImpl<BlogsMapper, Blogs> implements BlogService {
|
||||||
@Resource
|
@Resource
|
||||||
BlogsMapper blogsMapper;
|
BlogsMapper blogsMapper;
|
||||||
|
|
||||||
|
@ -47,6 +54,8 @@ public class BlogsServiceImpl implements BlogService {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
ObjectMapper objectMapper;
|
ObjectMapper objectMapper;
|
||||||
|
@Autowired
|
||||||
|
InterestPushService interestPushService;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -157,15 +166,18 @@ public class BlogsServiceImpl implements BlogService {
|
||||||
blog.setDescription(blogDto.getDescription());
|
blog.setDescription(blogDto.getDescription());
|
||||||
blog.setContent(blogDto.getContent());
|
blog.setContent(blogDto.getContent());
|
||||||
blog.setCoverImage(blogDto.getCoverImage());
|
blog.setCoverImage(blogDto.getCoverImage());
|
||||||
|
blog.setCategoryId(blogDto.getCategoryId());
|
||||||
blog.setStatus(blogDto.getStatus());
|
blog.setStatus(blogDto.getStatus());
|
||||||
blog.setAuthorId(RequestHolder.getuserId());
|
blog.setAuthorId(RequestHolder.getuserId());
|
||||||
// TODO 后续改为AOP切面统一进行创建、更新时间的插入
|
// TODO 后续改为AOP切面统一进行创建、更新时间的插入
|
||||||
blog.setCreatedTime(Timestamp.valueOf(now));
|
blog.setCreatedTime(Timestamp.valueOf(now));
|
||||||
blogsMapper.insert(blog);
|
blogsMapper.insert(blog);
|
||||||
// 插入博客分类中间表
|
// 插入博客标签中间表
|
||||||
blogDto.getCategories().forEach(category -> {
|
blogDto.getTags().forEach(tag -> {
|
||||||
blogsMapper.insertCategory(blog.getId(), category);
|
blogsMapper.insertTags(blog.getId(), tag);
|
||||||
});
|
});
|
||||||
|
// 插入系统标签库
|
||||||
|
interestPushService.pushTagsStockIn(blog.getId(), blogDto.getTags());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -266,6 +278,9 @@ public class BlogsServiceImpl implements BlogService {
|
||||||
redisTemplate.opsForValue().increment(likeCountKey);
|
redisTemplate.opsForValue().increment(likeCountKey);
|
||||||
redisTemplate.opsForHash().put(likeUserHashKey, userId, "true");
|
redisTemplate.opsForHash().put(likeUserHashKey, userId, "true");
|
||||||
|
|
||||||
|
//更新用户模型
|
||||||
|
interestPushService.updateUserModel(Integer.valueOf(userId), blogId, 1.0);
|
||||||
|
|
||||||
// 设置过期时间仅在首次操作集合时
|
// 设置过期时间仅在首次操作集合时
|
||||||
if (!Boolean.TRUE.equals(redisTemplate.hasKey(likeCountExpireKey))) {
|
if (!Boolean.TRUE.equals(redisTemplate.hasKey(likeCountExpireKey))) {
|
||||||
redisTemplate.opsForValue().set(likeCountExpireKey, "true", 25, TimeUnit.HOURS);
|
redisTemplate.opsForValue().set(likeCountExpireKey, "true", 25, TimeUnit.HOURS);
|
||||||
|
@ -278,6 +293,9 @@ public class BlogsServiceImpl implements BlogService {
|
||||||
redisTemplate.opsForValue().decrement(likeCountKey);
|
redisTemplate.opsForValue().decrement(likeCountKey);
|
||||||
redisTemplate.opsForHash().put(likeUserHashKey, userId, "false");
|
redisTemplate.opsForHash().put(likeUserHashKey, userId, "false");
|
||||||
|
|
||||||
|
//更新用户模型
|
||||||
|
interestPushService.updateUserModel(Integer.valueOf(userId), blogId, -1.0);
|
||||||
|
|
||||||
// 设置逻辑过期标志,以确保下次同步到数据库
|
// 设置逻辑过期标志,以确保下次同步到数据库
|
||||||
if (!Boolean.TRUE.equals(redisTemplate.hasKey(likeCountExpireKey))) {
|
if (!Boolean.TRUE.equals(redisTemplate.hasKey(likeCountExpireKey))) {
|
||||||
redisTemplate.opsForValue().set(likeCountExpireKey, "true", 25, TimeUnit.HOURS);
|
redisTemplate.opsForValue().set(likeCountExpireKey, "true", 25, TimeUnit.HOURS);
|
||||||
|
@ -326,6 +344,9 @@ public class BlogsServiceImpl implements BlogService {
|
||||||
// 将收藏的博客缓存到用户收藏夹的博客列表中
|
// 将收藏的博客缓存到用户收藏夹的博客列表中
|
||||||
redisTemplate.opsForHash().put(blogCollectBlogsHashKey, blogId, "true");
|
redisTemplate.opsForHash().put(blogCollectBlogsHashKey, blogId, "true");
|
||||||
|
|
||||||
|
//更新用户模型
|
||||||
|
interestPushService.updateUserModel(Integer.valueOf(userId), collectBlogDto.getBlogId(), 2.0);
|
||||||
|
|
||||||
// 设置逻辑过期时间 确保能同步到数据中
|
// 设置逻辑过期时间 确保能同步到数据中
|
||||||
if (!Boolean.TRUE.equals(redisTemplate.hasKey(collectCountExpireKey))) {
|
if (!Boolean.TRUE.equals(redisTemplate.hasKey(collectCountExpireKey))) {
|
||||||
redisTemplate.opsForValue().set(collectCountExpireKey, "true", 23, TimeUnit.HOURS);
|
redisTemplate.opsForValue().set(collectCountExpireKey, "true", 23, TimeUnit.HOURS);
|
||||||
|
@ -339,6 +360,9 @@ public class BlogsServiceImpl implements BlogService {
|
||||||
redisTemplate.opsForValue().decrement(collectCountKey);
|
redisTemplate.opsForValue().decrement(collectCountKey);
|
||||||
redisTemplate.opsForHash().put(blogCollectBlogsHashKey, blogId, "false");
|
redisTemplate.opsForHash().put(blogCollectBlogsHashKey, blogId, "false");
|
||||||
|
|
||||||
|
//更新用户模型
|
||||||
|
interestPushService.updateUserModel(Integer.valueOf(userId), collectBlogDto.getBlogId(), -2.0);
|
||||||
|
|
||||||
// 设置逻辑过期时间 确保能同步到数据中
|
// 设置逻辑过期时间 确保能同步到数据中
|
||||||
if (!Boolean.TRUE.equals(redisTemplate.hasKey(collectCountExpireKey))) {
|
if (!Boolean.TRUE.equals(redisTemplate.hasKey(collectCountExpireKey))) {
|
||||||
redisTemplate.opsForValue().set(collectCountExpireKey, "true", 23, TimeUnit.HOURS);
|
redisTemplate.opsForValue().set(collectCountExpireKey, "true", 23, TimeUnit.HOURS);
|
||||||
|
@ -355,4 +379,52 @@ public class BlogsServiceImpl implements BlogService {
|
||||||
log.warn("无法获取分布式锁,用户 {} 收藏博客 {} 操作被跳过", userId, blogId);
|
log.warn("无法获取分布式锁,用户 {} 收藏博客 {} 操作被跳过", userId, blogId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 兴趣推送博客
|
||||||
|
*
|
||||||
|
* @return {@link List }<{@link Blogs }>
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<Blogs> pushBlogs() {
|
||||||
|
Integer userId = RequestHolder.getuserId();
|
||||||
|
User user = null;
|
||||||
|
if (userId != null) {
|
||||||
|
user = userService.getUser(String.valueOf(userId));
|
||||||
|
}
|
||||||
|
List<String> blogIds = interestPushService.listBlogsByUserModel(user);
|
||||||
|
List<Blogs> blogs = new ArrayList<>();
|
||||||
|
|
||||||
|
// 如果该用户没有兴趣模型,默认给最新的十条博客
|
||||||
|
if (ObjectUtils.isEmpty(blogIds)) {
|
||||||
|
blogIds = list(new LambdaQueryWrapper<Blogs>().orderByDesc(Blogs::getCreatedTime)).stream().map(Blogs::getId).map(String::valueOf).collect(Collectors.toList());
|
||||||
|
blogIds = blogIds.subList(0, Math.min(10, blogIds.size()));
|
||||||
|
}
|
||||||
|
blogs = listByIds(blogIds);
|
||||||
|
return blogs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取热度排行榜
|
||||||
|
*
|
||||||
|
* @return {@link List }<{@link HotBlog }>
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<HotBlog> listHotRank() {
|
||||||
|
final Set<ZSetOperations.TypedTuple<Object>> zSet = redisTemplate.opsForZSet().reverseRangeWithScores(constantConfiguration.HOT_RANK, 0, -1);
|
||||||
|
final List<HotBlog> hotBlogs = new ArrayList<>();
|
||||||
|
|
||||||
|
for (ZSetOperations.TypedTuple<Object> objectTypedTuple : zSet) {
|
||||||
|
final HotBlog hotBlog;
|
||||||
|
try {
|
||||||
|
hotBlog = objectMapper.readValue(objectTypedTuple.getValue().toString(), HotBlog.class);
|
||||||
|
hotBlog.setHot(objectTypedTuple.getScore());
|
||||||
|
hotBlog.formatHot();
|
||||||
|
hotBlogs.add(hotBlog);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
log.error("解析热度排行榜失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hotBlogs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
package com.xubx.springboot_01demo.service.impl;
|
package com.xubx.springboot_01demo.service.impl;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.util.BeanUtil;
|
|
||||||
import com.xubx.springboot_01demo.controller.UserController;
|
|
||||||
import com.xubx.springboot_01demo.mapper.CommentMapper;
|
import com.xubx.springboot_01demo.mapper.CommentMapper;
|
||||||
import com.xubx.springboot_01demo.pojo.Comment;
|
import com.xubx.springboot_01demo.entity.pojo.Comment;
|
||||||
import com.xubx.springboot_01demo.service.CommentService;
|
import com.xubx.springboot_01demo.service.CommentService;
|
||||||
import com.xubx.springboot_01demo.service.UserService;
|
import com.xubx.springboot_01demo.service.UserService;
|
||||||
import com.xubx.springboot_01demo.utils.token.RequestHolder;
|
import com.xubx.springboot_01demo.entity.vo.CommentVo;
|
||||||
import com.xubx.springboot_01demo.vo.CommentVo;
|
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,189 @@
|
||||||
|
package com.xubx.springboot_01demo.service.impl;
|
||||||
|
|
||||||
|
import com.xubx.springboot_01demo.configuration.constantConfiguration;
|
||||||
|
import com.xubx.springboot_01demo.mapper.BlogsMapper;
|
||||||
|
import com.xubx.springboot_01demo.entity.pojo.User;
|
||||||
|
import com.xubx.springboot_01demo.service.InterestPushService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.RedisCallback;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 兴趣推送
|
||||||
|
*
|
||||||
|
* @author Xubx
|
||||||
|
* @date 2024/11/22
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class InterestPushServiceImpl implements InterestPushService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisTemplate redisTemplate;
|
||||||
|
@Resource
|
||||||
|
private BlogsMapper blogsMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化用户模型
|
||||||
|
*
|
||||||
|
* @param userId
|
||||||
|
* @param tags
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Async("asyncExecutor")
|
||||||
|
public void initUserModel(Integer userId, List<String> tags) {
|
||||||
|
String userModelKey = constantConfiguration.USER_MODEL + userId;
|
||||||
|
Map<Object, Object> modelMap = new HashMap<>();
|
||||||
|
if (!ObjectUtils.isEmpty(tags)) {
|
||||||
|
int size = tags.size();
|
||||||
|
// 将标签分为等分概率,
|
||||||
|
double probabilityValue = 100 / size;
|
||||||
|
for (String tag : tags) {
|
||||||
|
modelMap.put(tag, String.valueOf(probabilityValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
redisTemplate.delete(userModelKey);
|
||||||
|
redisTemplate.opsForHash().putAll(userModelKey, modelMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新用户模型
|
||||||
|
* 若标签已存在:调整权重。
|
||||||
|
* 若标签不存在:新增标签。
|
||||||
|
* 若权重更新后小于等于 0:移除标签,避免无效标签影响推荐。
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Async("asyncExecutor")
|
||||||
|
public void updateUserModel(Integer userId, Integer blogId, Double score) {
|
||||||
|
if (userId != null) {
|
||||||
|
String userModelKey = constantConfiguration.USER_MODEL + userId;
|
||||||
|
Map<Object, Object> modelMap = redisTemplate.opsForHash().entries(userModelKey);
|
||||||
|
|
||||||
|
if (ObjectUtils.isEmpty(modelMap)) {
|
||||||
|
modelMap = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取博客下的所有标签
|
||||||
|
List<String> tags = blogsMapper.getTagsByBlogId(blogId);
|
||||||
|
if (!ObjectUtils.isEmpty(tags)) {
|
||||||
|
for (String tag : tags) {
|
||||||
|
if (modelMap.containsKey(tag)) {
|
||||||
|
double newScore = Double.parseDouble((String) modelMap.get(tag)) + score;
|
||||||
|
if (newScore > 0) {
|
||||||
|
modelMap.put(tag, String.valueOf(newScore));
|
||||||
|
} else {
|
||||||
|
modelMap.remove(tag);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
modelMap.put(tag, String.valueOf(score));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 平滑权重
|
||||||
|
final int tagsSize = modelMap.keySet().size();
|
||||||
|
for (Object tag : modelMap.keySet()) {
|
||||||
|
double probabilityValue = (Double.parseDouble((String) modelMap.get(tag)) + tagsSize) / tagsSize;
|
||||||
|
modelMap.put(tag, String.valueOf(probabilityValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
redisTemplate.opsForHash().putAll(userModelKey, modelMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 兴趣推送
|
||||||
|
*
|
||||||
|
* @param user
|
||||||
|
* @return {@link List }<{@link String }>
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<String> listBlogsByUserModel(User user) {
|
||||||
|
// 非游客
|
||||||
|
if (!ObjectUtils.isEmpty(user)) {
|
||||||
|
String userModelKey = constantConfiguration.USER_MODEL + user.getId();
|
||||||
|
final Map<Object, Object> modelMap = redisTemplate.opsForHash().entries(userModelKey);
|
||||||
|
if (!ObjectUtils.isEmpty(modelMap)) {
|
||||||
|
// 构造概率数组
|
||||||
|
final String[] probabilityArray = initProbabilityArray(modelMap);
|
||||||
|
|
||||||
|
// 随机选取x个标签
|
||||||
|
final int x = 10;
|
||||||
|
final Random randomObject = new Random();
|
||||||
|
final List<String> tags = new ArrayList<>();
|
||||||
|
for (int i = 0; i < x; i++) {
|
||||||
|
tags.add(probabilityArray[randomObject.nextInt(probabilityArray.length)]);
|
||||||
|
}
|
||||||
|
//随机获取redis中该标签下的博客id
|
||||||
|
List<Object> list = redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
|
||||||
|
for (String tag : tags) {
|
||||||
|
String key = constantConfiguration.TAG_BLOGS + tag;
|
||||||
|
connection.sRandMember(key.getBytes());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
//TODO 根据观看历史进行已观看视频的去重
|
||||||
|
return list.stream().filter(Objects::nonNull).map(Object::toString).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//TODO 游客 随机获取十个标签
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增博客推入标签库中
|
||||||
|
*
|
||||||
|
* @param bligId
|
||||||
|
* @param tags
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Async("asyncExecutor")
|
||||||
|
public void pushTagsStockIn(Integer bligId, List<String> tags) {
|
||||||
|
//使用pipelined批量执行
|
||||||
|
redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
|
||||||
|
for (String tag : tags) {
|
||||||
|
connection.sAdd((constantConfiguration.TAG_BLOGS + tag).getBytes(), String.valueOf(bligId).getBytes());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造概率数组,保存的元素是标签 -> probabilityArray = ["标签A", "标签A", "标签A", "标签B", "标签B", "标签C"]
|
||||||
|
*
|
||||||
|
* @param modelMap
|
||||||
|
* @return {@link String[] }
|
||||||
|
*/
|
||||||
|
private String[] initProbabilityArray(Map<Object, Object> modelMap) {
|
||||||
|
// key: 标签 value: 概率
|
||||||
|
Map<String, Integer> probabilityMap = new HashMap<>();
|
||||||
|
int size = modelMap.size();
|
||||||
|
final AtomicInteger n = new AtomicInteger(0);
|
||||||
|
|
||||||
|
modelMap.forEach((key, value) -> {
|
||||||
|
double probabilityValue = Double.parseDouble(value.toString());
|
||||||
|
int probability = (int) ((probabilityValue + size) / size);
|
||||||
|
n.getAndAdd(probability);
|
||||||
|
probabilityMap.put((String) key, probability);
|
||||||
|
});
|
||||||
|
final String[] probabilityArray = new String[n.get()];
|
||||||
|
|
||||||
|
final AtomicInteger index = new AtomicInteger(0);
|
||||||
|
//初始化数组
|
||||||
|
probabilityMap.forEach((tag, probability) -> {
|
||||||
|
int i = index.get();
|
||||||
|
int limit = i + probability;
|
||||||
|
while (i < limit) {
|
||||||
|
probabilityArray[i++] = tag;
|
||||||
|
}
|
||||||
|
index.set(limit);
|
||||||
|
});
|
||||||
|
return probabilityArray;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
package com.xubx.springboot_01demo.service.impl;
|
package com.xubx.springboot_01demo.service.impl;
|
||||||
|
|
||||||
import com.xubx.springboot_01demo.configuration.constantConfiguration;
|
import com.xubx.springboot_01demo.configuration.constantConfiguration;
|
||||||
import com.xubx.springboot_01demo.dto.SendMesDto;
|
import com.xubx.springboot_01demo.entity.dto.SendMesDto;
|
||||||
import com.xubx.springboot_01demo.mapper.MessagesMapper;
|
import com.xubx.springboot_01demo.mapper.MessagesMapper;
|
||||||
import com.xubx.springboot_01demo.pojo.Messages;
|
import com.xubx.springboot_01demo.entity.pojo.Messages;
|
||||||
import com.xubx.springboot_01demo.service.MessagesService;
|
import com.xubx.springboot_01demo.service.MessagesService;
|
||||||
import com.xubx.springboot_01demo.vo.historyMessagesVo;
|
import com.xubx.springboot_01demo.entity.vo.historyMessagesVo;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,12 @@ package com.xubx.springboot_01demo.service.impl;
|
||||||
|
|
||||||
import com.xubx.springboot_01demo.configuration.constantConfiguration;
|
import com.xubx.springboot_01demo.configuration.constantConfiguration;
|
||||||
import com.xubx.springboot_01demo.mapper.RelationshipMapper;
|
import com.xubx.springboot_01demo.mapper.RelationshipMapper;
|
||||||
import com.xubx.springboot_01demo.pojo.Relationship;
|
import com.xubx.springboot_01demo.entity.pojo.Relationship;
|
||||||
import com.xubx.springboot_01demo.pojo.User;
|
import com.xubx.springboot_01demo.entity.pojo.User;
|
||||||
import com.xubx.springboot_01demo.service.RelationshipService;
|
import com.xubx.springboot_01demo.service.RelationshipService;
|
||||||
import com.xubx.springboot_01demo.service.UserService;
|
import com.xubx.springboot_01demo.service.UserService;
|
||||||
import com.xubx.springboot_01demo.utils.token.RequestHolder;
|
import com.xubx.springboot_01demo.entity.vo.UserListVo;
|
||||||
import com.xubx.springboot_01demo.vo.UserListVo;
|
import com.xubx.springboot_01demo.entity.vo.UserVo;
|
||||||
import com.xubx.springboot_01demo.vo.UserVo;
|
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
|
|
@ -5,23 +5,20 @@ import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.xubx.springboot_01demo.configuration.constantConfiguration;
|
import com.xubx.springboot_01demo.configuration.constantConfiguration;
|
||||||
import com.xubx.springboot_01demo.dto.user.EditMaterialDto;
|
import com.xubx.springboot_01demo.entity.dto.user.EditMaterialDto;
|
||||||
import com.xubx.springboot_01demo.dto.user.NewFavoritesDto;
|
import com.xubx.springboot_01demo.entity.dto.user.NewFavoritesDto;
|
||||||
import com.xubx.springboot_01demo.mapper.BlogsMapper;
|
import com.xubx.springboot_01demo.entity.dto.user.UserSubscription;
|
||||||
import com.xubx.springboot_01demo.mapper.RelationshipMapper;
|
import com.xubx.springboot_01demo.entity.pojo.User;
|
||||||
import com.xubx.springboot_01demo.mapper.UserFavoriteMapper;
|
import com.xubx.springboot_01demo.mapper.*;
|
||||||
import com.xubx.springboot_01demo.mapper.UserMapper;
|
import com.xubx.springboot_01demo.entity.pojo.*;
|
||||||
import com.xubx.springboot_01demo.pojo.Blogs;
|
import com.xubx.springboot_01demo.service.InterestPushService;
|
||||||
import com.xubx.springboot_01demo.pojo.Relationship;
|
|
||||||
import com.xubx.springboot_01demo.pojo.User;
|
|
||||||
import com.xubx.springboot_01demo.pojo.UserFavorite;
|
|
||||||
import com.xubx.springboot_01demo.service.UserService;
|
import com.xubx.springboot_01demo.service.UserService;
|
||||||
|
import com.xubx.springboot_01demo.service.UserSubscriptionService;
|
||||||
import com.xubx.springboot_01demo.utils.token.RequestHolder;
|
import com.xubx.springboot_01demo.utils.token.RequestHolder;
|
||||||
import com.xubx.springboot_01demo.utils.token.TokenGenerate;
|
import com.xubx.springboot_01demo.utils.token.TokenGenerate;
|
||||||
import com.xubx.springboot_01demo.vo.getUserInfoVo;
|
import com.xubx.springboot_01demo.entity.vo.UserModelVo;
|
||||||
|
import com.xubx.springboot_01demo.entity.vo.getUserInfoVo;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
@ -30,6 +27,7 @@ import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -40,19 +38,23 @@ import java.util.function.Supplier;
|
||||||
@Service
|
@Service
|
||||||
public class UserServiceImpl implements UserService {
|
public class UserServiceImpl implements UserService {
|
||||||
@Resource
|
@Resource
|
||||||
UserMapper userMapper;
|
private UserMapper userMapper;
|
||||||
@Resource
|
@Resource
|
||||||
RelationshipMapper relationshipMapper;
|
private RelationshipMapper relationshipMapper;
|
||||||
@Resource
|
@Resource
|
||||||
BlogsMapper blogMapper;
|
private BlogsMapper blogMapper;
|
||||||
@Resource
|
@Resource
|
||||||
UserFavoriteMapper userFavoriteMapper;
|
private UserFavoriteMapper userFavoriteMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
RedisTemplate redisTemplate;
|
private RedisTemplate redisTemplate;
|
||||||
@Resource
|
@Resource
|
||||||
private HttpSession session;
|
private HttpSession session;
|
||||||
|
@Resource
|
||||||
|
private UserFollowMapper userFollowMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
ObjectMapper objectMapper;
|
private UserSubscriptionService userSubscriptionService;
|
||||||
|
@Autowired
|
||||||
|
private InterestPushService interestPushService;
|
||||||
|
|
||||||
//登陆,获取User对象
|
//登陆,获取User对象
|
||||||
public String login(User user) {
|
public String login(User user) {
|
||||||
|
@ -316,4 +318,123 @@ public class UserServiceImpl implements UserService {
|
||||||
return blogsFromDb;
|
return blogsFromDb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户粉丝列表
|
||||||
|
* @param userId
|
||||||
|
* @return {@link List }<{@link User }>
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<User> getUserFans(String userId) {
|
||||||
|
String currentUserId = String.valueOf(RequestHolder.getuserId());
|
||||||
|
|
||||||
|
if (currentUserId == null) {
|
||||||
|
throw new IllegalStateException("用户未登录");
|
||||||
|
}
|
||||||
|
// 判断是否是获取当前用户的粉丝列表
|
||||||
|
if (userId == null || userId.isEmpty() || userId.equals(currentUserId)) {
|
||||||
|
return userMapper.getUserFans(currentUserId);
|
||||||
|
} else {
|
||||||
|
return userMapper.getUserFans(userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户关注列表
|
||||||
|
* @param userId
|
||||||
|
* @return {@link List }<{@link User }>
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<User> getUserFollowList(String userId) {
|
||||||
|
String currentUserId = String.valueOf(RequestHolder.getuserId());
|
||||||
|
|
||||||
|
if (currentUserId == null) {
|
||||||
|
throw new IllegalStateException("用户未登录");
|
||||||
|
}
|
||||||
|
// 判断是否是获取当前用户的粉丝列表
|
||||||
|
if (userId == null || userId.isEmpty() || userId.equals(currentUserId)) {
|
||||||
|
return userMapper.getUserFollowList(currentUserId);
|
||||||
|
} else {
|
||||||
|
return userMapper.getUserFollowList(userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关注/取消关注用户
|
||||||
|
* @param followedId
|
||||||
|
* @return {@link Object }
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Object followUser(String followedId) {
|
||||||
|
Integer currentUserId = RequestHolder.getuserId();
|
||||||
|
|
||||||
|
if (currentUserId == null) {
|
||||||
|
throw new IllegalStateException("用户未登录");
|
||||||
|
}
|
||||||
|
if (followedId == null || followedId.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("被关注用户id不能为空");
|
||||||
|
}
|
||||||
|
if (followedId.equals(currentUserId)) {
|
||||||
|
throw new IllegalArgumentException("不能关注自己");
|
||||||
|
}
|
||||||
|
|
||||||
|
LambdaQueryWrapper<UserFollow> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.eq(UserFollow::getFollowerId, currentUserId)
|
||||||
|
.eq(UserFollow::getFollowedId, followedId);
|
||||||
|
// 判断是否已经关注
|
||||||
|
if (userFollowMapper.selectOne(queryWrapper) != null) {
|
||||||
|
// 已经关注,取消关注
|
||||||
|
userFollowMapper.delete(queryWrapper);
|
||||||
|
return "取消关注成功";
|
||||||
|
} else {
|
||||||
|
// 未关注,添加关注
|
||||||
|
UserFollow userFollow = new UserFollow();
|
||||||
|
userFollow.setFollowerId(currentUserId);
|
||||||
|
userFollow.setFollowedId(Integer.valueOf(followedId));
|
||||||
|
userFollow.setCreatedTime(new Timestamp(System.currentTimeMillis()));
|
||||||
|
userFollowMapper.insert(userFollow);
|
||||||
|
return "关注成功";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户订阅分类,初始化用户模型
|
||||||
|
* @param categories
|
||||||
|
* @return {@link Object }
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void subscribe(List<String> categories) {
|
||||||
|
Integer currentUserId = RequestHolder.getuserId();
|
||||||
|
if (currentUserId == null) {
|
||||||
|
throw new IllegalStateException("用户未登录");
|
||||||
|
}
|
||||||
|
if (categories == null || categories.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("分类不能为空");
|
||||||
|
}
|
||||||
|
List<UserSubscription> userSubscriptions = new ArrayList<>();
|
||||||
|
for (String category : categories) {
|
||||||
|
UserSubscription userSubscription = new UserSubscription();
|
||||||
|
userSubscription.setUserId(currentUserId);
|
||||||
|
userSubscription.setCategoryId(Integer.valueOf(category));
|
||||||
|
userSubscriptions.add(userSubscription);
|
||||||
|
}
|
||||||
|
userSubscriptionService.remove(new LambdaQueryWrapper<UserSubscription>().eq(UserSubscription::getUserId, currentUserId));
|
||||||
|
userSubscriptionService.saveBatch(userSubscriptions);
|
||||||
|
|
||||||
|
// 初始化模型
|
||||||
|
UserModelVo userModelVo = new UserModelVo();
|
||||||
|
userModelVo.setUserId(currentUserId);
|
||||||
|
List<String> lables = new ArrayList<>();
|
||||||
|
for (String category : categories) {
|
||||||
|
lables.addAll(userSubscriptionService.gettagsByCategoryId(Integer.valueOf(category)));
|
||||||
|
}
|
||||||
|
userModelVo.setLableNames(lables);
|
||||||
|
initModel(userModelVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initModel(UserModelVo userModelVo) {
|
||||||
|
// 初始化模型
|
||||||
|
interestPushService.initUserModel(userModelVo.getUserId(),userModelVo.getLableNames());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.xubx.springboot_01demo.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.xubx.springboot_01demo.entity.dto.user.UserSubscription;
|
||||||
|
import com.xubx.springboot_01demo.mapper.UserSubscriptionMapper;
|
||||||
|
import com.xubx.springboot_01demo.service.UserSubscriptionService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户订阅分类
|
||||||
|
* @author Xubx
|
||||||
|
* @date 2024/11/22
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class UserSubscriptionServiceImpl extends ServiceImpl<UserSubscriptionMapper, UserSubscription> implements UserSubscriptionService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private UserSubscriptionMapper userSubscriptionMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> gettagsByCategoryId(Integer categoryId) {
|
||||||
|
return userSubscriptionMapper.gettagsByCategoryId(categoryId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,60 +0,0 @@
|
||||||
package com.xubx.springboot_01demo.sms;
|
|
||||||
|
|
||||||
|
|
||||||
import com.aliyuncs.DefaultAcsClient;
|
|
||||||
import com.aliyuncs.IAcsClient;
|
|
||||||
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
|
|
||||||
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
|
|
||||||
import com.aliyuncs.exceptions.ClientException;
|
|
||||||
import com.aliyuncs.profile.DefaultProfile;
|
|
||||||
import com.aliyuncs.profile.IClientProfile;
|
|
||||||
|
|
||||||
public class SMSsend {
|
|
||||||
//产品名称:云通信短信API产品,开发者无需替换
|
|
||||||
static final String product = "Dysmsapi";
|
|
||||||
//产品域名,开发者无需替换
|
|
||||||
static final String domain = "dysmsapi.aliyuncs.com";
|
|
||||||
|
|
||||||
// 此处需要替换成开发者自己的AK(在阿里云访问控制台寻找)
|
|
||||||
static final String accessKeyId = "LTAI5t6wVLcc5R9cpoQVimco";
|
|
||||||
static final String accessKeySecret = "zzPnrX4PiuT1MePZDrMK6EOhIK59jw";
|
|
||||||
|
|
||||||
public static SendSmsResponse sendSms() throws ClientException {
|
|
||||||
|
|
||||||
//可自助调整超时时间
|
|
||||||
System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
|
|
||||||
System.setProperty("sun.net.client.defaultReadTimeout", "10000");
|
|
||||||
|
|
||||||
//初始化acsClient,暂不支持region化
|
|
||||||
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
|
|
||||||
DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
|
|
||||||
IAcsClient acsClient = new DefaultAcsClient(profile);
|
|
||||||
|
|
||||||
//组装请求对象-具体描述见控制台-文档部分内容
|
|
||||||
SendSmsRequest request = new SendSmsRequest();
|
|
||||||
//必填:待发送手机号
|
|
||||||
request.setPhoneNumbers("13774774893");
|
|
||||||
//必填:短信签名-可在短信控制台中找到
|
|
||||||
request.setSignName("xbx博客");
|
|
||||||
//必填:短信模板-可在短信控制台中找到
|
|
||||||
request.setTemplateCode("SMS_467395020");
|
|
||||||
//可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
|
|
||||||
request.setTemplateParam("{\"name\":\"李豪\"}");
|
|
||||||
|
|
||||||
//hint 此处可能会抛出异常,注意catch
|
|
||||||
SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
|
|
||||||
|
|
||||||
return sendSmsResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) throws ClientException {
|
|
||||||
SendSmsResponse sendSms = sendSms();
|
|
||||||
|
|
||||||
if (sendSms.getCode().equals("OK")) {
|
|
||||||
System.out.println("短信发送成功...." + sendSms.getCode());
|
|
||||||
} else {
|
|
||||||
System.out.println("短信发送失败...." + sendSms.getCode());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,81 +0,0 @@
|
||||||
package com.xubx.springboot_01demo.sms;
|
|
||||||
// This file is auto-generated, don't edit it. Thanks.
|
|
||||||
|
|
||||||
import com.aliyun.auth.credentials.Credential;
|
|
||||||
import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
|
|
||||||
import com.aliyun.sdk.service.dysmsapi20170525.AsyncClient;
|
|
||||||
import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsRequest;
|
|
||||||
import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsResponse;
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import darabonba.core.client.ClientOverrideConfiguration;
|
|
||||||
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
public class Sample {
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
|
|
||||||
// HttpClient Configuration
|
|
||||||
/*HttpClient httpClient = new ApacheAsyncHttpClientBuilder()
|
|
||||||
.connectionTimeout(Duration.ofSeconds(10)) // Set the connection timeout time, the default is 10 seconds
|
|
||||||
.responseTimeout(Duration.ofSeconds(10)) // Set the response timeout time, the default is 20 seconds
|
|
||||||
.maxConnections(128) // Set the connection pool size
|
|
||||||
.maxIdleTimeOut(Duration.ofSeconds(50)) // Set the connection pool timeout, the default is 30 seconds
|
|
||||||
// Configure the proxy
|
|
||||||
.proxy(new ProxyOptions(ProxyOptions.Type.HTTP, new InetSocketAddress("<your-proxy-hostname>", 9001))
|
|
||||||
.setCredentials("<your-proxy-username>", "<your-proxy-password>"))
|
|
||||||
// If it is an https connection, you need to configure the certificate, or ignore the certificate(.ignoreSSL(true))
|
|
||||||
.x509TrustManagers(new X509TrustManager[]{})
|
|
||||||
.keyManagers(new KeyManager[]{})
|
|
||||||
.ignoreSSL(false)
|
|
||||||
.build();*/
|
|
||||||
|
|
||||||
// Configure Credentials authentication information, including ak, secret, token
|
|
||||||
StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder()
|
|
||||||
// Please ensure that the environment variables ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET are set.
|
|
||||||
.accessKeyId(System.getenv("LTAI5tEZgzfMnkLdKCRRVnMT"))
|
|
||||||
.accessKeySecret(System.getenv("51cCqBgSfOkVxVUNdkv56mHR68eKfl"))
|
|
||||||
//.securityToken(System.getenv("ALIBABA_CLOUD_SECURITY_TOKEN")) // use STS token
|
|
||||||
.build());
|
|
||||||
|
|
||||||
// Configure the Client
|
|
||||||
AsyncClient client = AsyncClient.builder()
|
|
||||||
.region("cn-hangzhou") // Region ID
|
|
||||||
//.httpClient(httpClient) // Use the configured HttpClient, otherwise use the default HttpClient (Apache HttpClient)
|
|
||||||
.credentialsProvider(provider)
|
|
||||||
//.serviceConfiguration(Configuration.create()) // Service-level configuration
|
|
||||||
// Client-level configuration rewrite, can set Endpoint, Http request parameters, etc.
|
|
||||||
.overrideConfiguration(
|
|
||||||
ClientOverrideConfiguration.create()
|
|
||||||
// Endpoint 请参考 https://api.aliyun.com/product/Dysmsapi
|
|
||||||
.setEndpointOverride("dysmsapi.aliyuncs.com")
|
|
||||||
//.setConnectTimeout(Duration.ofSeconds(30))
|
|
||||||
)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// Parameter settings for API request
|
|
||||||
SendSmsRequest sendSmsRequest = SendSmsRequest.builder()
|
|
||||||
.signName("xbx博客")
|
|
||||||
.templateCode("SMS_467565017")
|
|
||||||
.phoneNumbers("18659472561")
|
|
||||||
// .templateParam("{\"code\":\"1234\"}")
|
|
||||||
// Request-level configuration rewrite, can set Http request parameters, etc.
|
|
||||||
// .requestConfiguration(RequestConfiguration.create().setHttpHeaders(new HttpHeaders()))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// Asynchronously get the return value of the API request
|
|
||||||
CompletableFuture<SendSmsResponse> response = client.sendSms(sendSmsRequest);
|
|
||||||
// Synchronously get the return value of the API request
|
|
||||||
SendSmsResponse resp = response.get();
|
|
||||||
System.out.println(new Gson().toJson(resp));
|
|
||||||
// Asynchronous processing of return values
|
|
||||||
/*response.thenAccept(resp -> {
|
|
||||||
System.out.println(new Gson().toJson(resp));
|
|
||||||
}).exceptionally(throwable -> { // Handling exceptions
|
|
||||||
System.out.println(throwable.getMessage());
|
|
||||||
return null;
|
|
||||||
});*/
|
|
||||||
|
|
||||||
// Finally, close the client
|
|
||||||
client.close();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +1,7 @@
|
||||||
package com.xubx.springboot_01demo.utils.api;
|
package com.xubx.springboot_01demo.utils.api;
|
||||||
|
|
||||||
import com.xubx.springboot_01demo.pojo.Blogs;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class Result<T> {
|
public class Result<T> {
|
||||||
//状态码
|
//状态码
|
||||||
|
|
|
@ -9,7 +9,7 @@ import java.util.Date;
|
||||||
|
|
||||||
public class TokenGenerate {
|
public class TokenGenerate {
|
||||||
|
|
||||||
private static final long EXPIRE_TIME = 24 * 60 * 60 * 1000;
|
private static final long EXPIRE_TIME = 48 * 60 * 60 * 1000;// TODO 修改为2天过期
|
||||||
private static final String TOKEN_SECRET = "tokenqkj"; //密钥盐
|
private static final String TOKEN_SECRET = "tokenqkj"; //密钥盐
|
||||||
|
|
||||||
public String generateToken(int userId) {
|
public String generateToken(int userId) {
|
||||||
|
|
|
@ -3,4 +3,7 @@
|
||||||
|
|
||||||
<mapper namespace="com.xubx.springboot_01demo.mapper.BlogLikeMapper">
|
<mapper namespace="com.xubx.springboot_01demo.mapper.BlogLikeMapper">
|
||||||
|
|
||||||
|
<insert id="addData">
|
||||||
|
insert into blog_like(blog_id,user_id,created_time) values(#{blogId},#{userId},#{createdTime})
|
||||||
|
</insert>
|
||||||
</mapper>
|
</mapper>
|
|
@ -2,7 +2,7 @@
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
|
||||||
<mapper namespace="com.xubx.springboot_01demo.mapper.BlogsMapper">
|
<mapper namespace="com.xubx.springboot_01demo.mapper.BlogsMapper">
|
||||||
<resultMap id="BaseResultMap" type="com.xubx.springboot_01demo.pojo.Blogs">
|
<resultMap id="BaseResultMap" type="com.xubx.springboot_01demo.entity.pojo.Blogs">
|
||||||
<id column="id" property="id" />
|
<id column="id" property="id" />
|
||||||
<result column="id" property="id" />
|
<result column="id" property="id" />
|
||||||
<result column="title" property="title" />
|
<result column="title" property="title" />
|
||||||
|
@ -58,21 +58,24 @@
|
||||||
<select id="getCommentCount" resultType="java.lang.String">
|
<select id="getCommentCount" resultType="java.lang.String">
|
||||||
select comment_count from blog where id = #{blogId}
|
select comment_count from blog where id = #{blogId}
|
||||||
</select>
|
</select>
|
||||||
<select id="getBlogsByFavoriteId" resultType="com.xubx.springboot_01demo.pojo.Blogs">
|
<select id="getBlogsByFavoriteId" resultType="com.xubx.springboot_01demo.entity.pojo.Blogs">
|
||||||
select * from blog where id in (select blog_id from user_favorite_blog where favorite_id = #{favoriteId})
|
select * from blog where id in (select blog_id from user_favorite_blog where favorite_id = #{favoriteId})
|
||||||
</select>
|
</select>
|
||||||
<select id="getUserIdsByBlogId" resultType="java.lang.String">
|
<select id="getUserIdsByBlogId" resultType="java.lang.String">
|
||||||
SELECT user_id FROM blog_like WHERE blog_id = #{blogId}
|
SELECT user_id FROM blog_like WHERE blog_id = #{blogId}
|
||||||
</select>
|
</select>
|
||||||
|
<select id="getTagsByBlogId" resultType="java.lang.String">
|
||||||
|
SELECT tag_id FROM blog_tags WHERE blog_id = #{blogId}
|
||||||
|
</select>
|
||||||
|
|
||||||
<!--新增博客-->
|
<!--新增博客-->
|
||||||
<insert id="addBlogs" parameterType="com.xubx.springboot_01demo.pojo.Blogs">
|
<insert id="addBlogs" parameterType="com.xubx.springboot_01demo.entity.pojo.Blogs">
|
||||||
insert into blog (title, description, content, created)
|
insert into blog (title, description, content, created)
|
||||||
values (#{title}, #{description}, #{content}, #{created})
|
values (#{title}, #{description}, #{content}, #{created})
|
||||||
</insert>
|
</insert>
|
||||||
<insert id="insertCategory">
|
<insert id="insertTags">
|
||||||
insert into blog_category(blog_id, category_id)
|
insert into blog_tags(blog_id, tag_id)
|
||||||
values (#{blogId}, #{categoryId})
|
values (#{blogId}, #{tagId})
|
||||||
</insert>
|
</insert>
|
||||||
<insert id="collectBlog">
|
<insert id="collectBlog">
|
||||||
insert into user_favorite_blog(blog_id, favorite_id)
|
insert into user_favorite_blog(blog_id, favorite_id)
|
||||||
|
@ -80,7 +83,7 @@
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
<!--更新博客-->
|
<!--更新博客-->
|
||||||
<update id="updateBlogs" parameterType="com.xubx.springboot_01demo.pojo.Blogs">
|
<update id="updateBlogs" parameterType="com.xubx.springboot_01demo.entity.pojo.Blogs">
|
||||||
update blog
|
update blog
|
||||||
set title = #{title},
|
set title = #{title},
|
||||||
description = #{description},
|
description = #{description},
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
|
||||||
<mapper namespace="com.xubx.springboot_01demo.mapper.CommentMapper">
|
<mapper namespace="com.xubx.springboot_01demo.mapper.CommentMapper">
|
||||||
<resultMap id="CommentResultMap" type="com.xubx.springboot_01demo.vo.CommentVo">
|
<resultMap id="CommentResultMap" type="com.xubx.springboot_01demo.entity.vo.CommentVo">
|
||||||
<result column="comment_id" property="comment_id"/>
|
<result column="comment_id" property="comment_id"/>
|
||||||
<result column="article_id" property="article_id"/>
|
<result column="article_id" property="article_id"/>
|
||||||
<result column="username" property="username"/>
|
<result column="username" property="username"/>
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
WHERE c.article_id = #{article_id}
|
WHERE c.article_id = #{article_id}
|
||||||
</select>
|
</select>
|
||||||
<!--新增评论-->
|
<!--新增评论-->
|
||||||
<insert id="addComment" parameterType="com.xubx.springboot_01demo.pojo.Comment">
|
<insert id="addComment" parameterType="com.xubx.springboot_01demo.entity.pojo.Comment">
|
||||||
insert into comment (article_id, username, content, parent_id, parent_name, created)
|
insert into comment (article_id, username, content, parent_id, parent_name, created)
|
||||||
values (#{article_id}, #{username}, #{content}, #{parent_id}, #{parent_name}, #{created})
|
values (#{article_id}, #{username}, #{content}, #{parent_id}, #{parent_name}, #{created})
|
||||||
</insert>
|
</insert>
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
|
|
||||||
<mapper namespace="com.xubx.springboot_01demo.mapper.MessagesMapper">
|
<mapper namespace="com.xubx.springboot_01demo.mapper.MessagesMapper">
|
||||||
<!--1.发送消息-->
|
<!--1.发送消息-->
|
||||||
<insert id="sendMessages" parameterType="com.xubx.springboot_01demo.pojo.Messages">
|
<insert id="sendMessages" parameterType="com.xubx.springboot_01demo.entity.pojo.Messages">
|
||||||
insert into messages (sender, recipient, content, state, created)
|
insert into messages (sender, recipient, content, state, created)
|
||||||
values (#{sender}, #{recipient}, #{content}, #{state}, #{created})
|
values (#{sender}, #{recipient}, #{content}, #{state}, #{created})
|
||||||
</insert>
|
</insert>
|
||||||
<!--2.获取历史记录-->
|
<!--2.获取历史记录-->
|
||||||
<select id="getMessages" resultType="com.xubx.springboot_01demo.vo.historyMessagesVo">
|
<select id="getMessages" resultType="com.xubx.springboot_01demo.entity.vo.historyMessagesVo">
|
||||||
SELECT ch.sender,
|
SELECT ch.sender,
|
||||||
ch.recipient,
|
ch.recipient,
|
||||||
ch.content,
|
ch.content,
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
ORDER BY ch.created;
|
ORDER BY ch.created;
|
||||||
</select>
|
</select>
|
||||||
<!--3.将state设置为已读-->
|
<!--3.将state设置为已读-->
|
||||||
<update id="updateState" parameterType="com.xubx.springboot_01demo.pojo.Messages">
|
<update id="updateState" parameterType="com.xubx.springboot_01demo.entity.pojo.Messages">
|
||||||
update messages
|
update messages
|
||||||
set state = #{state}
|
set state = #{state}
|
||||||
where sender = #{recipient} and recipient = #{sender} and state = 0;
|
where sender = #{recipient} and recipient = #{sender} and state = 0;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
<mapper namespace="com.xubx.springboot_01demo.mapper.RelationshipMapper">
|
<mapper namespace="com.xubx.springboot_01demo.mapper.RelationshipMapper">
|
||||||
<!--1.根据用户名模糊查询用户-->
|
<!--1.根据用户名模糊查询用户-->
|
||||||
<select id="findUserByUsername" resultType="com.xubx.springboot_01demo.pojo.User">
|
<select id="findUserByUsername" resultType="com.xubx.springboot_01demo.entity.pojo.User">
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM register r
|
FROM register r
|
||||||
WHERE r.username LIKE CONCAT('%', #{username}, '%')
|
WHERE r.username LIKE CONCAT('%', #{username}, '%')
|
||||||
|
@ -15,27 +15,27 @@
|
||||||
AND r.username != #{currentName}
|
AND r.username != #{currentName}
|
||||||
</select>
|
</select>
|
||||||
<!--2.向用户发送添加好友请求-->
|
<!--2.向用户发送添加好友请求-->
|
||||||
<insert id="addFriendRequest" parameterType="com.xubx.springboot_01demo.pojo.Relationship">
|
<insert id="addFriendRequest" parameterType="com.xubx.springboot_01demo.entity.pojo.Relationship">
|
||||||
insert into relationship (username, friend, status, created, initiator)
|
insert into relationship (username, friend, status, created, initiator)
|
||||||
values (#{username}, #{friend}, #{status}, #{created}, #{username}),
|
values (#{username}, #{friend}, #{status}, #{created}, #{username}),
|
||||||
(#{friend}, #{username}, #{status}, #{created}, #{username})
|
(#{friend}, #{username}, #{status}, #{created}, #{username})
|
||||||
</insert>
|
</insert>
|
||||||
<!--3.接受好友添加请求-->
|
<!--3.接受好友添加请求-->
|
||||||
<update id="acceptFriendRequest" parameterType="com.xubx.springboot_01demo.pojo.Relationship">
|
<update id="acceptFriendRequest" parameterType="com.xubx.springboot_01demo.entity.pojo.Relationship">
|
||||||
update relationship
|
update relationship
|
||||||
set status = #{status}
|
set status = #{status}
|
||||||
where (username = #{username} and friend = #{friend})
|
where (username = #{username} and friend = #{friend})
|
||||||
OR (username = #{friend} and friend = #{username})
|
OR (username = #{friend} and friend = #{username})
|
||||||
</update>
|
</update>
|
||||||
<!--4.删除好友-->
|
<!--4.删除好友-->
|
||||||
<delete id="removeFriend" parameterType="com.xubx.springboot_01demo.pojo.Relationship">
|
<delete id="removeFriend" parameterType="com.xubx.springboot_01demo.entity.pojo.Relationship">
|
||||||
delete
|
delete
|
||||||
from relationship
|
from relationship
|
||||||
where (username = #{username} and friend = #{friend})
|
where (username = #{username} and friend = #{friend})
|
||||||
OR (username = #{friend} and friend = #{username})
|
OR (username = #{friend} and friend = #{username})
|
||||||
</delete>
|
</delete>
|
||||||
<!--5.查询好友列表-->
|
<!--5.查询好友列表-->
|
||||||
<select id="getFriends" resultType="com.xubx.springboot_01demo.vo.UserListVo">
|
<select id="getFriends" resultType="com.xubx.springboot_01demo.entity.vo.UserListVo">
|
||||||
SELECT r.*, unreadCount.unreadCount
|
SELECT r.*, unreadCount.unreadCount
|
||||||
FROM register r
|
FROM register r
|
||||||
JOIN (SELECT friend, COUNT(m.id) AS unreadCount
|
JOIN (SELECT friend, COUNT(m.id) AS unreadCount
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
AND status = 1)
|
AND status = 1)
|
||||||
</select>
|
</select>
|
||||||
<!--6.查看是否有好友请求-->
|
<!--6.查看是否有好友请求-->
|
||||||
<select id="checkFriendRequest" resultType="com.xubx.springboot_01demo.pojo.Relationship">
|
<select id="checkFriendRequest" resultType="com.xubx.springboot_01demo.entity.pojo.Relationship">
|
||||||
select *
|
select *
|
||||||
from relationship
|
from relationship
|
||||||
where friend = #{username}
|
where friend = #{username}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?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.xubx.springboot_01demo.mapper.UserFollowMapper">
|
||||||
|
|
||||||
|
</mapper>
|
|
@ -3,18 +3,18 @@
|
||||||
|
|
||||||
<mapper namespace="com.xubx.springboot_01demo.mapper.UserMapper">
|
<mapper namespace="com.xubx.springboot_01demo.mapper.UserMapper">
|
||||||
|
|
||||||
<resultMap id="BaseResultMap" type="com.xubx.springboot_01demo.pojo.User">
|
<resultMap id="BaseResultMap" type="com.xubx.springboot_01demo.entity.pojo.User">
|
||||||
<id column="username" property="username" />
|
<id column="username" property="username" />
|
||||||
<result column="username" property="username" />
|
<result column="username" property="username" />
|
||||||
<result column="password" property="password" />
|
<result column="password" property="password" />
|
||||||
<result column="avatar" property="avatar"/>
|
<result column="avatar" property="avatar"/>
|
||||||
</resultMap>
|
</resultMap>
|
||||||
<!-- 插入用户 -->
|
<!-- 插入用户 -->
|
||||||
<insert id="insertUser" parameterType="com.xubx.springboot_01demo.pojo.User" useGeneratedKeys="true" keyProperty="id">
|
<insert id="insertUser" parameterType="com.xubx.springboot_01demo.entity.pojo.User" useGeneratedKeys="true" keyProperty="id">
|
||||||
insert into user(username, password) values(#{username}, #{password})
|
insert into user(username, password) values(#{username}, #{password})
|
||||||
</insert>
|
</insert>
|
||||||
<!--添加头像-->
|
<!--添加头像-->
|
||||||
<insert id="addAvatar" parameterType="com.xubx.springboot_01demo.pojo.User">
|
<insert id="addAvatar" parameterType="com.xubx.springboot_01demo.entity.pojo.User">
|
||||||
UPDATE user
|
UPDATE user
|
||||||
SET avatar = #{path}
|
SET avatar = #{path}
|
||||||
WHERE username = #{username};
|
WHERE username = #{username};
|
||||||
|
@ -34,9 +34,20 @@
|
||||||
UPDATE user
|
UPDATE user
|
||||||
SET password = #{newPassword}
|
SET password = #{newPassword}
|
||||||
WHERE username = #{username}
|
WHERE username = #{username}
|
||||||
|
</insert>
|
||||||
|
<insert id="subscribe">
|
||||||
|
|
||||||
</insert>
|
</insert>
|
||||||
<!-- 根据name查密码 -->
|
<!-- 根据name查密码 -->
|
||||||
<select id="getPasswordByname" resultType="java.lang.String">
|
<select id="getPasswordByname" resultType="java.lang.String">
|
||||||
select password from user where username = #{username}
|
select password from user where username = #{username}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="getUserFans" resultType="com.xubx.springboot_01demo.entity.pojo.User">
|
||||||
|
SELECT * FROM `user` WHERE id in (SELECT follower_id FROM user_follow WHERE followed_id = #{userId})
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="getUserFollowList" resultType="com.xubx.springboot_01demo.entity.pojo.User">
|
||||||
|
SELECT * FROM `user` WHERE id in (SELECT followed_id FROM user_follow WHERE follower_id = #{userId})
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?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.xubx.springboot_01demo.mapper.UserSubscriptionMapper">
|
||||||
|
|
||||||
|
<select id="gettagsByCategoryId" resultType="java.lang.String">
|
||||||
|
select id from tags where category_id = #{categoryId}
|
||||||
|
</select>
|
||||||
|
</mapper>
|
|
@ -1,34 +0,0 @@
|
||||||
import com.auth0.jwt.JWT;
|
|
||||||
import com.auth0.jwt.JWTVerifier;
|
|
||||||
import com.auth0.jwt.algorithms.Algorithm;
|
|
||||||
import com.auth0.jwt.interfaces.DecodedJWT;
|
|
||||||
import com.xubx.springboot_01demo.utils.token.RequestHolder;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
public class test {
|
|
||||||
public static boolean verify(String token) {
|
|
||||||
try {
|
|
||||||
//去掉token的第一个和最后一个引号
|
|
||||||
if (token != null && token.startsWith("\"") && token.endsWith("\"")) {
|
|
||||||
token = token.substring(1, token.length() - 1);
|
|
||||||
}
|
|
||||||
JWTVerifier verifier = JWT.require(Algorithm.HMAC256("tokenqkj")).withIssuer("auth0").build();
|
|
||||||
DecodedJWT jwt = verifier.verify(token);
|
|
||||||
RequestHolder.add(jwt.getClaim("username").asString());
|
|
||||||
System.out.println("认证通过:");
|
|
||||||
System.out.println("issuer: " + jwt.getIssuer());
|
|
||||||
System.out.println("username: " + jwt.getClaim("username").asString());
|
|
||||||
System.out.println("过期时间: " + jwt.getExpiresAt());
|
|
||||||
return true;
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println(e.getMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
public void test1(){
|
|
||||||
verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhdXRoMCIsImV4cCI6MTcxODk1MzMxMiwidXNlcm5hbWUiOiIxMjM0In0.x_P_0vm7fBStK7feBWrFhfDFBZYXTOpDpvayztj0MNE");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue