修改数据库表,添加post接口,优化工具类

lzt
forely 2 weeks ago
parent 5a58c834db
commit 010cf3dc0f

@ -1,5 +1,6 @@
package com.luojia_channel.common.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
@ -10,12 +11,7 @@ public class MybatisConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
PaginationInnerInterceptor paginationInterceptor = new PaginationInnerInterceptor();
// 设置单页最大限制(如不限制可设为 -1
paginationInterceptor.setMaxLimit(1000L);
// 设置是否溢出总页数true自动调整页码false抛出异常
paginationInterceptor.setOverflow(true);
interceptor.addInnerInterceptor(paginationInterceptor);
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}

@ -5,4 +5,6 @@ public class RedisConstant {
public static final String REFRESH_TOKEN_PREFIX = "refresh_token:";
// redis存储的黑名单前缀
public static final String BLACKLIST_PREFIX = "blacklist:";
// 重建缓存分布式锁前缀
public static final String SAFE_GET_LOCK_KEY_PREFIX = "safe_get_lock_key_prefix:";
}

@ -0,0 +1,9 @@
package com.luojia_channel.common.domain.page;
import lombok.Data;
@Data
public class PageRequest {
private Long current = 1L;
private Long size = 10L;
}

@ -0,0 +1,20 @@
package com.luojia_channel.common.domain.page;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Collections;
import java.util.List;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PageResponse<T> {
private Long current;
private Long size = 10L;
private Long total;
private List<T> records = Collections.emptyList();
}

@ -0,0 +1,12 @@
package com.luojia_channel.common.dto;
import lombok.Data;
@Data
public class CreatePostDTO {
private String title;
private String content;
private Long userId;
private Long categoryId;
}

@ -0,0 +1,41 @@
package com.luojia_channel.common.utils;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.luojia_channel.common.domain.page.PageRequest;
import com.luojia_channel.common.domain.page.PageResponse;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
public class PageUtil {
public static <R,T> PageResponse<R> convert(IPage<T> page, Function<? super T,? extends R> mapper) {
List<R> targetList = page.getRecords().stream()
.map(mapper)
.collect(Collectors.toList());
return PageResponse.<R>builder()
.current(page.getCurrent())
.size(page.getSize())
.records(targetList)
.total(page.getTotal())
.build();
}
public static <R,T> PageResponse<R> convert(IPage<T> page, Class<R> clazz) {
List<R> targetList = page.getRecords().stream()
.map(each -> BeanUtil.copyProperties(each, clazz))
.collect(Collectors.toList());
return PageResponse.<R>builder()
.current(page.getCurrent())
.size(page.getSize())
.records(targetList)
.total(page.getTotal())
.build();
}
public static Page convert(PageRequest request){
return new Page(request.getCurrent(), request.getSize());
}
}

