feat(biji-houdaun): 实现用户注册、登录、 Markdown 文件和图片上传功能
- 新增用户注册、登录接口及服务实现 - 添加 Markdown 文件创建、更新接口及服务实现 - 实现图片上传、获取接口及服务实现 - 集成 Snowflake ID 生成器 - 添加全局异常处理和统一返回结果封装 - 配置跨域访问和静态资源处理 - 实现基础的 XSS 防护
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
package com.test.bijihoudaun.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.test.bijihoudaun.entity.Image;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public interface ImageService extends IService<Image> {
|
||||
/**
|
||||
* 上传图片
|
||||
* @param userId 用户ID
|
||||
* @param markdownId Markdown文件ID(可选)
|
||||
* @param file 图片文件
|
||||
* @return 上传的图片对象
|
||||
* @throws IOException 文件操作异常
|
||||
*/
|
||||
Image uploadImage(Integer userId, Integer markdownId, MultipartFile file) throws IOException;
|
||||
|
||||
/**
|
||||
* 删除图片
|
||||
* @param id 图片ID
|
||||
* @param userId 用户ID(用于权限验证)
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
boolean deleteImage(Integer id, Integer userId);
|
||||
|
||||
/**
|
||||
* 获取用户的图片列表
|
||||
* @param userId 用户ID
|
||||
* @return 图片列表
|
||||
*/
|
||||
List<Image> getUserImages(Integer userId);
|
||||
|
||||
/**
|
||||
* 获取Markdown文件关联的图片
|
||||
* @param markdownId Markdown文件ID
|
||||
* @return 图片列表
|
||||
*/
|
||||
List<Image> getMarkdownImages(Integer markdownId);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.test.bijihoudaun.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.test.bijihoudaun.entity.MarkdownFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface MarkdownFileService extends IService<MarkdownFile> {
|
||||
/**
|
||||
* 创建Markdown文件
|
||||
* @param userId 用户ID
|
||||
* @param title 文件标题
|
||||
* @param fileName 文件名
|
||||
* @param content 文件内容
|
||||
* @return 创建的文件对象
|
||||
*/
|
||||
MarkdownFile createMarkdownFile(Integer userId, String title, String fileName, String content);
|
||||
|
||||
/**
|
||||
* 更新Markdown内容
|
||||
* @param id 文件ID
|
||||
* @param content 新内容
|
||||
* @return 更新后的文件对象
|
||||
*/
|
||||
MarkdownFile updateMarkdownContent(Integer id, String content);
|
||||
|
||||
/**
|
||||
* 获取用户的所有Markdown文件
|
||||
* @param userId 用户ID
|
||||
* @return 文件列表
|
||||
*/
|
||||
List<MarkdownFile> getUserFiles(Integer userId);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.test.bijihoudaun.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.test.bijihoudaun.entity.User;
|
||||
|
||||
public interface UserService extends IService<User> {
|
||||
/**
|
||||
* 用户注册
|
||||
* @param username 用户名
|
||||
* @param password 密码
|
||||
* @param email 邮箱
|
||||
* @return 注册成功的用户
|
||||
*/
|
||||
User register(String username, String password, String email);
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
* @param username 用户名
|
||||
* @param password 密码
|
||||
* @return 登录成功的用户
|
||||
*/
|
||||
User login(String username, String password);
|
||||
|
||||
/**
|
||||
* 用户删除
|
||||
* @param id 用户id
|
||||
*/
|
||||
void deleteUser(Integer id);
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.test.bijihoudaun.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.test.bijihoudaun.entity.Image;
|
||||
import com.test.bijihoudaun.mapper.ImageMapper;
|
||||
import com.test.bijihoudaun.service.ImageService;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class ImageServiceImpl
|
||||
extends ServiceImpl<ImageMapper, Image>
|
||||
implements ImageService {
|
||||
|
||||
@Value("${file.upload-dir}")
|
||||
private String uploadDir;
|
||||
|
||||
@Override
|
||||
public Image uploadImage(Integer userId, Integer markdownId, MultipartFile file) throws IOException {
|
||||
// 创建上传目录
|
||||
Path uploadPath = Paths.get(uploadDir);
|
||||
if (!Files.exists(uploadPath)) {
|
||||
Files.createDirectories(uploadPath);
|
||||
}
|
||||
|
||||
// 生成唯一文件名
|
||||
String originalFilename = file.getOriginalFilename();
|
||||
String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
|
||||
String storedName = UUID.randomUUID() + extension;
|
||||
|
||||
// 保存文件
|
||||
Path filePath = uploadPath.resolve(storedName);
|
||||
Files.copy(file.getInputStream(), filePath);
|
||||
|
||||
// 创建图片实体
|
||||
Image image = new Image();
|
||||
image.setUserId(userId);
|
||||
image.setMarkdownId(markdownId);
|
||||
image.setOriginalName(originalFilename);
|
||||
image.setStoredName(storedName);
|
||||
image.setUrl("/uploads/" + storedName);
|
||||
image.setSize((int) file.getSize());
|
||||
image.setContentType(file.getContentType());
|
||||
image.setCreatedAt(LocalDateTime.now());
|
||||
|
||||
this.save(image);
|
||||
return image;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteImage(Integer id, Integer userId) {
|
||||
QueryWrapper<Image> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("id", id)
|
||||
.eq("user_id", userId);
|
||||
|
||||
Image image = this.getOne(queryWrapper);
|
||||
if (image == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// 删除文件系统中的图片
|
||||
Path filePath = Paths.get(uploadDir, image.getStoredName());
|
||||
Files.deleteIfExists(filePath);
|
||||
|
||||
// 删除数据库记录
|
||||
this.removeById(id);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("删除图片失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Image> getUserImages(Integer userId) {
|
||||
QueryWrapper<Image> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("user_id", userId)
|
||||
.orderByDesc("created_at");
|
||||
return this.list(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Image> getMarkdownImages(Integer markdownId) {
|
||||
QueryWrapper<Image> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("markdown_id", markdownId)
|
||||
.orderByDesc("created_at");
|
||||
return this.list(queryWrapper);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.test.bijihoudaun.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.test.bijihoudaun.entity.MarkdownFile;
|
||||
import com.test.bijihoudaun.mapper.MarkdownFileMapper;
|
||||
import com.test.bijihoudaun.service.MarkdownFileService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class MarkdownFileServiceImpl
|
||||
extends ServiceImpl<MarkdownFileMapper, MarkdownFile>
|
||||
implements MarkdownFileService {
|
||||
|
||||
@Override
|
||||
public MarkdownFile createMarkdownFile(Integer userId, String title, String fileName, String content) {
|
||||
MarkdownFile file = new MarkdownFile();
|
||||
file.setUserId(userId);
|
||||
file.setTitle(title);
|
||||
file.setFileName(fileName);
|
||||
file.setContent(content);
|
||||
file.setCreatedAt(LocalDateTime.now());
|
||||
file.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
this.save(file);
|
||||
return file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkdownFile updateMarkdownContent(Integer id, String content) {
|
||||
MarkdownFile file = this.getById(id);
|
||||
if (file != null) {
|
||||
file.setContent(content);
|
||||
file.setUpdatedAt(LocalDateTime.now());
|
||||
this.updateById(file);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MarkdownFile> getUserFiles(Integer userId) {
|
||||
QueryWrapper<MarkdownFile> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("user_id", userId)
|
||||
.orderByDesc("updated_at");
|
||||
return this.list(queryWrapper);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.test.bijihoudaun.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.test.bijihoudaun.entity.User;
|
||||
import com.test.bijihoudaun.mapper.UserMapper;
|
||||
import com.test.bijihoudaun.service.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Service
|
||||
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
|
||||
|
||||
@Autowired
|
||||
private UserMapper userMapper;
|
||||
|
||||
@Override
|
||||
public User register(String username, String password, String email) {
|
||||
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(User::getUsername, username);
|
||||
if (this.count(queryWrapper) > 0) {
|
||||
return null;
|
||||
}
|
||||
queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(User::getEmail, email);
|
||||
if (this.count(queryWrapper) > 0) {
|
||||
return null;
|
||||
}
|
||||
User user = new User();
|
||||
user.setUsername(username);
|
||||
user.setPassword(password);
|
||||
user.setEmail(email);
|
||||
user.setCreatedAt(LocalDateTime.now());
|
||||
userMapper.insert(user);
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User login(String username, String password) {
|
||||
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(User::getUsername, username)
|
||||
.eq(User::getPassword, password);
|
||||
return userMapper.selectOne(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteUser(Integer id) {
|
||||
userMapper.deleteById(id);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user