6 Commits

Author SHA1 Message Date
1007a2a1e4 完成用户注册和展示用户收藏 2025-12-29 10:42:56 +08:00
KilLze
bd12c599b0 完成jwt拦截器和从token中获取当前登录的用户id
目前除登录以外的所有操作都会经过拦截器,可以在WebConfig中设置拦截器忽略的接口
获取用户id不需要手动输入了,直接通过UserContext获取当前登录的用户id
为动态删除,动态修改等我负责的功能添加身份验证,用户id不匹配则会跳出异常
增加token过期验证
2025-12-28 02:19:42 +08:00
KilLze
b5a15a3f01 完成jwt拦截器和从token中获取当前登录的用户id
目前除登录以外的所有操作都会经过拦截器,可以在WebConfig中设置拦截器忽略的接口
获取用户id不需要手动输入了,直接通过UserContext获取当前登录的用户id
为动态删除,动态修改等我负责的功能添加身份验证,用户id不匹配则会跳出异常
2025-12-28 02:19:41 +08:00
KilLze
039443dc0f 用户密码登录功能完成 2025-12-28 02:19:40 +08:00
bao
ae0cca5437 配置redis 2025-12-27 19:32:58 +08:00
bao
c329eaef79 增加User项目结构 2025-12-27 19:00:50 +08:00
16 changed files with 122 additions and 295 deletions

View File

@@ -1,26 +1,14 @@
package com.bao.dating.common;
/**
* 响应状态码枚举
*/
public enum ResultCode {
/** 成功 */
SUCCESS(200, "成功"),
/** 请求已成功处理 */
SUCCESS_REVIEW(201, "请求已成功处理"),
/** 删除成功 */
SUCCESS_DELETE(204, "删除成功"),
/** 参数错误 */
PARAM_ERROR(400, "参数错误"),
/** 未登录或 Token 失效 */
UNAUTHORIZED(401, "未登录或 Token 失效"),
/** 无权限 */
FORBIDDEN(403, "无权限"),
/** 数据不存在 */
NOT_FOUND(404, "数据不存在"),
/** 系统异常 */
SYSTEM_ERROR(500, "系统异常"),
/** 操作失败 */
FAIL(500, "操作失败");
private final int code;
@@ -38,4 +26,4 @@ public enum ResultCode {
public String msg() {
return msg;
}
}
}

View File

@@ -25,7 +25,9 @@ public class WebConfig implements WebMvcConfigurer {
.addPathPatterns("/**")
// 忽略的接口
.excludePathPatterns(
"/user/login"
"/user/login",
"/user/userRegister"
);
}
}

View File