@ -3,6 +3,8 @@ package com.luojia_channel.common.utils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;
@ -11,16 +13,26 @@ import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import static com.luojia_channel.common.constants.RedisConstant.SAFE_GET_LOCK_KEY_PREFIX;
@Component
@RequiredArgsConstructor
public class RedisUtil {
private final RedisTemplate<String, Object> redisTemplate;
private final RedissonClient redissonClient;
private static final Long DEFAULT_TIMEOUT = 30000L;
private static final TimeUnit DEFAULT_TIME_UNIT = TimeUnit.MILLISECONDS;
// 获取redisTemplate,因为复杂的redis操作不便于封装
public RedisTemplate<String, Object> getInstance(){
return redisTemplate;
}
/**
* redis
*/
@ -30,12 +42,35 @@ public class RedisUtil {
return value != null ? type.cast(value) : null;
}
public <T> T safeGet(String key, Class<T> type, Supplier<T> cacheLoader, long timeout, TimeUnit timeUnit) {
T result = get(key, type);
if(result != null){
return result;
}
// 重建缓存
RLock lock = redissonClient.getLock(SAFE_GET_LOCK_KEY_PREFIX + key);
lock.lock();
try{
if(get(key, type) == null){
T dbResult = cacheLoader.get();
if(dbResult == null){
return null;
}
set(key, dbResult, timeout, timeUnit);
return dbResult;
}
}finally {
lock.unlock();
}
return get(key, type);
}
public void set(String key, Object value) {
redisTemplate.opsForValue().set(key, value, DEFAULT_TIMEOUT, DEFAULT_TIME_UNIT);
}
public void set(String key, Object value, long timeout, TimeUnit unit) {
redisTemplate.opsForValue().set(key, value, timeout, unit);
public void set(String key, Object value, long timeout, TimeUnit timeUnit) {
redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
}
public void expire(String key, long time, TimeUnit timeUnit) {

@ -9,7 +9,7 @@ import com.luojia_channel.modules.file.entity.LjFile;
public interface FileService extends IService<LjFile> {
Boolean createBucket(String name);
Boolean deleteBucket(String name);
Long uploadFile(UploadFileDTO uploadFileDTO);
Long uploadFileAndGetFileId(UploadFileDTO uploadFileDTO);
Boolean uploadChunk(UploadChunkDTO chunkDTO);
Long completeUpload(CompleteUploadDTO completeDTO);
}

@ -70,7 +70,7 @@ public class FileServiceImpl extends ServiceImpl<LjFileMapper, LjFile> implement
// 普通上传
@Override
@Transactional(rollbackFor = Exception.class)
public Long uploadFile(UploadFileDTO fileDTO) {
public Long uploadFileAndGetFileId(UploadFileDTO fileDTO) {
validateFileUtil.validateFile(fileDTO);
Long fileId = validateFileUtil.getExistedFileId(fileDTO.getFileMd5());
if(fileId != null){

@ -0,0 +1,72 @@
package com.luojia_channel.modules.post.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.luojia_channel.common.domain.Result;
import com.luojia_channel.common.domain.page.PageResponse;
import com.luojia_channel.modules.file.dto.UploadFileDTO;
import com.luojia_channel.modules.post.dto.req.PostCreateDTO;
import com.luojia_channel.modules.post.dto.req.PostPageQueryDTO;
import com.luojia_channel.modules.post.dto.req.PostUpdateDTO;
import com.luojia_channel.modules.post.dto.resp.PostBasicInfoDTO;
import com.luojia_channel.modules.post.entity.Post;
import com.luojia_channel.modules.post.service.PostService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@RequiredArgsConstructor
@RestController
@RequestMapping("/post")
public class PostController {
private final PostService postService;
// 创建帖子
@PostMapping
public Result<Void> createPost(@RequestBody PostCreateDTO postCreateDTO) {
postService.createPost(postCreateDTO);
return Result.success();
}
// 设置帖子封面
@PostMapping("/cover")
public Result<Void> setCover(@RequestParam("file") MultipartFile file,
@RequestParam("fileType") String fileType,
@RequestParam("fileMd5") String fileMd5){
UploadFileDTO fileDTO = UploadFileDTO.builder()
.file(file).fileType(fileType).fileMd5(fileMd5)
.build();
postService.setCover(fileDTO);
return Result.success();
}
// 更新帖子
@PutMapping()
public Result<Void> updatePost(@RequestBody PostUpdateDTO postUpdateDTO) {
postService.updatePost(postUpdateDTO);
return Result.success();
}
// 删除帖子
@DeleteMapping("/{id}")
public Result<Void> deletePost(@PathVariable Long id) {
postService.deletePost(id);
return Result.success();
}
// 根据ID获取帖子详情
@GetMapping("/{id}")
public Post getPostById(@PathVariable Long id) {
return postService.getById(id);
}
// 分页查询帖子
@GetMapping
public Result<PageResponse<PostBasicInfoDTO>> pagePost(PostPageQueryDTO postPageQueryDTO) {
return Result.success(postService.pagePost(postPageQueryDTO));
}
}

@ -0,0 +1,11 @@
package com.luojia_channel.modules.post.dto.req;
import lombok.Data;
@Data
public class PostCreateDTO {
private String title;
private String content;
private Long userId;
private Long categoryId;
}

@ -0,0 +1,9 @@
package com.luojia_channel.modules.post.dto.req;
import com.luojia_channel.common.domain.page.PageRequest;
import lombok.Data;
@Data
public class PostPageQueryDTO extends PageRequest {
}

@ -0,0 +1,10 @@
package com.luojia_channel.modules.post.dto.req;
import lombok.Data;
@Data
public class PostUpdateDTO {
private String title;
private String content;
private Long categoryId;
}

@ -0,0 +1,13 @@
package com.luojia_channel.modules.post.dto.resp;
import lombok.Data;
@Data
public class PostBasicInfoDTO {
private Long id;
private String coverUrl;
private String title;
private Integer likeCount;
private Integer commentCount;
private Integer favoriteCount;
}

@ -0,0 +1,30 @@
package com.luojia_channel.modules.post.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@TableName("post")
public class Post {
@TableId(type = IdType.AUTO)
private Long id;
private String title;
private Long coverId;
private String content;
private Integer likeCount;
private Integer commentCount;
private Integer favoriteCount;
private Integer viewCount;
private Long userId;
private Long categoryId;
private String createTime;
private String updateTime;
}

@ -0,0 +1,10 @@
package com.luojia_channel.modules.post.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.luojia_channel.modules.post.entity.Post;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface PostMapper extends BaseMapper<Post> {
}

@ -0,0 +1,7 @@
package com.luojia_channel.modules.post.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.luojia_channel.modules.post.entity.Post;
public interface PostService extends IService<Post> {
}

@ -0,0 +1,25 @@
package com.luojia_channel.modules.post.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.luojia_channel.modules.file.mapper.LjFileMapper;
import com.luojia_channel.modules.post.entity.Post;
import com.luojia_channel.modules.post.mapper.PostMapper;
import com.luojia_channel.modules.post.service.PostService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class PostServiceImpl extends ServiceImpl<PostMapper, Post> implements PostService {
private final PostMapper postMapper;
private final LjFileMapper fileMapper;
private String getUrlById(String id){
return fileMapper.selectById(id).getFileUrl();
}
}

@ -0,0 +1,4 @@
package com.luojia_channel.modules.post.utils;
public class ValidatePostUtil {
}

@ -16,9 +16,7 @@ import com.luojia_channel.modules.user.service.UserInfoService;
import com.luojia_channel.modules.user.utils.ValidateUserUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import java.io.InputStream;
import java.time.LocalDateTime;
@Service
@ -27,7 +25,7 @@ public class UserInfoServiceImpl extends ServiceImpl<UserMapper, User> implement
private final UserMapper userMapper;
private final ValidateUserUtil validateUserUtil;
private final FileServiceImpl minioService;
private final FileServiceImpl fileService;
private final GeneratePathUtil generatePathUtil;
private final ValidateFileUtil validateFileUtil;
@ -74,22 +72,18 @@ public class UserInfoServiceImpl extends ServiceImpl<UserMapper, User> implement
validateFileUtil.validateFile(uploadFileDTO);
try {
// TODO 下述工作应该是前端干的----------
/*
/*
InputStream inputStream = uploadFileDTO.getFile().getInputStream();
String fileMd5 = DigestUtils.md5DigestAsHex(inputStream);
String fileType = "image";
uploadFileDTO.setFileType(fileType);
uploadFileDTO.setFileMd5(fileMd5);
// TODO ending---------
*/
minioService.uploadFile(uploadFileDTO);
fileService.uploadFileAndGetFileId(uploadFileDTO);
String filePath = generatePathUtil
.getObjectName(uploadFileDTO.getFile().getOriginalFilename(),
uploadFileDTO.getFileMd5());
// 直接设置成url省去一次读数据库操作
user.setAvatar(filePath);
updateById(user);
} catch (Exception e) {

@ -1,19 +1,36 @@
# 本地开发环境
# lj:
# db:
# host: localhost
# password: 123456
# redis:
# host: localhost
# port: 6379
# password: 123456
# rabbitmq:
# host: localhost
# port: 15672
# username: root
# password: 123456
# minio:
# endpoint: http://localhost:9000
# accessKey: minioadmin
# secretKey: minioadmin
lj:
db:
host: localhost
password: 123456
host: 192.168.59.129
password: Forely123!
redis:
host: localhost
host: 192.168.59.129
port: 6379
password: 123456
password: Forely123!
rabbitmq:
host: localhost
port: 15672
username: root
password: 123456
host: 192.168.59.129
port: 5672
username: admin
password: Forely123!
minio:
endpoint: http://localhost:9000
accessKey: minioadmin
secretKey: minioadmin
endpoint: http://192.168.59.129:9000
accessKey: forely
secretKey: Forely123!

@ -23,6 +23,16 @@ CREATE TABLE `user` (
UNIQUE INDEX `uk_student_id` (`student_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
## 分类表
DROP TABLE IF EXISTS `category`;
CREATE TABLE `category` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
`name` VARCHAR(50) NOT NULL UNIQUE COMMENT '分类名称',
`description` VARCHAR(255) COMMENT '分类描述',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='分类表';
## 文件表
DROP TABLE IF EXISTS `lj_file`;
CREATE TABLE `lj_file` (
@ -35,7 +45,10 @@ CREATE TABLE `lj_file` (
`file_status` INT NOT NULL DEFAULT 0 COMMENT '文件状态0:正在上传, 1:上传成功, 2:失败或删除, 3:审核中)',
`user_id` BIGINT NOT NULL COMMENT '上传用户ID',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
INDEX idx_user_id (user_id),
INDEX idx_file_status (file_status),
INDEX idx_file_md5 (file_md5)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文件存储表';
## 图文帖子表
@ -48,23 +61,16 @@ CREATE TABLE `post` (
`like_count` INT DEFAULT 0 COMMENT '点赞数',
`comment_count` INT DEFAULT 0 COMMENT '评论数',
`favorite_count` INT DEFAULT 0 COMMENT '收藏数',
`view_count` INT DEFAULT 0 COMMENT '浏览数',
`user_id` BIGINT NOT NULL COMMENT '发布用户ID',
`category_id` BIGINT NOT NULL COMMENT '分类ID',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`),
FOREIGN KEY (`cover_id`) REFERENCES `lj_file`(`id`)
INDEX idx_user_id (user_id),
INDEX idx_category_id (category_id),
INDEX idx_create_time (create_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='图文帖子表';
## 帖子图片关联表
DROP TABLE IF EXISTS `post_image`;
CREATE TABLE `post_image` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
`post_id` BIGINT NOT NULL COMMENT '图文帖子ID',
`file_id` BIGINT NOT NULL COMMENT '图片文件ID',
FOREIGN KEY (`post_id`) REFERENCES `post`(`id`),
FOREIGN KEY (`file_id`) REFERENCES `lj_file`(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='图文帖子与图片关联表';
## 视频表
DROP TABLE IF EXISTS `video`;
CREATE TABLE `video` (
@ -76,15 +82,17 @@ CREATE TABLE `video` (
`like_count` INT DEFAULT 0 COMMENT '点赞数',
`comment_count` INT DEFAULT 0 COMMENT '评论数',
`favorite_count` INT DEFAULT 0 COMMENT '收藏数',
`view_count` INT DEFAULT 0 COMMENT '浏览数',
`user_id` BIGINT NOT NULL COMMENT '发布用户ID',
`duration` INT NOT NULL COMMENT '视频时长(秒)',
`category` VARCHAR(50) NOT NULL COMMENT '分类(如“音乐”、“游戏”)',
`category_id` BIGINT NOT NULL COMMENT '分类ID',
`tags` VARCHAR(255) COMMENT '标签(逗号分隔)',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`),
FOREIGN KEY (`cover_id`) REFERENCES `lj_file`(`id`),
FOREIGN KEY (`video_file_id`) REFERENCES `lj_file`(`id`)
INDEX idx_user_id (user_id),
INDEX idx_category_id (category_id),
INDEX idx_duration (duration),
INDEX idx_create_time (create_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='视频表';
## 评论表
@ -99,7 +107,46 @@ CREATE TABLE `comment` (
`top_id` BIGINT COMMENT '顶层评论ID',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`)
INDEX idx_post_id (post_id),
INDEX idx_user_id (user_id),
INDEX idx_create_time (create_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='评论表';
## 点赞记录表
DROP TABLE IF EXISTS `like_record`;
CREATE TABLE `like_record` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
`user_id` BIGINT NOT NULL COMMENT '用户ID',
`post_type` VARCHAR(20) NOT NULL COMMENT '帖子类型post/video',
`post_id` BIGINT NOT NULL COMMENT '关联的帖子ID',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
INDEX idx_user_id (user_id),
INDEX idx_post_type (post_type),
INDEX idx_post_id (post_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='点赞记录表';
## 收藏记录表
DROP TABLE IF EXISTS `favorite_record`;
CREATE TABLE `favorite_record` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
`user_id` BIGINT NOT NULL COMMENT '用户ID',
`post_type` VARCHAR(20) NOT NULL COMMENT '帖子类型post/video',
`post_id` BIGINT NOT NULL COMMENT '关联的帖子ID',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
INDEX idx_user_id (user_id),
INDEX idx_post_type (post_type),
INDEX idx_post_id (post_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='收藏记录表';
## 浏览记录表
DROP TABLE IF EXISTS `view_record`;
CREATE TABLE `view_record` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
`user_id` BIGINT NOT NULL COMMENT '用户ID',
`post_type` VARCHAR(20) NOT NULL COMMENT '帖子类型post/video',
`post_id` BIGINT NOT NULL COMMENT '关联的帖子ID',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
INDEX idx_user_id (user_id),
INDEX idx_post_type (post_type),
INDEX idx_post_id (post_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='浏览记录表';

Loading…
Cancel
Save