@@ -36,7 +36,7 @@ public class PostController {
* @param postDTO 动态信息
* @return 发布的动态对象
*/
@PostMapping( "/createPost")
@PostMapping(consumes = "application/json")
public Result<Post> createPostJson(@RequestBody PostRequestDTO postDTO) {
// 调用 Service 层处理发布动态业务逻辑
Post result = postService.createPost(postDTO);
@@ -49,8 +49,8 @@ public class PostController {
* @param postIds 动态ID
* @return 删除结果
*/
@PostMapping("/deletePost")
public Result<String> deleteById(@RequestBody List<Long> postIds){
@DeleteMapping
public Result<String> deleteById(@RequestParam List<Long> postIds){
int deletedCount = postService.deletePostById(postIds);
return Result.success(ResultCode.SUCCESS_DELETE, deletedCount > 0 ? "成功删除" : "删除失败,该动态不存在", null);
}
@@ -60,7 +60,7 @@ public class PostController {
* @param postId 动态ID
* @return 动态对象
*/
@PostMapping("/{postId}")
@GetMapping("/{postId}")
public Result<PostEditVO> getPostById(@PathVariable Long postId) {
PostEditVO postEditVO = postService.getPostForEdit(postId);
return Result.success(ResultCode.SUCCESS,"查询成功", postEditVO);
@@ -72,7 +72,7 @@ public class PostController {
* @param postRequestDTO 动态信息
* @return 更新后的动态对象
*/
@PostMapping("/{postId}/updatePost")
@PutMapping("/{postId}")
public Result<PostEditVO> updatePost(@PathVariable Long postId, @RequestBody PostRequestDTO postRequestDTO) {
PostEditVO result = postService.updatePost(postId, postRequestDTO);
return Result.success(ResultCode.SUCCESS_REVIEW, "动态更新成功", result);

View File

@@ -2,12 +2,15 @@ package com.bao.dating.controller;
import com.bao.dating.common.Result;
import com.bao.dating.common.ResultCode;
import com.bao.dating.pojo.entity.Post;
import com.bao.dating.pojo.entity.PostFavorite;
import com.bao.dating.pojo.entity.User;
import com.bao.dating.service.PostFavoriteService;
import com.bao.dating.service.PostService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@@ -31,4 +34,11 @@ public class PostFavoriteController {
Long userId = user.getUserId();
return postFavoriteService.deletePostFavorite(userId, postId);
}
@GetMapping("/{user_id}/favorites")
public Result<List<Post>> getFavorites(@PathVariable("user_id")Long postId){
if (postId == null){
return Result.error(ResultCode.PARAM_ERROR);
}
return postFavoriteService.getAllFavoritePost(postId);
}
}

View File

@@ -2,17 +2,11 @@ package com.bao.dating.controller;
import com.bao.dating.common.Result;
import com.bao.dating.common.ResultCode;
import com.bao.dating.context.UserContext;
import com.bao.dating.pojo.dto.UserLoginDTO;
import com.bao.dating.pojo.entity.User;
import com.bao.dating.pojo.vo.UserInfoVO;
import com.bao.dating.pojo.vo.UserLoginVO;
import com.bao.dating.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
@RestController
@RequestMapping("/user")
@@ -32,35 +26,23 @@ public class UserController {
}
/**
* 获取用户信息
* @return 用户信息
* 用户注册
* @param userAccount 用户名称
* @param userPassword 用户密码
* @return 用户id
*/
@GetMapping("/info")
public Result<UserInfoVO> getUserInfo() {
Long userId = UserContext.getUserId();
UserInfoVO userInfoVO = userService.getUserInfo(userId);
return Result.success(ResultCode.SUCCESS, "获取用户信息成功", userInfoVO);
}
/**
* 上传头像接口
* @param file 头像文件
* @return 上传后的文件URL列表
*/
@PostMapping(value = "/info/uploadAvatar", consumes = "multipart/form-data")
public Result<String> uploadAvatar(@RequestParam("file") MultipartFile file) {
String fileUrl = userService.uploadAvatar(file);
return Result.success(ResultCode.SUCCESS_REVIEW, "头像上传成功", fileUrl);
}
/**
* 上传背景接口
* @param file 背景文件
* @return 上传后的文件URL列表
*/
@PostMapping(value = "/info/uploadBackground", consumes = "multipart/form-data")
public Result<String> uploadBackground(@RequestParam("file") MultipartFile file) {
String fileUrl = userService.uploadBackground(file);
return Result.success(ResultCode.SUCCESS_REVIEW, "背景上传成功", fileUrl);
@PostMapping("/userRegister")
public Result userRegister(String userAccount, String userPassword){
long result = userService.userRegister(userAccount, userPassword);
if (result == -1){
return Result.error(ResultCode.SYSTEM_ERROR);
}
if (result==-2){
return Result.error(ResultCode.PARAM_ERROR);
}
if (result == -3){
return Result.error(ResultCode.FAIL,"用户名称相同");
}
return Result.success(ResultCode.SUCCESS,"注册成功",result);
}
}

View File

@@ -1,5 +1,6 @@
package com.bao.dating.mapper;
import com.bao.dating.pojo.entity.Post;
import com.bao.dating.pojo.entity.PostFavorite;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@@ -12,4 +13,5 @@ public interface PostFavoriteMapper {
List<Long> selectUserIDByPostID(@Param("postId") Long postId);
int addPostFavorite(PostFavorite postFavorite);
int deletePostFavorite(@Param("postId") Long postId);
List<Post> getAllPost(@Param("userId") Long userId);
}

View File

@@ -20,7 +20,7 @@ public interface PostMapper {
*
* @param postIds 动态ID
*/
int deletePostByIds(List<Long> postIds);
int deletePostByIds(@Param("postIds") List<Long> postIds);
/**
* 根据ID查询动态
@@ -28,7 +28,7 @@ public interface PostMapper {
* @param postId
* @return
*/
Post selectById(Long postId);
Post selectById(@Param("postId") Long postId);
/**
* 根据ID更新动态

View File

@@ -2,7 +2,6 @@ package com.bao.dating.mapper;
import com.bao.dating.pojo.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface UserMapper {
@@ -16,10 +15,10 @@ public interface UserMapper {
User getByUsername(String username);
/**
* 根据用户id查询用户信息
*
* @param userid 用户id
* @return 用户
* 添加用户
* @param user 用户对象
* @return 受影响行数
*/
User selectByUserId(Long userid);
Long insertUser(User user);
long getMaxUserId();
}

View File

@@ -1,24 +0,0 @@
package com.bao.dating.pojo.vo;
import lombok.Data;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
/**
* 用户信息VO
*/
@Data
public class UserInfoVO {
private Long userId;
private String nickname;
private String avatarUrl;
private String backgroundUrl;
private Integer gender;
private LocalDate birthday;
private List<String> hobbies;
private String signature;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}

View File

@@ -1,10 +1,13 @@
package com.bao.dating.service;
import com.bao.dating.common.Result;
import com.bao.dating.pojo.entity.Post;
import java.util.List;
import java.util.Map;
public interface PostFavoriteService {
Result<Map<String,Long>> postFavorite(Long userid,Long postId);
Result<?> deletePostFavorite(Long userid,Long postId);
Result<List<Post>> getAllFavoritePost(Long userId);
}

View File

@@ -1,12 +1,7 @@
package com.bao.dating.service;
import com.bao.dating.pojo.dto.UserLoginDTO;
import com.bao.dating.pojo.vo.PostEditVO;
import com.bao.dating.pojo.vo.UserInfoVO;
import com.bao.dating.pojo.vo.UserLoginVO;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
public interface UserService {
/**
@@ -15,24 +10,5 @@ public interface UserService {
* @return 登录结果
*/
UserLoginVO userLogin(UserLoginDTO userLoginDTO);
/**
* 查询个人信息
* @param userId 动态ID
*/
UserInfoVO getUserInfo(Long userId);
/**
* 上传头像
* @param file 头像文件
* @return 上传后的文件URL列表
*/
String uploadAvatar(MultipartFile file);
/**
* 上传背景
* @param file 背景文件
* @return 上传后的文件URL列表
*/
String uploadBackground(MultipartFile file);
long userRegister(String userAccount, String userPassword);
}

View File

@@ -4,6 +4,7 @@ import com.bao.dating.common.Result;
import com.bao.dating.common.ResultCode;
import com.bao.dating.mapper.PostFavoriteMapper;
import com.bao.dating.mapper.PostMapper;
import com.bao.dating.pojo.entity.Post;
import com.bao.dating.pojo.entity.PostFavorite;
import com.bao.dating.service.PostFavoriteService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -58,4 +59,10 @@ public class PostFavoriteServiceImpl implements PostFavoriteService {
postMapper.decreaseFavoriteCount(postId);
return null;
}
@Override
public Result<List<Post>> getAllFavoritePost(Long userId) {
List<Post> result = postFavoriteMapper.getAllPost(userId);
return Result.success(ResultCode.SUCCESS,"查询成功",result);
}
}

View File

@@ -20,7 +20,10 @@ import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* 动态服务实现类
@@ -49,55 +52,34 @@ public class PostServiceImpl implements PostService {
*/
@Override
public List<String> uploadMedia(MultipartFile[] files) {
// 如果没有文件,则返回空列表
if (files == null || files.length == 0) {
return Collections.emptyList();
}
// 创建媒体文件列表
List<String> mediaUrls = new ArrayList<>();
if (files != null && files.length > 0) {
for (MultipartFile file : files) {
// 跳过空文件
if (file == null || file.isEmpty()) {
continue;
}
// 获取文件名并跳过空文件
String originalFilename = file.getOriginalFilename();
if (originalFilename == null) {
continue;
}
// 校验文件类型
String fileType = FileUtil.getFileType(originalFilename);
if (!"image".equals(fileType) && !"video".equals(fileType)) {
throw new RuntimeException("不支持的文件类型:" + originalFilename);
}
// 创建目录
String dir = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM"));
// 获取文件扩展名
String extension = FileUtil.getFileExtension(originalFilename);
// 生成唯一文件名
String newFileName = UUID.randomUUID().toString().replace("-", "") + "." + extension;
// 获取用户ID
Long userId = UserContext.getUserId();
// 创建文件名
String fileName = "post/" + userId + "/" + dir + "/" + newFileName;
if (!file.isEmpty()) {
try {
// 根据文件扩展名判断文件类型
String fileType = FileUtil.getFileType(file.getOriginalFilename());
// 创建目录
String dir = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM"));
// 生成唯一文件名
String newFileName = UUID.randomUUID().toString() + "." + FileUtil.getFileExtension(file.getOriginalFilename());
String fileName = "post/" + dir + "/" + newFileName;
// 获取文件字节数据
byte[] fileBytes = file.getBytes();
// 上传图片或视频
String ossUrl = ossUtil.upload(fileBytes, fileName);
if (ossUrl == null || ossUrl.isEmpty()) {
throw new RuntimeException("文件上传失败:" + originalFilename);
// 根据文件类型处理
String ossUrl = "";
if ("image".equals(fileType) || "video".equals(fileType)) {
// 上传图片或视频
ossUrl = ossUtil.upload(fileBytes, fileName);
}
// 添加上传后的 URL
mediaUrls.add(ossUrl);
} catch (IOException e) {
// 统一异常处理
throw new RuntimeException("上传媒体文件失败:" + originalFilename, e);
e.printStackTrace();
}
}
}
}
return mediaUrls;
}
@@ -206,7 +188,7 @@ public class PostServiceImpl implements PostService {
* 查询动态详情(用于编辑)
*
* @param postId 动态ID
* @return 动态详情
* @return
*/
@Override
public PostEditVO getPostForEdit(Long postId) {
@@ -228,7 +210,7 @@ public class PostServiceImpl implements PostService {
* 修改动态
* @param postId 动态ID
* @param postRequestDTO 修改的动态数据传输对象
* @return 修改的动态对象
* @return
*/
@Override
public PostEditVO updatePost(Long postId, PostRequestDTO postRequestDTO) {
@@ -243,8 +225,9 @@ public class PostServiceImpl implements PostService {
throw new RuntimeException("无权限修改此动态");
}
post.setContent(postRequestDTO.getContent());
// 如果请求中的mediaOssKeys不为null即使是空列表则更新为新值
post.setMediaOssKeys(postRequestDTO.getMediaOssKeys());
if (postRequestDTO.getMediaOssKeys() != null && !postRequestDTO.getMediaOssKeys().isEmpty()) {
post.setMediaOssKeys(postRequestDTO.getMediaOssKeys());
}
// 1. 文本内容审核
Map textResult;
@@ -256,11 +239,11 @@ public class PostServiceImpl implements PostService {
// 文本审核结果
String textSuggestion = (String) textResult.get("suggestion");
// 2. 图片审核(如果有媒体文件
if (post.getMediaOssKeys() != null && !post.getMediaOssKeys().isEmpty()) {
// 2. 图片审核(如果有)
if (postRequestDTO.getMediaOssKeys() != null && !postRequestDTO.getMediaOssKeys().isEmpty()) {
Map imageResult;
try {
imageResult = greenImageScan.imageScan(post.getMediaOssKeys());
imageResult = greenImageScan.imageScan(postRequestDTO.getMediaOssKeys());
} catch (Exception e) {
throw new RuntimeException(e);
}

View File

@@ -1,40 +1,23 @@
package com.bao.dating.service.impl;
import com.bao.dating.common.aliyun.AliOssUtil;
import com.bao.dating.context.UserContext;
import com.bao.dating.mapper.UserMapper;
import com.bao.dating.pojo.dto.UserLoginDTO;
import com.bao.dating.pojo.entity.User;
import com.bao.dating.pojo.vo.UserInfoVO;
import com.bao.dating.pojo.vo.UserLoginVO;
import com.bao.dating.service.UserService;
import com.bao.dating.util.FileUtil;
import com.bao.dating.util.JwtUtil;
import com.bao.dating.util.MD5Util;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.UUID;
import java.time.LocalDateTime;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private AliOssUtil ossUtil;
@Autowired
private UserMapper userMapper;
/**
* 用户登录
* @param userLoginDTO
* @return 登录信息
*/
@Override
public UserLoginVO userLogin(UserLoginDTO userLoginDTO) {
// 参数校验
@@ -66,95 +49,36 @@ public class UserServiceImpl implements UserService {
}
/**
* 获取用户信息
* @param userId
* @return 用户信息
* 用户注册
* @param userAccount 账户名称
* @param userPassword 密码
* @return 用户id
*/
@Override
public UserInfoVO getUserInfo(Long userId) {
User user = userMapper.selectByUserId(userId);
if (user == null){
throw new RuntimeException("用户不存在");
public long userRegister(String userAccount, String userPassword) {
//验证非空
if (userAccount.isEmpty() ||userPassword.isEmpty()){
return -2;
}
UserInfoVO userInfoVO = new UserInfoVO();
BeanUtils.copyProperties(user, userInfoVO);
return userInfoVO;
}
@Override
public String uploadAvatar(MultipartFile file) {
// 参数校验
if (file == null || file.isEmpty()) {
throw new RuntimeException("图片不存在");
//校验账户不能重复
User resultUser = userMapper.getByUsername(userAccount);
if (resultUser!=null){
return -3;
}
String originalFilename = file.getOriginalFilename();
if (originalFilename == null) {
throw new RuntimeException("文件名非法");
}
String fileType = FileUtil.getFileType(originalFilename);
if (!"image".equals(fileType)) {
throw new RuntimeException("仅支持图片上传");
}
//生成 OSS 路径
String dir = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM"));
String extension = FileUtil.getFileExtension(originalFilename);
String fileName = UUID.randomUUID().toString().replace("-", "") + "." + extension;
Long userId = UserContext.getUserId();
String objectKey = "user/" + userId + "/avatar/" + fileName;
try {
byte[] fileBytes = file.getBytes();
String ossUrl = ossUtil.upload(fileBytes, objectKey);
if (ossUrl == null || ossUrl.isEmpty()) {
throw new RuntimeException("图片上传失败");
}
return ossUrl;
} catch (Exception e) {
throw new RuntimeException("上传图片失败", e);
}
}
@Override
public String uploadBackground(MultipartFile file) {
// 参数校验
if (file == null || file.isEmpty()) {
throw new RuntimeException("图片不存在");
}
String originalFilename = file.getOriginalFilename();
if (originalFilename == null) {
throw new RuntimeException("文件名非法");
}
String fileType = FileUtil.getFileType(originalFilename);
if (!"image".equals(fileType)) {
throw new RuntimeException("仅支持图片上传");
}
//生成 OSS 路径
String extension = FileUtil.getFileExtension(originalFilename);
String fileName = UUID.randomUUID().toString().replace("-", "") + "." + extension;
Long userId = UserContext.getUserId();
String objectKey = "user/" + userId + "/background/" + fileName;
try {
byte[] fileBytes = file.getBytes();
String ossUrl = ossUtil.upload(fileBytes, objectKey);
if (ossUrl == null || ossUrl.isEmpty()) {
throw new RuntimeException("图片上传失败");
}
return ossUrl;
} catch (Exception e) {
throw new RuntimeException("上传图片失败", e);
//对密码进行加密
String encryptPassword = MD5Util.encryptWithSalt(userPassword, "yujian");
long maxUserId = userMapper.getMaxUserId();
User user = new User();
user.setUserId(maxUserId+1);
user.setUserName(userAccount);
user.setSalt("yujian");
user.setPasswordHash(encryptPassword);
user.setCreatedAt(LocalDateTime.now());
user.setUpdatedAt(LocalDateTime.now());
Long result = userMapper.insertUser(user);
if (result < 0){
return -1;
}
return user.getUserId();
}
}

View File

@@ -14,4 +14,8 @@
<select id="selectUserIDByPostID" resultType="java.lang.Long">
SELECT user_id FROM post_favorite WHERE post_id = #{postId}
</select>
<!--查询用户收藏的所有动态-->
<select id="getAllPost" resultType="com.bao.dating.pojo.entity.Post">
select * from post where post_id in (select post_id from post_favorite where user_id=#{userId})
</select>
</mapper>

View File

@@ -3,44 +3,15 @@
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bao.dating.mapper.UserMapper">
<insert id="insertUser" useGeneratedKeys="true" parameterType="com.bao.dating.pojo.entity.User">
insert into user(user_id,user_name,salt,password_hash,created_at,updated_at) values (#{userId},#{userName},#{salt},#{passwordHash},#{createdAt},#{updatedAt})
</insert>
<!--根据用户名查询用户-->
<select id="getByUsername" resultType="com.bao.dating.pojo.entity.User">
SELECT
user_id,
user_name,
password_hash,
salt,
nickname
FROM user WHERE user_name = #{userName}
SELECT * FROM user WHERE user_name = #{userName}
</select>
<!--根据用户id查询用户信息-->
<resultMap id="UserResultMap" type="com.bao.dating.pojo.entity.User">
<id property="userId" column="user_id"/>
<result property="nickname" column="nickname"/>
<result property="avatarUrl" column="avatar_url"/>
<result property="backgroundUrl" column="background_url"/>
<result property="gender" column="gender"/>
<result property="birthday" column="birthday"/>
<result property="hobbies" column="hobbies" typeHandler="com.bao.dating.handler.ListToVarcharTypeHandler"/>
<result property="signature" column="signature"/>
<result property="createdAt" column="created_at"/>
<result property="updatedAt" column="updated_at"/>
</resultMap>
<select id="selectByUserId" resultMap="UserResultMap">
SELECT
user_id,
nickname,
avatar_url,
background_url,
gender,
birthday,
hobbies,
signature,
created_at,
updated_at
FROM user WHERE user_id = #{userId}
<select id="getMaxUserId" resultType="java.lang.Long">
SELECT IFNULL(MAX(user_id), 0) AS max_id FROM user;
</select>
</mapper>