From 4401a8a44a4016c5da11b30019790c6bf49104da Mon Sep 17 00:00:00 2001 From: KilLze Date: Sat, 27 Dec 2025 19:25:03 +0800 Subject: [PATCH 01/37] =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=AF=86=E7=A0=81?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E5=8A=9F=E8=83=BD=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bao/dating/controller/UserController.java | 17 +++++++- .../com/bao/dating/mapper/UserMapper.java | 9 +++++ .../com/bao/dating/pojo/dto/UserLoginDTO.java | 14 +++++++ .../com/bao/dating/service/UserService.java | 9 +++++ .../dating/service/impl/UserServiceImpl.java | 39 +++++++++++++++++++ .../com/bao/dating/mapper/UserMapper.xml | 3 ++ 6 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/bao/dating/pojo/dto/UserLoginDTO.java diff --git a/src/main/java/com/bao/dating/controller/UserController.java b/src/main/java/com/bao/dating/controller/UserController.java index 6fa9900..2aae750 100644 --- a/src/main/java/com/bao/dating/controller/UserController.java +++ b/src/main/java/com/bao/dating/controller/UserController.java @@ -1,9 +1,12 @@ package com.bao.dating.controller; +import com.bao.dating.common.Result; +import com.bao.dating.common.ResultCode; +import com.bao.dating.pojo.dto.UserLoginDTO; +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.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/user") @@ -11,4 +14,14 @@ public class UserController { @Autowired private UserService userService; + + /** + * 登录 + * @param userLoginDTO 登录参数 + */ + @PostMapping("/login") + public Result login(@RequestBody UserLoginDTO userLoginDTO) { + UserLoginVO userloginVO = userService.userLogin(userLoginDTO); + return Result.success(ResultCode.SUCCESS, "登录成功", userloginVO); + } } diff --git a/src/main/java/com/bao/dating/mapper/UserMapper.java b/src/main/java/com/bao/dating/mapper/UserMapper.java index 5f89522..89811e2 100644 --- a/src/main/java/com/bao/dating/mapper/UserMapper.java +++ b/src/main/java/com/bao/dating/mapper/UserMapper.java @@ -1,7 +1,16 @@ package com.bao.dating.mapper; +import com.bao.dating.pojo.entity.User; import org.apache.ibatis.annotations.Mapper; @Mapper public interface UserMapper { + + /** + * 根据用户名查询用户 + * + * @param username 用户名 + * @return 用户 + */ + User getByUsername(String username); } diff --git a/src/main/java/com/bao/dating/pojo/dto/UserLoginDTO.java b/src/main/java/com/bao/dating/pojo/dto/UserLoginDTO.java new file mode 100644 index 0000000..119a6cf --- /dev/null +++ b/src/main/java/com/bao/dating/pojo/dto/UserLoginDTO.java @@ -0,0 +1,14 @@ +package com.bao.dating.pojo.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 用户登录数据传输对象 + */ +@Data +public class UserLoginDTO implements Serializable { + private String username; + private String password; +} diff --git a/src/main/java/com/bao/dating/service/UserService.java b/src/main/java/com/bao/dating/service/UserService.java index f5b2a08..2c14fe4 100644 --- a/src/main/java/com/bao/dating/service/UserService.java +++ b/src/main/java/com/bao/dating/service/UserService.java @@ -1,4 +1,13 @@ package com.bao.dating.service; +import com.bao.dating.pojo.dto.UserLoginDTO; +import com.bao.dating.pojo.vo.UserLoginVO; + public interface UserService { + /** + * 登录 + * @param userLoginDTO 登录参数 + * @return 登录结果 + */ + UserLoginVO userLogin(UserLoginDTO userLoginDTO); } diff --git a/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java b/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java index 7ec6895..0d922df 100644 --- a/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java +++ b/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java @@ -1,13 +1,52 @@ package com.bao.dating.service.impl; 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.UserLoginVO; import com.bao.dating.service.UserService; +import com.bao.dating.util.JwtUtil; +import com.bao.dating.util.MD5Util; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.util.HashMap; +import java.util.Map; + @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; + + @Override + public UserLoginVO userLogin(UserLoginDTO userLoginDTO) { + // 参数校验 + if (userLoginDTO == null || userLoginDTO.getUsername() == null || userLoginDTO.getPassword() == null) { + throw new RuntimeException("用户名或密码不能为空"); + } + // 查询用户 + User user = userMapper.getByUsername(userLoginDTO.getUsername()); + if (user == null){ + throw new RuntimeException("用户不存在"); + } + // 密码加密 + boolean match = MD5Util.verifyWithSalt( + userLoginDTO.getPassword(), + user.getSalt(), + user.getPasswordHash() + ); + // 密码校验 + if (!match){ + throw new RuntimeException("密码错误"); + } + // 生成token + String token = JwtUtil.generateToken(String.valueOf(user.getUserId())); + // 封装返回 + UserLoginVO userLoginVO = new UserLoginVO(); + userLoginVO.setUserId(user.getUserId()); + userLoginVO.setNickname(user.getNickname()); + userLoginVO.setToken(token); + return userLoginVO; + } } diff --git a/src/main/resources/com/bao/dating/mapper/UserMapper.xml b/src/main/resources/com/bao/dating/mapper/UserMapper.xml index 861a043..f2736cd 100644 --- a/src/main/resources/com/bao/dating/mapper/UserMapper.xml +++ b/src/main/resources/com/bao/dating/mapper/UserMapper.xml @@ -4,5 +4,8 @@ + \ No newline at end of file From 0b0959fa8020f0c786240862dc113650e489f6a6 Mon Sep 17 00:00:00 2001 From: bao <19271189822@163.com> Date: Sat, 27 Dec 2025 19:00:50 +0800 Subject: [PATCH 02/37] =?UTF-8?q?=E5=A2=9E=E5=8A=A0User=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit c329eaef7964df56211a1c638357fe197beda36d) --- src/main/java/com/bao/dating/pojo/entity/User.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/bao/dating/pojo/entity/User.java b/src/main/java/com/bao/dating/pojo/entity/User.java index fbf6b68..db16def 100644 --- a/src/main/java/com/bao/dating/pojo/entity/User.java +++ b/src/main/java/com/bao/dating/pojo/entity/User.java @@ -38,4 +38,8 @@ public class User implements Serializable { private LocalDateTime createdAt; private LocalDateTime updatedAt; + + private String userEmail; + + private String userPhone; } From 4a2aff888a9f1dd2b6b49aee481fa3363f35cdb8 Mon Sep 17 00:00:00 2001 From: bao <19271189822@163.com> Date: Sat, 27 Dec 2025 19:32:58 +0800 Subject: [PATCH 03/37] =?UTF-8?q?=E9=85=8D=E7=BD=AEredis?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit ae0cca54375f314b7b2d0620582887af39b6d548) --- src/main/resources/application.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 062f0d5..b190806 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -7,6 +7,19 @@ spring: username: root password: JoyeeServe2025 driver-class-name: com.mysql.cj.jdbc.Driver + redis: + host: 127.0.0.1 + port: 6379 + password: "" + database: 0 + timeout: 10000 + # 连接池配置(lettuce是Spring Boot默认Redis客户端,性能更优) + lettuce: + pool: + max-active: 8 # 连接池最大连接数(默认8,可根据业务并发调整) + max-wait: -1 # 连接池最大阻塞等待时间(毫秒,-1表示无限制) + max-idle: 8 # 连接池最大空闲连接数(默认8) + min-idle: 1 # 连接池最小空闲连接数(默认0,建议设置1-4,提高连接复用率) # 邮箱SMTP配置 mail: host: smtp.163.com # QQ邮箱SMTP服务器地址 From d3c069967e1a216ff204f08f5afc9813a1b9443a Mon Sep 17 00:00:00 2001 From: KilLze Date: Sun, 28 Dec 2025 02:04:25 +0800 Subject: [PATCH 04/37] =?UTF-8?q?=E5=AE=8C=E6=88=90jwt=E6=8B=A6=E6=88=AA?= =?UTF-8?q?=E5=99=A8=E5=92=8C=E4=BB=8Etoken=E4=B8=AD=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E5=BD=93=E5=89=8D=E7=99=BB=E5=BD=95=E7=9A=84=E7=94=A8=E6=88=B7?= =?UTF-8?q?id=20=E7=9B=AE=E5=89=8D=E9=99=A4=E7=99=BB=E5=BD=95=E4=BB=A5?= =?UTF-8?q?=E5=A4=96=E7=9A=84=E6=89=80=E6=9C=89=E6=93=8D=E4=BD=9C=E9=83=BD?= =?UTF-8?q?=E4=BC=9A=E7=BB=8F=E8=BF=87=E6=8B=A6=E6=88=AA=E5=99=A8=EF=BC=8C?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E5=9C=A8WebConfig=E4=B8=AD=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E6=8B=A6=E6=88=AA=E5=99=A8=E5=BF=BD=E7=95=A5=E7=9A=84=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=20=E8=8E=B7=E5=8F=96=E7=94=A8=E6=88=B7id=E4=B8=8D?= =?UTF-8?q?=E9=9C=80=E8=A6=81=E6=89=8B=E5=8A=A8=E8=BE=93=E5=85=A5=E4=BA=86?= =?UTF-8?q?=EF=BC=8C=E7=9B=B4=E6=8E=A5=E9=80=9A=E8=BF=87UserContext?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=BD=93=E5=89=8D=E7=99=BB=E5=BD=95=E7=9A=84?= =?UTF-8?q?=E7=94=A8=E6=88=B7id=20=E4=B8=BA=E5=8A=A8=E6=80=81=E5=88=A0?= =?UTF-8?q?=E9=99=A4=EF=BC=8C=E5=8A=A8=E6=80=81=E4=BF=AE=E6=94=B9=E7=AD=89?= =?UTF-8?q?=E6=88=91=E8=B4=9F=E8=B4=A3=E7=9A=84=E5=8A=9F=E8=83=BD=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E8=BA=AB=E4=BB=BD=E9=AA=8C=E8=AF=81=EF=BC=8C=E7=94=A8?= =?UTF-8?q?=E6=88=B7id=E4=B8=8D=E5=8C=B9=E9=85=8D=E5=88=99=E4=BC=9A?= =?UTF-8?q?=E8=B7=B3=E5=87=BA=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/bao/dating/config/WebConfig.java | 31 ++++++++ .../com/bao/dating/context/UserContext.java | 33 +++++++++ .../bao/dating/controller/PostController.java | 5 +- .../dating/interceptor/TokenInterceptor.java | 70 +++++++++++++++++++ .../com/bao/dating/service/PostService.java | 3 +- .../dating/service/impl/PostServiceImpl.java | 30 +++++++- .../dating/service/impl/UserServiceImpl.java | 6 +- 7 files changed, 165 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/bao/dating/config/WebConfig.java create mode 100644 src/main/java/com/bao/dating/context/UserContext.java create mode 100644 src/main/java/com/bao/dating/interceptor/TokenInterceptor.java diff --git a/src/main/java/com/bao/dating/config/WebConfig.java b/src/main/java/com/bao/dating/config/WebConfig.java new file mode 100644 index 0000000..a7ff5fd --- /dev/null +++ b/src/main/java/com/bao/dating/config/WebConfig.java @@ -0,0 +1,31 @@ +package com.bao.dating.config; + + +import com.bao.dating.interceptor.TokenInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + @Autowired + private TokenInterceptor tokenInterceptor; + + /** + * 添加拦截器到Spring MVC配置中 + * @param registry 拦截器注册中心 + */ + @Override + public void addInterceptors(InterceptorRegistry registry) { + //注册自定义拦截器对象 + registry.addInterceptor(tokenInterceptor) + // 拦截所有请求 + .addPathPatterns("/**") + // 忽略的接口 + .excludePathPatterns( + "/user/login" + ); + } +} diff --git a/src/main/java/com/bao/dating/context/UserContext.java b/src/main/java/com/bao/dating/context/UserContext.java new file mode 100644 index 0000000..df2cfbd --- /dev/null +++ b/src/main/java/com/bao/dating/context/UserContext.java @@ -0,0 +1,33 @@ +package com.bao.dating.context; + +/** + * 用户上下文类 + * @author lenovo + */ +public class UserContext { + + private static final ThreadLocal userHolder = new ThreadLocal<>(); + + /** + * 设置当前线程的用户ID + * @param userId 用户ID + */ + public static void setUserId(Long userId) { + userHolder.set(userId); + } + + /** + * 获取当前线程的用户ID + * @return 当前用户ID,如果未设置则返回null + */ + public static Long getUserId() { + return userHolder.get(); + } + + /** + * 清除当前线程的用户ID + */ + public static void clear() { + userHolder.remove(); + } +} diff --git a/src/main/java/com/bao/dating/controller/PostController.java b/src/main/java/com/bao/dating/controller/PostController.java index b7c284f..2541283 100644 --- a/src/main/java/com/bao/dating/controller/PostController.java +++ b/src/main/java/com/bao/dating/controller/PostController.java @@ -34,13 +34,12 @@ public class PostController { /** * 发布动态接口 - JSON格式请求 * @param postDTO 动态信息 - * @param userId 用户ID * @return 发布的动态对象 */ @PostMapping(consumes = "application/json") - public Result createPostJson(@RequestBody PostRequestDTO postDTO, @RequestParam Long userId) { + public Result createPostJson(@RequestBody PostRequestDTO postDTO) { // 调用 Service 层处理发布动态业务逻辑 - Post result = postService.createPost(userId, postDTO); + Post result = postService.createPost(postDTO); return Result.success(ResultCode.SUCCESS_REVIEW, "动态发布成功,等待审核。", result); } diff --git a/src/main/java/com/bao/dating/interceptor/TokenInterceptor.java b/src/main/java/com/bao/dating/interceptor/TokenInterceptor.java new file mode 100644 index 0000000..ed0102f --- /dev/null +++ b/src/main/java/com/bao/dating/interceptor/TokenInterceptor.java @@ -0,0 +1,70 @@ +package com.bao.dating.interceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.bao.dating.context.UserContext; +import com.bao.dating.util.JwtUtil; +import io.jsonwebtoken.Claims; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +/** + * HttpToken拦截器类 + * 用于拦截请求并验证JWT token的有效性,同时从token中解析用户信息 + */ +@Slf4j +@Component +public class TokenInterceptor implements HandlerInterceptor { + /** + * 在请求处理之前进行拦截 + * 从请求头或URL参数中获取token,验证其有效性,并将用户ID保存到ThreadLocal中 + * @param request HTTP请求对象 + * @param response HTTP响应对象 + * @param handler 处理器 + * @return 验证通过返回true,否则返回false + * @throws Exception 异常 + */ + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + + //判断当前拦截到的是Controller的方法还是其他资源 + if (!(handler instanceof HandlerMethod)) { + //当前拦截到的不是动态方法,直接放行 + return true; + } + // 从 header 获取 token + String token = request.getHeader("token"); + + try { + log.info("jwt校验:{}", token); + // 解析 token + String userId = JwtUtil.getSubjectFromToken(token); + log.info("用户:{}", userId); + // 保存 userId 到 ThreadLocal + UserContext.setUserId(Long.valueOf(userId)); + return true; + } catch (Exception e) { + log.error("Token 校验失败: {}", e.getMessage()); + response.setStatus(401); + return false; + } + } + + /** + * 在请求完成之后执行清理工作 + * 清除保存在ThreadLocal中的用户ID,防止内存泄漏 + * @param request HTTP请求对象 + * @param response HTTP响应对象 + * @param handler 处理器 + * @param ex 异常对象 + * @throws Exception 异常 + */ + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { + UserContext.clear(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/bao/dating/service/PostService.java b/src/main/java/com/bao/dating/service/PostService.java index 6600836..c29c887 100644 --- a/src/main/java/com/bao/dating/service/PostService.java +++ b/src/main/java/com/bao/dating/service/PostService.java @@ -17,11 +17,10 @@ public interface PostService { /** * 创建动态 - * @param userId 用户ID * @param postRequestDTO 动态数据传输对象 * @return 创建的动态对象 */ - Post createPost(Long userId, PostRequestDTO postRequestDTO); + Post createPost(PostRequestDTO postRequestDTO); /** * 批量删除动态 diff --git a/src/main/java/com/bao/dating/service/impl/PostServiceImpl.java b/src/main/java/com/bao/dating/service/impl/PostServiceImpl.java index 4381790..f83db47 100644 --- a/src/main/java/com/bao/dating/service/impl/PostServiceImpl.java +++ b/src/main/java/com/bao/dating/service/impl/PostServiceImpl.java @@ -2,6 +2,7 @@ package com.bao.dating.service.impl; import com.bao.dating.common.aliyun.GreenImageScan; import com.bao.dating.common.aliyun.GreenTextScan; +import com.bao.dating.context.UserContext; import com.bao.dating.mapper.PostMapper; import com.bao.dating.pojo.dto.PostRequestDTO; import com.bao.dating.pojo.entity.Post; @@ -85,15 +86,15 @@ public class PostServiceImpl implements PostService { /** * 创建动态 * - * @param userId 用户ID * @param postRequestDTO 动态数据传输对象 * @return 创建的动态对象 */ @Override - public Post createPost(Long userId, PostRequestDTO postRequestDTO) { + public Post createPost(PostRequestDTO postRequestDTO) { // 创建动态对象 Post post = new Post(); + Long userId = UserContext.getUserId(); post.setUserId(userId); post.setContent(postRequestDTO.getContent()); post.setTags(postRequestDTO.getTags()); @@ -165,6 +166,20 @@ public class PostServiceImpl implements PostService { @Override @Transactional(rollbackFor = Exception.class) public int deletePostById(List postIds) { + // 判断用户权限 + Long userId = UserContext.getUserId(); + + // 遍历所有要删除的帖子ID,验证权限 + for (Long postId : postIds) { + Post post = postMapper.selectById(postId); + if (post == null) { + throw new RuntimeException("动态不存在"); + } + // 验证用户权限 + if (post.getUserId() == null || !post.getUserId().equals(userId)) { + throw new RuntimeException("无权限删除此动态"); + } + } // 批量删除动态 return postMapper.deletePostByIds(postIds); } @@ -177,11 +192,15 @@ public class PostServiceImpl implements PostService { */ @Override public PostEditVO getPostForEdit(Long postId) { - Post post = postMapper.selectById(postId); if (post == null) { throw new RuntimeException("动态不存在"); } + // 判断用户权限 + Long userId = UserContext.getUserId(); + if (post.getUserId() == null || !post.getUserId().equals(userId)){ + throw new RuntimeException("无权限查看此动态"); + } PostEditVO postEditVO = new PostEditVO(); BeanUtils.copyProperties(post, postEditVO); return postEditVO; @@ -200,6 +219,11 @@ public class PostServiceImpl implements PostService { if (post == null) { throw new RuntimeException("动态不存在"); } + // 判断用户权限 + Long userId = UserContext.getUserId(); + if (post.getUserId() == null || !post.getUserId().equals(userId)){ + throw new RuntimeException("无权限修改此动态"); + } post.setContent(postRequestDTO.getContent()); if (postRequestDTO.getMediaOssKeys() != null && !postRequestDTO.getMediaOssKeys().isEmpty()) { post.setMediaOssKeys(postRequestDTO.getMediaOssKeys()); diff --git a/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java b/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java index 0d922df..59f77d6 100644 --- a/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java +++ b/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java @@ -10,9 +10,6 @@ import com.bao.dating.util.MD5Util; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.HashMap; -import java.util.Map; - @Service public class UserServiceImpl implements UserService { @@ -30,13 +27,12 @@ public class UserServiceImpl implements UserService { if (user == null){ throw new RuntimeException("用户不存在"); } - // 密码加密 + // 密码校验 boolean match = MD5Util.verifyWithSalt( userLoginDTO.getPassword(), user.getSalt(), user.getPasswordHash() ); - // 密码校验 if (!match){ throw new RuntimeException("密码错误"); } From 4c70bd3c6f525dc277ecb7ccff0f6a27ea2c5aea Mon Sep 17 00:00:00 2001 From: KilLze Date: Sun, 28 Dec 2025 02:17:09 +0800 Subject: [PATCH 05/37] =?UTF-8?q?=E5=AE=8C=E6=88=90jwt=E6=8B=A6=E6=88=AA?= =?UTF-8?q?=E5=99=A8=E5=92=8C=E4=BB=8Etoken=E4=B8=AD=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E5=BD=93=E5=89=8D=E7=99=BB=E5=BD=95=E7=9A=84=E7=94=A8=E6=88=B7?= =?UTF-8?q?id=20=E7=9B=AE=E5=89=8D=E9=99=A4=E7=99=BB=E5=BD=95=E4=BB=A5?= =?UTF-8?q?=E5=A4=96=E7=9A=84=E6=89=80=E6=9C=89=E6=93=8D=E4=BD=9C=E9=83=BD?= =?UTF-8?q?=E4=BC=9A=E7=BB=8F=E8=BF=87=E6=8B=A6=E6=88=AA=E5=99=A8=EF=BC=8C?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E5=9C=A8WebConfig=E4=B8=AD=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E6=8B=A6=E6=88=AA=E5=99=A8=E5=BF=BD=E7=95=A5=E7=9A=84=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=20=E8=8E=B7=E5=8F=96=E7=94=A8=E6=88=B7id=E4=B8=8D?= =?UTF-8?q?=E9=9C=80=E8=A6=81=E6=89=8B=E5=8A=A8=E8=BE=93=E5=85=A5=E4=BA=86?= =?UTF-8?q?=EF=BC=8C=E7=9B=B4=E6=8E=A5=E9=80=9A=E8=BF=87UserContext?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=BD=93=E5=89=8D=E7=99=BB=E5=BD=95=E7=9A=84?= =?UTF-8?q?=E7=94=A8=E6=88=B7id=20=E4=B8=BA=E5=8A=A8=E6=80=81=E5=88=A0?= =?UTF-8?q?=E9=99=A4=EF=BC=8C=E5=8A=A8=E6=80=81=E4=BF=AE=E6=94=B9=E7=AD=89?= =?UTF-8?q?=E6=88=91=E8=B4=9F=E8=B4=A3=E7=9A=84=E5=8A=9F=E8=83=BD=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E8=BA=AB=E4=BB=BD=E9=AA=8C=E8=AF=81=EF=BC=8C=E7=94=A8?= =?UTF-8?q?=E6=88=B7id=E4=B8=8D=E5=8C=B9=E9=85=8D=E5=88=99=E4=BC=9A?= =?UTF-8?q?=E8=B7=B3=E5=87=BA=E5=BC=82=E5=B8=B8=20=E5=A2=9E=E5=8A=A0token?= =?UTF-8?q?=E8=BF=87=E6=9C=9F=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bao/dating/interceptor/TokenInterceptor.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/bao/dating/interceptor/TokenInterceptor.java b/src/main/java/com/bao/dating/interceptor/TokenInterceptor.java index ed0102f..29ab4a1 100644 --- a/src/main/java/com/bao/dating/interceptor/TokenInterceptor.java +++ b/src/main/java/com/bao/dating/interceptor/TokenInterceptor.java @@ -37,12 +37,21 @@ public class TokenInterceptor implements HandlerInterceptor { } // 从 header 获取 token String token = request.getHeader("token"); - + try { - log.info("jwt校验:{}", token); + log.info("jwt校验: {}", token); + + // 验证 token 是否有效(包括是否过期) + if (!JwtUtil.validateToken(token)) { + log.error("Token 无效或已过期"); + response.setStatus(401); + return false; + } + // 解析 token String userId = JwtUtil.getSubjectFromToken(token); - log.info("用户:{}", userId); + log.info("用户: {}", userId); + // 保存 userId 到 ThreadLocal UserContext.setUserId(Long.valueOf(userId)); return true; From dfc9508827d9ef47fa6a3c9830bf5f89b2fcd6e1 Mon Sep 17 00:00:00 2001 From: KilLze Date: Sun, 28 Dec 2025 02:17:09 +0800 Subject: [PATCH 06/37] =?UTF-8?q?=E4=BF=AEbug=EF=BC=8C=E9=A1=BA=E4=BE=BF?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=8E=A5=E5=8F=A3=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/bao/dating/controller/PostController.java | 8 ++++---- .../com/bao/dating/service/impl/PostServiceImpl.java | 11 +++++------ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/bao/dating/controller/PostController.java b/src/main/java/com/bao/dating/controller/PostController.java index 2541283..62443c0 100644 --- a/src/main/java/com/bao/dating/controller/PostController.java +++ b/src/main/java/com/bao/dating/controller/PostController.java @@ -36,7 +36,7 @@ public class PostController { * @param postDTO 动态信息 * @return 发布的动态对象 */ - @PostMapping(consumes = "application/json") + @PostMapping( "/addPost") public Result createPostJson(@RequestBody PostRequestDTO postDTO) { // 调用 Service 层处理发布动态业务逻辑 Post result = postService.createPost(postDTO); @@ -49,7 +49,7 @@ public class PostController { * @param postIds 动态ID * @return 删除结果 */ - @DeleteMapping + @PostMapping("/deletePost") public Result deleteById(@RequestParam List 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 动态对象 */ - @GetMapping("/{postId}") + @PostMapping("/postById/{postId}") public Result 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 更新后的动态对象 */ - @PutMapping("/{postId}") + @PostMapping("/updatePost/{postId}") public Result updatePost(@PathVariable Long postId, @RequestBody PostRequestDTO postRequestDTO) { PostEditVO result = postService.updatePost(postId, postRequestDTO); return Result.success(ResultCode.SUCCESS_REVIEW, "动态更新成功", result); diff --git a/src/main/java/com/bao/dating/service/impl/PostServiceImpl.java b/src/main/java/com/bao/dating/service/impl/PostServiceImpl.java index f83db47..bdbd921 100644 --- a/src/main/java/com/bao/dating/service/impl/PostServiceImpl.java +++ b/src/main/java/com/bao/dating/service/impl/PostServiceImpl.java @@ -225,9 +225,8 @@ public class PostServiceImpl implements PostService { throw new RuntimeException("无权限修改此动态"); } post.setContent(postRequestDTO.getContent()); - if (postRequestDTO.getMediaOssKeys() != null && !postRequestDTO.getMediaOssKeys().isEmpty()) { - post.setMediaOssKeys(postRequestDTO.getMediaOssKeys()); - } + // 如果请求中的mediaOssKeys不为null(即使是空列表),则更新为新值 + post.setMediaOssKeys(postRequestDTO.getMediaOssKeys()); // 1. 文本内容审核 Map textResult; @@ -239,11 +238,11 @@ public class PostServiceImpl implements PostService { // 文本审核结果 String textSuggestion = (String) textResult.get("suggestion"); - // 2. 图片审核(如果有) - if (postRequestDTO.getMediaOssKeys() != null && !postRequestDTO.getMediaOssKeys().isEmpty()) { + // 2. 图片审核(如果有媒体文件) + if (post.getMediaOssKeys() != null && !post.getMediaOssKeys().isEmpty()) { Map imageResult; try { - imageResult = greenImageScan.imageScan(postRequestDTO.getMediaOssKeys()); + imageResult = greenImageScan.imageScan(post.getMediaOssKeys()); } catch (Exception e) { throw new RuntimeException(e); } From 7abd6fe27d32ed6341aa98996eaa2fb055c8b3d7 Mon Sep 17 00:00:00 2001 From: KilLze Date: Sun, 28 Dec 2025 17:53:16 +0800 Subject: [PATCH 07/37] =?UTF-8?q?=E4=BF=AEbug=EF=BC=8C=E9=A1=BA=E4=BE=BF?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=8E=A5=E5=8F=A3=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/bao/dating/controller/PostController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/bao/dating/controller/PostController.java b/src/main/java/com/bao/dating/controller/PostController.java index 62443c0..34c18c5 100644 --- a/src/main/java/com/bao/dating/controller/PostController.java +++ b/src/main/java/com/bao/dating/controller/PostController.java @@ -60,7 +60,7 @@ public class PostController { * @param postId 动态ID * @return 动态对象 */ - @PostMapping("/postById/{postId}") + @PostMapping("/{postId}") public Result 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("/updatePost/{postId}") + @PostMapping("/{postId}/updatePost") public Result updatePost(@PathVariable Long postId, @RequestBody PostRequestDTO postRequestDTO) { PostEditVO result = postService.updatePost(postId, postRequestDTO); return Result.success(ResultCode.SUCCESS_REVIEW, "动态更新成功", result); From 2cb8ae5c3c5a2ba9f0b9acc57ad920d7d44b9743 Mon Sep 17 00:00:00 2001 From: KilLze Date: Sun, 28 Dec 2025 18:05:47 +0800 Subject: [PATCH 08/37] =?UTF-8?q?=E4=BF=AEbug=EF=BC=8C=E9=A1=BA=E4=BE=BF?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=8E=A5=E5=8F=A3=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/bao/dating/controller/PostController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/bao/dating/controller/PostController.java b/src/main/java/com/bao/dating/controller/PostController.java index 34c18c5..94fc92e 100644 --- a/src/main/java/com/bao/dating/controller/PostController.java +++ b/src/main/java/com/bao/dating/controller/PostController.java @@ -36,7 +36,7 @@ public class PostController { * @param postDTO 动态信息 * @return 发布的动态对象 */ - @PostMapping( "/addPost") + @PostMapping( "/createPost") public Result createPostJson(@RequestBody PostRequestDTO postDTO) { // 调用 Service 层处理发布动态业务逻辑 Post result = postService.createPost(postDTO); @@ -50,7 +50,7 @@ public class PostController { * @return 删除结果 */ @PostMapping("/deletePost") - public Result deleteById(@RequestParam List postIds){ + public Result deleteById(@RequestBody List postIds){ int deletedCount = postService.deletePostById(postIds); return Result.success(ResultCode.SUCCESS_DELETE, deletedCount > 0 ? "成功删除" : "删除失败,该动态不存在", null); } From 0f8f47de8e727021bc780c3a63ff7845e475bc18 Mon Sep 17 00:00:00 2001 From: KilLze Date: Sun, 28 Dec 2025 19:57:05 +0800 Subject: [PATCH 09/37] =?UTF-8?q?=E7=94=A8=E6=88=B7=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E4=B8=AA=E4=BA=BA=E4=BF=A1=E6=81=AF=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bao/dating/controller/UserController.java | 10 +++++ .../com/bao/dating/mapper/PostMapper.java | 4 +- .../com/bao/dating/mapper/UserMapper.java | 9 +++++ .../com/bao/dating/pojo/vo/UserInfoVO.java | 23 +++++++++++ .../com/bao/dating/service/UserService.java | 8 ++++ .../dating/service/impl/PostServiceImpl.java | 4 +- .../dating/service/impl/UserServiceImpl.java | 23 +++++++++++ .../com/bao/dating/mapper/UserMapper.xml | 39 ++++++++++++++++++- 8 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/bao/dating/pojo/vo/UserInfoVO.java diff --git a/src/main/java/com/bao/dating/controller/UserController.java b/src/main/java/com/bao/dating/controller/UserController.java index 2aae750..5c2f323 100644 --- a/src/main/java/com/bao/dating/controller/UserController.java +++ b/src/main/java/com/bao/dating/controller/UserController.java @@ -2,7 +2,10 @@ 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; @@ -24,4 +27,11 @@ public class UserController { UserLoginVO userloginVO = userService.userLogin(userLoginDTO); return Result.success(ResultCode.SUCCESS, "登录成功", userloginVO); } + + @GetMapping("/info") + public Result getUserInfo() { + Long userId = UserContext.getUserId(); + UserInfoVO userInfoVO = userService.getUserInfo(userId); + return Result.success(ResultCode.SUCCESS, "获取用户信息成功", userInfoVO); + } } diff --git a/src/main/java/com/bao/dating/mapper/PostMapper.java b/src/main/java/com/bao/dating/mapper/PostMapper.java index 8cd4943..fd30d09 100644 --- a/src/main/java/com/bao/dating/mapper/PostMapper.java +++ b/src/main/java/com/bao/dating/mapper/PostMapper.java @@ -20,7 +20,7 @@ public interface PostMapper { * * @param postIds 动态ID */ - int deletePostByIds(@Param("postIds") List postIds); + int deletePostByIds(List postIds); /** * 根据ID查询动态 @@ -28,7 +28,7 @@ public interface PostMapper { * @param postId * @return */ - Post selectById(@Param("postId") Long postId); + Post selectById(Long postId); /** * 根据ID更新动态 diff --git a/src/main/java/com/bao/dating/mapper/UserMapper.java b/src/main/java/com/bao/dating/mapper/UserMapper.java index 89811e2..1e28552 100644 --- a/src/main/java/com/bao/dating/mapper/UserMapper.java +++ b/src/main/java/com/bao/dating/mapper/UserMapper.java @@ -2,6 +2,7 @@ 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 { @@ -13,4 +14,12 @@ public interface UserMapper { * @return 用户 */ User getByUsername(String username); + + /** + * 根据用户id查询用户信息 + * + * @param userid 用户id + * @return 用户 + */ + User selectByUserId(Long userid); } diff --git a/src/main/java/com/bao/dating/pojo/vo/UserInfoVO.java b/src/main/java/com/bao/dating/pojo/vo/UserInfoVO.java new file mode 100644 index 0000000..1fcbf05 --- /dev/null +++ b/src/main/java/com/bao/dating/pojo/vo/UserInfoVO.java @@ -0,0 +1,23 @@ +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 hobbies; + private String signature; + private LocalDateTime createdAt; +} diff --git a/src/main/java/com/bao/dating/service/UserService.java b/src/main/java/com/bao/dating/service/UserService.java index 2c14fe4..01f4e41 100644 --- a/src/main/java/com/bao/dating/service/UserService.java +++ b/src/main/java/com/bao/dating/service/UserService.java @@ -1,6 +1,8 @@ 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; public interface UserService { @@ -10,4 +12,10 @@ public interface UserService { * @return 登录结果 */ UserLoginVO userLogin(UserLoginDTO userLoginDTO); + + /** + * 查询个人信息 + * @param userId 动态ID + */ + UserInfoVO getUserInfo(Long userId); } diff --git a/src/main/java/com/bao/dating/service/impl/PostServiceImpl.java b/src/main/java/com/bao/dating/service/impl/PostServiceImpl.java index bdbd921..c4b323b 100644 --- a/src/main/java/com/bao/dating/service/impl/PostServiceImpl.java +++ b/src/main/java/com/bao/dating/service/impl/PostServiceImpl.java @@ -188,7 +188,7 @@ public class PostServiceImpl implements PostService { * 查询动态详情(用于编辑) * * @param postId 动态ID - * @return + * @return 动态详情 */ @Override public PostEditVO getPostForEdit(Long postId) { @@ -210,7 +210,7 @@ public class PostServiceImpl implements PostService { * 修改动态 * @param postId 动态ID * @param postRequestDTO 修改的动态数据传输对象 - * @return + * @return 修改的动态对象 */ @Override public PostEditVO updatePost(Long postId, PostRequestDTO postRequestDTO) { diff --git a/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java b/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java index 59f77d6..43f854c 100644 --- a/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java +++ b/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java @@ -3,10 +3,12 @@ package com.bao.dating.service.impl; 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.JwtUtil; import com.bao.dating.util.MD5Util; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -16,6 +18,11 @@ public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; + /** + * 用户登录 + * @param userLoginDTO + * @return 登录信息 + */ @Override public UserLoginVO userLogin(UserLoginDTO userLoginDTO) { // 参数校验 @@ -45,4 +52,20 @@ public class UserServiceImpl implements UserService { userLoginVO.setToken(token); return userLoginVO; } + + /** + * 获取用户信息 + * @param userId + * @return 用户信息 + */ + @Override + public UserInfoVO getUserInfo(Long userId) { + User user = userMapper.selectByUserId(userId); + if (user == null){ + throw new RuntimeException("用户不存在"); + } + UserInfoVO userInfoVO = new UserInfoVO(); + BeanUtils.copyProperties(user, userInfoVO); + return userInfoVO; + } } diff --git a/src/main/resources/com/bao/dating/mapper/UserMapper.xml b/src/main/resources/com/bao/dating/mapper/UserMapper.xml index f2736cd..6d6343a 100644 --- a/src/main/resources/com/bao/dating/mapper/UserMapper.xml +++ b/src/main/resources/com/bao/dating/mapper/UserMapper.xml @@ -4,8 +4,43 @@ - + SELECT + user_id, + user_name, + password_hash, + salt, + nickname + FROM user WHERE user_name = #{userName} + + + + + + + + + + + + + + + + \ No newline at end of file From fca54a6f972ac8d482947a8eccbf147dfa7b7467 Mon Sep 17 00:00:00 2001 From: KilLze Date: Sun, 28 Dec 2025 21:10:55 +0800 Subject: [PATCH 10/37] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=A4=B4=E5=83=8F?= =?UTF-8?q?=E5=92=8C=E8=83=8C=E6=99=AF=E4=B8=8A=E4=BC=A0=EF=BC=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=8A=A8=E6=80=81=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=EF=BC=8C=E4=BF=AEbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bao/dating/controller/UserController.java | 29 ++++++ .../com/bao/dating/pojo/vo/UserInfoVO.java | 1 + .../com/bao/dating/service/UserService.java | 17 ++++ .../dating/service/impl/PostServiceImpl.java | 60 ++++++++----- .../dating/service/impl/UserServiceImpl.java | 89 +++++++++++++++++++ 5 files changed, 175 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/bao/dating/controller/UserController.java b/src/main/java/com/bao/dating/controller/UserController.java index 5c2f323..d530366 100644 --- a/src/main/java/com/bao/dating/controller/UserController.java +++ b/src/main/java/com/bao/dating/controller/UserController.java @@ -10,6 +10,9 @@ 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") @@ -28,10 +31,36 @@ public class UserController { return Result.success(ResultCode.SUCCESS, "登录成功", userloginVO); } + /** + * 获取用户信息 + * @return 用户信息 + */ @GetMapping("/info") public Result 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 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 uploadBackground(@RequestParam("file") MultipartFile file) { + String fileUrl = userService.uploadBackground(file); + return Result.success(ResultCode.SUCCESS_REVIEW, "背景上传成功", fileUrl); + } } diff --git a/src/main/java/com/bao/dating/pojo/vo/UserInfoVO.java b/src/main/java/com/bao/dating/pojo/vo/UserInfoVO.java index 1fcbf05..83fd640 100644 --- a/src/main/java/com/bao/dating/pojo/vo/UserInfoVO.java +++ b/src/main/java/com/bao/dating/pojo/vo/UserInfoVO.java @@ -20,4 +20,5 @@ public class UserInfoVO { private List hobbies; private String signature; private LocalDateTime createdAt; + private LocalDateTime updatedAt; } diff --git a/src/main/java/com/bao/dating/service/UserService.java b/src/main/java/com/bao/dating/service/UserService.java index 01f4e41..ab5ed64 100644 --- a/src/main/java/com/bao/dating/service/UserService.java +++ b/src/main/java/com/bao/dating/service/UserService.java @@ -4,6 +4,9 @@ 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 { /** @@ -18,4 +21,18 @@ public interface UserService { * @param userId 动态ID */ UserInfoVO getUserInfo(Long userId); + + /** + * 上传头像 + * @param file 头像文件 + * @return 上传后的文件URL列表 + */ + String uploadAvatar(MultipartFile file); + + /** + * 上传背景 + * @param file 背景文件 + * @return 上传后的文件URL列表 + */ + String uploadBackground(MultipartFile file); } diff --git a/src/main/java/com/bao/dating/service/impl/PostServiceImpl.java b/src/main/java/com/bao/dating/service/impl/PostServiceImpl.java index c4b323b..e759ddc 100644 --- a/src/main/java/com/bao/dating/service/impl/PostServiceImpl.java +++ b/src/main/java/com/bao/dating/service/impl/PostServiceImpl.java @@ -20,10 +20,7 @@ import java.io.IOException; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.UUID; +import java.util.*; /** * 动态服务实现类 @@ -52,34 +49,55 @@ public class PostServiceImpl implements PostService { */ @Override public List uploadMedia(MultipartFile[] files) { + // 如果没有文件,则返回空列表 + if (files == null || files.length == 0) { + return Collections.emptyList(); + } + // 创建媒体文件列表 List mediaUrls = new ArrayList<>(); - if (files != null && files.length > 0) { + for (MultipartFile file : files) { - if (!file.isEmpty()) { + // 跳过空文件 + 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; + 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 = ""; - if ("image".equals(fileType) || "video".equals(fileType)) { - // 上传图片或视频 - ossUrl = ossUtil.upload(fileBytes, fileName); + // 上传图片或视频 + String ossUrl = ossUtil.upload(fileBytes, fileName); + if (ossUrl == null || ossUrl.isEmpty()) { + throw new RuntimeException("文件上传失败:" + originalFilename); } // 添加上传后的 URL mediaUrls.add(ossUrl); } catch (IOException e) { - e.printStackTrace(); + // 统一异常处理 + throw new RuntimeException("上传媒体文件失败:" + originalFilename, e); } } - } - } return mediaUrls; } diff --git a/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java b/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java index 43f854c..3aac7da 100644 --- a/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java +++ b/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java @@ -1,20 +1,32 @@ 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; @Service public class UserServiceImpl implements UserService { + @Autowired + private AliOssUtil ossUtil; + @Autowired private UserMapper userMapper; @@ -68,4 +80,81 @@ public class UserServiceImpl implements UserService { BeanUtils.copyProperties(user, userInfoVO); return userInfoVO; } + + @Override + public String uploadAvatar(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 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); + } + } } From 96b256d46eccb1139ac0e2b56d7eb85571deac41 Mon Sep 17 00:00:00 2001 From: KilLze Date: Sun, 28 Dec 2025 21:14:30 +0800 Subject: [PATCH 11/37] =?UTF-8?q?=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/bao/dating/common/ResultCode.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/bao/dating/common/ResultCode.java b/src/main/java/com/bao/dating/common/ResultCode.java index d577366..fb89f00 100644 --- a/src/main/java/com/bao/dating/common/ResultCode.java +++ b/src/main/java/com/bao/dating/common/ResultCode.java @@ -1,14 +1,26 @@ 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; @@ -26,4 +38,4 @@ public enum ResultCode { public String msg() { return msg; } -} +} \ No newline at end of file From cd0abad22583c2e518eb4853f5e9118f702c96ea Mon Sep 17 00:00:00 2001 From: KilLze Date: Mon, 29 Dec 2025 11:59:33 +0800 Subject: [PATCH 12/37] =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E4=B8=AA=E4=BA=BA=E4=BF=A1=E6=81=AF=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bao/dating/controller/UserController.java | 14 ++++++++ .../com/bao/dating/mapper/UserMapper.java | 10 +++++- .../dating/pojo/dto/UserInfoUpdateDTO.java | 20 ++++++++++++ .../java/com/bao/dating/pojo/entity/User.java | 3 +- .../com/bao/dating/pojo/vo/UserInfoVO.java | 2 +- .../com/bao/dating/service/UserService.java | 7 ++++ .../dating/service/impl/UserServiceImpl.java | 32 +++++++++++++++++++ .../com/bao/dating/mapper/UserMapper.xml | 29 +++++++++++++++++ 8 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/bao/dating/pojo/dto/UserInfoUpdateDTO.java diff --git a/src/main/java/com/bao/dating/controller/UserController.java b/src/main/java/com/bao/dating/controller/UserController.java index d530366..355f8b7 100644 --- a/src/main/java/com/bao/dating/controller/UserController.java +++ b/src/main/java/com/bao/dating/controller/UserController.java @@ -3,6 +3,7 @@ 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.UserInfoUpdateDTO; import com.bao.dating.pojo.dto.UserLoginDTO; import com.bao.dating.pojo.entity.User; import com.bao.dating.pojo.vo.UserInfoVO; @@ -63,4 +64,17 @@ public class UserController { String fileUrl = userService.uploadBackground(file); return Result.success(ResultCode.SUCCESS_REVIEW, "背景上传成功", fileUrl); } + + /** + * 更新用户信息 + * @param userInfoUpdateDTO 用户信息更新参数 + * @return 更新后的用户信息 + */ + @PostMapping("/info/update") + public Result userInfoUpdate(@RequestBody UserInfoUpdateDTO userInfoUpdateDTO) { + Long userId = UserContext.getUserId(); + userInfoUpdateDTO.setUserId(userId); + UserInfoVO userInfoVO = userService.updateUserInfo(userInfoUpdateDTO); + return Result.success(ResultCode.SUCCESS_REVIEW, "用户信息更新成功", userInfoVO); + } } diff --git a/src/main/java/com/bao/dating/mapper/UserMapper.java b/src/main/java/com/bao/dating/mapper/UserMapper.java index 1e28552..8326914 100644 --- a/src/main/java/com/bao/dating/mapper/UserMapper.java +++ b/src/main/java/com/bao/dating/mapper/UserMapper.java @@ -1,8 +1,9 @@ package com.bao.dating.mapper; +import com.bao.dating.pojo.dto.UserInfoUpdateDTO; +import com.bao.dating.pojo.entity.Post; import com.bao.dating.pojo.entity.User; import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; @Mapper public interface UserMapper { @@ -22,4 +23,11 @@ public interface UserMapper { * @return 用户 */ User selectByUserId(Long userid); + + /** + * 更新用户信息 + * @param userInfoUpdateDTO + */ + void updateUserInfoByUserId(UserInfoUpdateDTO userInfoUpdateDTO); + } diff --git a/src/main/java/com/bao/dating/pojo/dto/UserInfoUpdateDTO.java b/src/main/java/com/bao/dating/pojo/dto/UserInfoUpdateDTO.java new file mode 100644 index 0000000..79df035 --- /dev/null +++ b/src/main/java/com/bao/dating/pojo/dto/UserInfoUpdateDTO.java @@ -0,0 +1,20 @@ +package com.bao.dating.pojo.dto; + +import lombok.Data; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; + +@Data +public class UserInfoUpdateDTO { + private Long userId; + private String nickname; + private String avatarUrl; + private String backgroundUrl; + private Integer gender; + private LocalDate birthday; + private List hobbies; + private String signature; + private LocalDateTime updatedAt; +} diff --git a/src/main/java/com/bao/dating/pojo/entity/User.java b/src/main/java/com/bao/dating/pojo/entity/User.java index db16def..e668af5 100644 --- a/src/main/java/com/bao/dating/pojo/entity/User.java +++ b/src/main/java/com/bao/dating/pojo/entity/User.java @@ -5,6 +5,7 @@ import lombok.Data; import java.io.Serializable; import java.time.LocalDate; import java.time.LocalDateTime; +import java.util.List; /** * 用户表 @@ -31,7 +32,7 @@ public class User implements Serializable { private LocalDate birthday; - private String hobbies; + private List hobbies; private String signature; diff --git a/src/main/java/com/bao/dating/pojo/vo/UserInfoVO.java b/src/main/java/com/bao/dating/pojo/vo/UserInfoVO.java index 83fd640..8be5be1 100644 --- a/src/main/java/com/bao/dating/pojo/vo/UserInfoVO.java +++ b/src/main/java/com/bao/dating/pojo/vo/UserInfoVO.java @@ -19,6 +19,6 @@ public class UserInfoVO { private LocalDate birthday; private List hobbies; private String signature; - private LocalDateTime createdAt; private LocalDateTime updatedAt; + private LocalDateTime createdAt; } diff --git a/src/main/java/com/bao/dating/service/UserService.java b/src/main/java/com/bao/dating/service/UserService.java index ab5ed64..0eb9218 100644 --- a/src/main/java/com/bao/dating/service/UserService.java +++ b/src/main/java/com/bao/dating/service/UserService.java @@ -1,5 +1,6 @@ package com.bao.dating.service; +import com.bao.dating.pojo.dto.UserInfoUpdateDTO; import com.bao.dating.pojo.dto.UserLoginDTO; import com.bao.dating.pojo.vo.PostEditVO; import com.bao.dating.pojo.vo.UserInfoVO; @@ -35,4 +36,10 @@ public interface UserService { * @return 上传后的文件URL列表 */ String uploadBackground(MultipartFile file); + + /** + * 更新用户信息 + * @param userInfoUpdateDTO 用户信息 + */ + UserInfoVO updateUserInfo(UserInfoUpdateDTO userInfoUpdateDTO); } diff --git a/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java b/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java index 3aac7da..1481799 100644 --- a/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java +++ b/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java @@ -1,10 +1,14 @@ package com.bao.dating.service.impl; import com.bao.dating.common.aliyun.AliOssUtil; +import com.bao.dating.common.aliyun.GreenImageScan; +import com.bao.dating.common.aliyun.GreenTextScan; import com.bao.dating.context.UserContext; import com.bao.dating.mapper.UserMapper; +import com.bao.dating.pojo.dto.UserInfoUpdateDTO; import com.bao.dating.pojo.dto.UserLoginDTO; import com.bao.dating.pojo.entity.User; +import com.bao.dating.pojo.vo.PostEditVO; import com.bao.dating.pojo.vo.UserInfoVO; import com.bao.dating.pojo.vo.UserLoginVO; import com.bao.dating.service.UserService; @@ -14,11 +18,14 @@ 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.util.StringUtils; import org.springframework.web.multipart.MultipartFile; import java.time.LocalDate; +import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.util.Map; import java.util.UUID; @Service @@ -27,6 +34,12 @@ public class UserServiceImpl implements UserService { @Autowired private AliOssUtil ossUtil; + @Autowired + private GreenTextScan greenTextScan; + + @Autowired + private GreenImageScan greenImageScan; + @Autowired private UserMapper userMapper; @@ -157,4 +170,23 @@ public class UserServiceImpl implements UserService { throw new RuntimeException("上传图片失败", e); } } + + @Override + public UserInfoVO updateUserInfo(UserInfoUpdateDTO userInfoUpdateDTO) { + Long userId = userInfoUpdateDTO.getUserId(); + User user = userMapper.selectByUserId(userId); + if (user == null){ + throw new RuntimeException("用户不存在"); + } + + userInfoUpdateDTO.setUpdatedAt(LocalDateTime.now()); + + // 更新数据库 + userMapper.updateUserInfoByUserId(userInfoUpdateDTO); + + // 返回动态详情 + UserInfoVO userInfoVO = new UserInfoVO(); + BeanUtils.copyProperties(user, userInfoVO); + return userInfoVO; + } } diff --git a/src/main/resources/com/bao/dating/mapper/UserMapper.xml b/src/main/resources/com/bao/dating/mapper/UserMapper.xml index 6d6343a..fdcbcb4 100644 --- a/src/main/resources/com/bao/dating/mapper/UserMapper.xml +++ b/src/main/resources/com/bao/dating/mapper/UserMapper.xml @@ -43,4 +43,33 @@ FROM user WHERE user_id = #{userId} + + + UPDATE user + + + nickname = #{nickname}, + + + avatar_url = #{avatarUrl}, + + + background_url = #{backgroundUrl}, + + + gender = #{gender}, + + + birthday = #{birthday}, + + + hobbies = #{hobbies}, + + + signature = #{signature}, + + updated_at = #{updatedAt} + + WHERE user_id = #{userId} + \ No newline at end of file From fec7bb04b91c958c8f769dc3ba2f8efc41f63ed0 Mon Sep 17 00:00:00 2001 From: KilLze Date: Mon, 29 Dec 2025 15:16:31 +0800 Subject: [PATCH 13/37] =?UTF-8?q?=E4=BF=AEbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/com/bao/dating/mapper/UserMapper.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/com/bao/dating/mapper/UserMapper.xml b/src/main/resources/com/bao/dating/mapper/UserMapper.xml index fdcbcb4..28a3a94 100644 --- a/src/main/resources/com/bao/dating/mapper/UserMapper.xml +++ b/src/main/resources/com/bao/dating/mapper/UserMapper.xml @@ -63,7 +63,7 @@ birthday = #{birthday}, - hobbies = #{hobbies}, + hobbies = #{hobbies, typeHandler=com.bao.dating.handler.ListToVarcharTypeHandler}, signature = #{signature}, From 401c2fa8bfa07e4765e519f468458542bc79361c Mon Sep 17 00:00:00 2001 From: KilLze Date: Mon, 29 Dec 2025 15:16:59 +0800 Subject: [PATCH 14/37] =?UTF-8?q?=E4=BF=AEbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bao/dating/handler/ListToVarcharTypeHandler.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/bao/dating/handler/ListToVarcharTypeHandler.java b/src/main/java/com/bao/dating/handler/ListToVarcharTypeHandler.java index ca30e97..5d0c8eb 100644 --- a/src/main/java/com/bao/dating/handler/ListToVarcharTypeHandler.java +++ b/src/main/java/com/bao/dating/handler/ListToVarcharTypeHandler.java @@ -6,10 +6,7 @@ import org.apache.ibatis.type.MappedJdbcTypes; import org.apache.ibatis.type.MappedTypes; import org.apache.ibatis.type.TypeHandler; -import java.sql.CallableStatement; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; +import java.sql.*; import java.util.Arrays; import java.util.List; @@ -22,6 +19,11 @@ import java.util.List; public class ListToVarcharTypeHandler implements TypeHandler> { @Override public void setParameter(PreparedStatement preparedStatement, int i, List strings, JdbcType jdbcType) throws SQLException { + // 允许 null + if (strings == null || strings.isEmpty()) { + preparedStatement.setNull(i, Types.VARCHAR); + return; + } // 遍历List类型的入参,拼装为String类型,使用Statement对象插入数据库 StringBuffer sb = new StringBuffer(); for (int j = 0; j < strings.size(); j++) { From 9cf50ce7df631fb80485d24026456e839d6a9293 Mon Sep 17 00:00:00 2001 From: KilLze Date: Mon, 29 Dec 2025 15:34:41 +0800 Subject: [PATCH 15/37] =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E4=BF=AE=E6=94=B9=EF=BC=8C=E4=BB=A5=E5=8F=8A?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E4=BF=A1=E6=81=AF=E5=AE=A1=E6=A0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bao/dating/controller/UserController.java | 5 +- .../dating/handler/ListToJsonTypeHandler.java | 64 +++++++++++++ .../com/bao/dating/service/UserService.java | 2 +- .../dating/service/impl/UserServiceImpl.java | 96 ++++++++++++++++--- .../com/bao/dating/mapper/UserMapper.xml | 4 +- 5 files changed, 154 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/bao/dating/handler/ListToJsonTypeHandler.java diff --git a/src/main/java/com/bao/dating/controller/UserController.java b/src/main/java/com/bao/dating/controller/UserController.java index 355f8b7..3f92cac 100644 --- a/src/main/java/com/bao/dating/controller/UserController.java +++ b/src/main/java/com/bao/dating/controller/UserController.java @@ -71,10 +71,9 @@ public class UserController { * @return 更新后的用户信息 */ @PostMapping("/info/update") - public Result userInfoUpdate(@RequestBody UserInfoUpdateDTO userInfoUpdateDTO) { + public Result userInfoUpdate(@RequestBody UserInfoUpdateDTO userInfoUpdateDTO) { Long userId = UserContext.getUserId(); userInfoUpdateDTO.setUserId(userId); - UserInfoVO userInfoVO = userService.updateUserInfo(userInfoUpdateDTO); - return Result.success(ResultCode.SUCCESS_REVIEW, "用户信息更新成功", userInfoVO); + return Result.success(ResultCode.SUCCESS_REVIEW, "用户信息更新成功", null); } } diff --git a/src/main/java/com/bao/dating/handler/ListToJsonTypeHandler.java b/src/main/java/com/bao/dating/handler/ListToJsonTypeHandler.java new file mode 100644 index 0000000..2448bfb --- /dev/null +++ b/src/main/java/com/bao/dating/handler/ListToJsonTypeHandler.java @@ -0,0 +1,64 @@ +package com.bao.dating.handler; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedJdbcTypes; +import org.apache.ibatis.type.MappedTypes; +import org.apache.ibatis.type.TypeHandler; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +@MappedJdbcTypes(JdbcType.VARCHAR) // 也可以使用JdbcType.JSON,如果数据库支持的话 +@MappedTypes(List.class) +public class ListToJsonTypeHandler implements TypeHandler> { + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public void setParameter(PreparedStatement ps, int i, List parameter, JdbcType jdbcType) throws SQLException { + if (parameter == null || parameter.isEmpty()) { + ps.setNull(i, java.sql.Types.VARCHAR); // 或者 Types.JSON 如果数据库支持 + return; + } + try { + String json = objectMapper.writeValueAsString(parameter); + ps.setString(i, json); + } catch (JsonProcessingException e) { + throw new SQLException("Error converting list to JSON", e); + } + } + + @Override + public List getResult(ResultSet rs, String columnName) throws SQLException { + String json = rs.getString(columnName); + return convertJsonToList(json); + } + + @Override + public List getResult(ResultSet rs, int columnIndex) throws SQLException { + String json = rs.getString(columnIndex); + return convertJsonToList(json); + } + + @Override + public List getResult(java.sql.CallableStatement cs, int columnIndex) throws SQLException { + String json = cs.getString(columnIndex); + return convertJsonToList(json); + } + + private List convertJsonToList(String json) throws SQLException { + if (json == null || json.isEmpty()) { + return null; + } + try { + return objectMapper.readValue(json, new TypeReference>() {}); + } catch (JsonProcessingException e) { + throw new SQLException("Error converting JSON to list", e); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/bao/dating/service/UserService.java b/src/main/java/com/bao/dating/service/UserService.java index 0eb9218..2fd6dce 100644 --- a/src/main/java/com/bao/dating/service/UserService.java +++ b/src/main/java/com/bao/dating/service/UserService.java @@ -41,5 +41,5 @@ public interface UserService { * 更新用户信息 * @param userInfoUpdateDTO 用户信息 */ - UserInfoVO updateUserInfo(UserInfoUpdateDTO userInfoUpdateDTO); + void updateUserInfo(UserInfoUpdateDTO userInfoUpdateDTO); } diff --git a/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java b/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java index 1481799..540c225 100644 --- a/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java +++ b/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java @@ -25,6 +25,8 @@ import org.springframework.web.multipart.MultipartFile; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.UUID; @@ -45,6 +47,7 @@ public class UserServiceImpl implements UserService { /** * 用户登录 + * * @param userLoginDTO * @return 登录信息 */ @@ -56,7 +59,7 @@ public class UserServiceImpl implements UserService { } // 查询用户 User user = userMapper.getByUsername(userLoginDTO.getUsername()); - if (user == null){ + if (user == null) { throw new RuntimeException("用户不存在"); } // 密码校验 @@ -65,7 +68,7 @@ public class UserServiceImpl implements UserService { user.getSalt(), user.getPasswordHash() ); - if (!match){ + if (!match) { throw new RuntimeException("密码错误"); } // 生成token @@ -80,13 +83,14 @@ public class UserServiceImpl implements UserService { /** * 获取用户信息 + * * @param userId * @return 用户信息 */ @Override public UserInfoVO getUserInfo(Long userId) { User user = userMapper.selectByUserId(userId); - if (user == null){ + if (user == null) { throw new RuntimeException("用户不存在"); } UserInfoVO userInfoVO = new UserInfoVO(); @@ -116,7 +120,7 @@ public class UserServiceImpl implements UserService { String extension = FileUtil.getFileExtension(originalFilename); String fileName = UUID.randomUUID().toString().replace("-", "") + "." + extension; Long userId = UserContext.getUserId(); - String objectKey = "user/" + userId + "/avatar/" + fileName; + String objectKey = "user/" + userId + "/avatar/" + fileName; try { byte[] fileBytes = file.getBytes(); @@ -171,22 +175,92 @@ public class UserServiceImpl implements UserService { } } + /** + * 更新用户信息 + * + * @param userInfoUpdateDTO + * @return 用户信息 + */ @Override - public UserInfoVO updateUserInfo(UserInfoUpdateDTO userInfoUpdateDTO) { + public void updateUserInfo(UserInfoUpdateDTO userInfoUpdateDTO) { Long userId = userInfoUpdateDTO.getUserId(); User user = userMapper.selectByUserId(userId); - if (user == null){ + if (user == null) { throw new RuntimeException("用户不存在"); } + // 将需要审核的内容合并成一个文本,用于减少调用次数 + StringBuilder textBuilder = new StringBuilder(); + + if (userInfoUpdateDTO.getNickname() != null && !userInfoUpdateDTO.getNickname().isEmpty()) { + textBuilder.append(userInfoUpdateDTO.getNickname()).append(" "); + } + if (userInfoUpdateDTO.getHobbies() != null && !userInfoUpdateDTO.getHobbies().isEmpty()) { + // 将爱好列表转换为字符串,用空格分隔 + String hobbiesStr = String.join(" ", userInfoUpdateDTO.getHobbies()); + textBuilder.append(hobbiesStr).append(" "); + } + if (userInfoUpdateDTO.getSignature() != null && !userInfoUpdateDTO.getSignature().isEmpty()) { + textBuilder.append(userInfoUpdateDTO.getSignature()).append(" "); + } + // 文本审核 + if (textBuilder.length() > 0) { + Map textResult; + try { + textResult = greenTextScan.greeTextScan(textBuilder.toString()); + } catch (Exception e) { + throw new RuntimeException("用户信息文本审核失败"); + } + + String suggestion = (String) textResult.get("suggestion"); + + if ("block".equals(suggestion)) { + throw new RuntimeException("用户信息包含违规内容,修改失败"); + } + if ("review".equals(suggestion)) { + throw new RuntimeException("用户信息需要人工审核,暂无法修改"); + } + } + + // 图片审核 + List imageKeys = new ArrayList<>(); + if (userInfoUpdateDTO.getAvatarUrl() != null && !userInfoUpdateDTO.getAvatarUrl().isEmpty()) { + imageKeys.add(userInfoUpdateDTO.getAvatarUrl()); + } + if (userInfoUpdateDTO.getBackgroundUrl() != null && !userInfoUpdateDTO.getBackgroundUrl().isEmpty()) { + imageKeys.add(userInfoUpdateDTO.getBackgroundUrl()); + } + if (!imageKeys.isEmpty()) { + Map imageResult; + try { + imageResult = greenImageScan.imageScan(imageKeys); + } catch (Exception e) { + throw new RuntimeException("用户图片审核失败"); + } + + String suggestion = (String) imageResult.get("suggestion"); + + if ("block".equals(suggestion)) { + throw new RuntimeException("头像或背景图不合规,修改失败"); + } + if ("review".equals(suggestion)) { + throw new RuntimeException("头像或背景图需要人工审核,暂无法修改"); + } + } + + String nickname = userInfoUpdateDTO.getNickname(); + // 用户没传昵称 or 传空串 + if (!StringUtils.hasText(nickname)) { + // 如果数据库里原本也没有昵称 + if (!StringUtils.hasText(user.getNickname())) { + userInfoUpdateDTO.setNickname(user.getUserName()); + } else { + userInfoUpdateDTO.setNickname(null); + } + } userInfoUpdateDTO.setUpdatedAt(LocalDateTime.now()); // 更新数据库 userMapper.updateUserInfoByUserId(userInfoUpdateDTO); - - // 返回动态详情 - UserInfoVO userInfoVO = new UserInfoVO(); - BeanUtils.copyProperties(user, userInfoVO); - return userInfoVO; } } diff --git a/src/main/resources/com/bao/dating/mapper/UserMapper.xml b/src/main/resources/com/bao/dating/mapper/UserMapper.xml index 28a3a94..bf483dc 100644 --- a/src/main/resources/com/bao/dating/mapper/UserMapper.xml +++ b/src/main/resources/com/bao/dating/mapper/UserMapper.xml @@ -23,7 +23,7 @@ - + @@ -63,7 +63,7 @@ birthday = #{birthday}, - hobbies = #{hobbies, typeHandler=com.bao.dating.handler.ListToVarcharTypeHandler}, + hobbies = #{hobbies, typeHandler=com.bao.dating.handler.ListToJsonTypeHandler}, signature = #{signature}, From f31b42a03874185525912721ede36759fd13edaa Mon Sep 17 00:00:00 2001 From: KilLze Date: Mon, 29 Dec 2025 15:42:20 +0800 Subject: [PATCH 16/37] =?UTF-8?q?=E4=BF=AEbug=20=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E4=BF=A1=E6=81=AF=E4=BF=AE=E6=94=B9=EF=BC=8C?= =?UTF-8?q?=E4=BB=A5=E5=8F=8A=E7=94=A8=E6=88=B7=E4=BF=A1=E6=81=AF=E5=AE=A1?= =?UTF-8?q?=E6=A0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/bao/dating/controller/PostController.java | 6 +++--- .../java/com/bao/dating/controller/UserController.java | 7 ++++--- .../com/bao/dating/service/impl/UserServiceImpl.java | 10 ---------- 3 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/bao/dating/controller/PostController.java b/src/main/java/com/bao/dating/controller/PostController.java index 94fc92e..9f335ae 100644 --- a/src/main/java/com/bao/dating/controller/PostController.java +++ b/src/main/java/com/bao/dating/controller/PostController.java @@ -28,7 +28,7 @@ public class PostController { @PostMapping(value = "/upload", consumes = "multipart/form-data") public Result> uploadMedia(@RequestParam("files") MultipartFile[] files) { List fileUrls = postService.uploadMedia(files); - return Result.success(ResultCode.SUCCESS_REVIEW, "文件上传成功", fileUrls); + return Result.success(ResultCode.SUCCESS, "文件上传成功", fileUrls); } /** @@ -40,7 +40,7 @@ public class PostController { public Result createPostJson(@RequestBody PostRequestDTO postDTO) { // 调用 Service 层处理发布动态业务逻辑 Post result = postService.createPost(postDTO); - return Result.success(ResultCode.SUCCESS_REVIEW, "动态发布成功,等待审核。", result); + return Result.success(ResultCode.SUCCESS, "动态发布成功,等待审核。", result); } /** @@ -75,6 +75,6 @@ public class PostController { @PostMapping("/{postId}/updatePost") public Result updatePost(@PathVariable Long postId, @RequestBody PostRequestDTO postRequestDTO) { PostEditVO result = postService.updatePost(postId, postRequestDTO); - return Result.success(ResultCode.SUCCESS_REVIEW, "动态更新成功", result); + return Result.success(ResultCode.SUCCESS, "动态更新成功", result); } } \ No newline at end of file diff --git a/src/main/java/com/bao/dating/controller/UserController.java b/src/main/java/com/bao/dating/controller/UserController.java index 3f92cac..260c080 100644 --- a/src/main/java/com/bao/dating/controller/UserController.java +++ b/src/main/java/com/bao/dating/controller/UserController.java @@ -51,7 +51,7 @@ public class UserController { @PostMapping(value = "/info/uploadAvatar", consumes = "multipart/form-data") public Result uploadAvatar(@RequestParam("file") MultipartFile file) { String fileUrl = userService.uploadAvatar(file); - return Result.success(ResultCode.SUCCESS_REVIEW, "头像上传成功", fileUrl); + return Result.success(ResultCode.SUCCESS, "头像上传成功", fileUrl); } /** @@ -62,7 +62,7 @@ public class UserController { @PostMapping(value = "/info/uploadBackground", consumes = "multipart/form-data") public Result uploadBackground(@RequestParam("file") MultipartFile file) { String fileUrl = userService.uploadBackground(file); - return Result.success(ResultCode.SUCCESS_REVIEW, "背景上传成功", fileUrl); + return Result.success(ResultCode.SUCCESS, "背景上传成功", fileUrl); } /** @@ -74,6 +74,7 @@ public class UserController { public Result userInfoUpdate(@RequestBody UserInfoUpdateDTO userInfoUpdateDTO) { Long userId = UserContext.getUserId(); userInfoUpdateDTO.setUserId(userId); - return Result.success(ResultCode.SUCCESS_REVIEW, "用户信息更新成功", null); + userService.updateUserInfo(userInfoUpdateDTO); + return Result.success(ResultCode.SUCCESS, "用户信息更新成功", null); } } diff --git a/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java b/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java index 540c225..2ff6081 100644 --- a/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java +++ b/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java @@ -248,16 +248,6 @@ public class UserServiceImpl implements UserService { } } - String nickname = userInfoUpdateDTO.getNickname(); - // 用户没传昵称 or 传空串 - if (!StringUtils.hasText(nickname)) { - // 如果数据库里原本也没有昵称 - if (!StringUtils.hasText(user.getNickname())) { - userInfoUpdateDTO.setNickname(user.getUserName()); - } else { - userInfoUpdateDTO.setNickname(null); - } - } userInfoUpdateDTO.setUpdatedAt(LocalDateTime.now()); // 更新数据库 From 0c4ddc2803de3ab9c6a1790b24572cb23ec5df03 Mon Sep 17 00:00:00 2001 From: KilLze Date: Mon, 29 Dec 2025 17:03:06 +0800 Subject: [PATCH 17/37] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=94=A8=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E4=B8=AA=E4=BA=BA=E4=BF=A1=E6=81=AF=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bao/dating/controller/UserController.java | 6 +-- .../dating/pojo/dto/UserInfoUpdateDTO.java | 3 ++ .../com/bao/dating/pojo/vo/UserInfoVO.java | 1 + .../com/bao/dating/service/UserService.java | 2 +- .../dating/service/impl/UserServiceImpl.java | 39 +++++++++++++++---- .../com/bao/dating/mapper/UserMapper.xml | 2 + 6 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/bao/dating/controller/UserController.java b/src/main/java/com/bao/dating/controller/UserController.java index 260c080..ac14c17 100644 --- a/src/main/java/com/bao/dating/controller/UserController.java +++ b/src/main/java/com/bao/dating/controller/UserController.java @@ -71,10 +71,10 @@ public class UserController { * @return 更新后的用户信息 */ @PostMapping("/info/update") - public Result userInfoUpdate(@RequestBody UserInfoUpdateDTO userInfoUpdateDTO) { + public Result userInfoUpdate(@RequestBody UserInfoUpdateDTO userInfoUpdateDTO) { Long userId = UserContext.getUserId(); userInfoUpdateDTO.setUserId(userId); - userService.updateUserInfo(userInfoUpdateDTO); - return Result.success(ResultCode.SUCCESS, "用户信息更新成功", null); + UserInfoVO userInfoVO =userService.updateUserInfo(userInfoUpdateDTO); + return Result.success(ResultCode.SUCCESS, "用户信息更新成功", userInfoVO); } } diff --git a/src/main/java/com/bao/dating/pojo/dto/UserInfoUpdateDTO.java b/src/main/java/com/bao/dating/pojo/dto/UserInfoUpdateDTO.java index 79df035..8fc9912 100644 --- a/src/main/java/com/bao/dating/pojo/dto/UserInfoUpdateDTO.java +++ b/src/main/java/com/bao/dating/pojo/dto/UserInfoUpdateDTO.java @@ -9,6 +9,7 @@ import java.util.List; @Data public class UserInfoUpdateDTO { private Long userId; + private String userName; private String nickname; private String avatarUrl; private String backgroundUrl; @@ -17,4 +18,6 @@ public class UserInfoUpdateDTO { private List hobbies; private String signature; private LocalDateTime updatedAt; + /** 需要清空的字段 */ + private List clearFields; } diff --git a/src/main/java/com/bao/dating/pojo/vo/UserInfoVO.java b/src/main/java/com/bao/dating/pojo/vo/UserInfoVO.java index 8be5be1..475bb66 100644 --- a/src/main/java/com/bao/dating/pojo/vo/UserInfoVO.java +++ b/src/main/java/com/bao/dating/pojo/vo/UserInfoVO.java @@ -12,6 +12,7 @@ import java.util.List; @Data public class UserInfoVO { private Long userId; + private String userName; private String nickname; private String avatarUrl; private String backgroundUrl; diff --git a/src/main/java/com/bao/dating/service/UserService.java b/src/main/java/com/bao/dating/service/UserService.java index 2fd6dce..0eb9218 100644 --- a/src/main/java/com/bao/dating/service/UserService.java +++ b/src/main/java/com/bao/dating/service/UserService.java @@ -41,5 +41,5 @@ public interface UserService { * 更新用户信息 * @param userInfoUpdateDTO 用户信息 */ - void updateUserInfo(UserInfoUpdateDTO userInfoUpdateDTO); + UserInfoVO updateUserInfo(UserInfoUpdateDTO userInfoUpdateDTO); } diff --git a/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java b/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java index 2ff6081..0481b62 100644 --- a/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java +++ b/src/main/java/com/bao/dating/service/impl/UserServiceImpl.java @@ -8,7 +8,6 @@ import com.bao.dating.mapper.UserMapper; import com.bao.dating.pojo.dto.UserInfoUpdateDTO; import com.bao.dating.pojo.dto.UserLoginDTO; import com.bao.dating.pojo.entity.User; -import com.bao.dating.pojo.vo.PostEditVO; import com.bao.dating.pojo.vo.UserInfoVO; import com.bao.dating.pojo.vo.UserLoginVO; import com.bao.dating.service.UserService; @@ -18,7 +17,6 @@ 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.util.StringUtils; import org.springframework.web.multipart.MultipartFile; @@ -30,6 +28,11 @@ import java.util.List; import java.util.Map; import java.util.UUID; +/** + * 用户服务实现类 + * + * @author KilLze + */ @Service public class UserServiceImpl implements UserService { @@ -48,7 +51,7 @@ public class UserServiceImpl implements UserService { /** * 用户登录 * - * @param userLoginDTO + * @param userLoginDTO 登录参数 * @return 登录信息 */ @Override @@ -84,7 +87,7 @@ public class UserServiceImpl implements UserService { /** * 获取用户信息 * - * @param userId + * @param userId 用户ID * @return 用户信息 */ @Override @@ -98,6 +101,12 @@ public class UserServiceImpl implements UserService { return userInfoVO; } + /** + * 上传头像接口 + * + * @param file 头像文件 + * @return 上传后的文件URL + */ @Override public String uploadAvatar(MultipartFile file) { // 参数校验 @@ -137,6 +146,12 @@ public class UserServiceImpl implements UserService { } } + /** + * 上传背景图片 + * + * @param file 背景图片文件 + * @return 上传后的文件URL + */ @Override public String uploadBackground(MultipartFile file) { // 参数校验 @@ -178,11 +193,10 @@ public class UserServiceImpl implements UserService { /** * 更新用户信息 * - * @param userInfoUpdateDTO - * @return 用户信息 + * @param userInfoUpdateDTO 用户信息更新参数 */ @Override - public void updateUserInfo(UserInfoUpdateDTO userInfoUpdateDTO) { + public UserInfoVO updateUserInfo(UserInfoUpdateDTO userInfoUpdateDTO) { Long userId = userInfoUpdateDTO.getUserId(); User user = userMapper.selectByUserId(userId); if (user == null) { @@ -247,10 +261,19 @@ public class UserServiceImpl implements UserService { throw new RuntimeException("头像或背景图需要人工审核,暂无法修改"); } } - + // 默认昵称兜底 + if (userInfoUpdateDTO.getNickname() == null || userInfoUpdateDTO.getNickname().trim().isEmpty()) { + userInfoUpdateDTO.setNickname(user.getUserName()); + } userInfoUpdateDTO.setUpdatedAt(LocalDateTime.now()); // 更新数据库 userMapper.updateUserInfoByUserId(userInfoUpdateDTO); + + // 封装返回结果 + User updatedUser = userMapper.selectByUserId(userInfoUpdateDTO.getUserId()); + UserInfoVO userInfoVO = new UserInfoVO(); + BeanUtils.copyProperties(updatedUser, userInfoVO); + return userInfoVO; } } diff --git a/src/main/resources/com/bao/dating/mapper/UserMapper.xml b/src/main/resources/com/bao/dating/mapper/UserMapper.xml index bf483dc..61bb82b 100644 --- a/src/main/resources/com/bao/dating/mapper/UserMapper.xml +++ b/src/main/resources/com/bao/dating/mapper/UserMapper.xml @@ -18,6 +18,7 @@ + @@ -31,6 +32,7 @@ SELECT user_id FROM post_favorite WHERE post_id = #{postId} + + + + DELETE FROM post_favorite + WHERE post_id IN + + #{postId} + + + \ No newline at end of file diff --git a/src/main/resources/com/bao/dating/mapper/PostLikeMapper.xml b/src/main/resources/com/bao/dating/mapper/PostLikeMapper.xml index fe82536..9e26cd2 100644 --- a/src/main/resources/com/bao/dating/mapper/PostLikeMapper.xml +++ b/src/main/resources/com/bao/dating/mapper/PostLikeMapper.xml @@ -14,4 +14,14 @@ delete from dating.post_like where post_id = #{postId} and user_id = #{userId} + + + + DELETE FROM post_like + WHERE post_id IN + + #{postId} + + + \ No newline at end of file diff --git a/src/main/resources/com/bao/dating/mapper/PostMapper.xml b/src/main/resources/com/bao/dating/mapper/PostMapper.xml index b1924e4..d3c96bd 100644 --- a/src/main/resources/com/bao/dating/mapper/PostMapper.xml +++ b/src/main/resources/com/bao/dating/mapper/PostMapper.xml @@ -28,25 +28,19 @@ #{isPublic}, 0, 0, #{createdAt}, #{updatedAt}) - - - DELETE FROM post WHERE post_id IN + + + UPDATE post + + is_public = 3, + updated_at = NOW() + + WHERE post_id IN #{postId} - - - - DELETE FROM post_favorite WHERE post_id = #{postId} - - - - DELETE FROM post_like WHERE post_id = #{postId} - - - - DELETE FROM comments WHERE post_id = #{postId} - + AND user_id = #{userId} + From 717c0a0507bd2a92c9a427cf5245090c3c5e4b29 Mon Sep 17 00:00:00 2001 From: KilLze Date: Mon, 5 Jan 2026 01:52:10 +0800 Subject: [PATCH 34/37] =?UTF-8?q?=E4=BC=98=E5=8C=96redis=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/bao/dating/config/RedisConfig.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/bao/dating/config/RedisConfig.java b/src/main/java/com/bao/dating/config/RedisConfig.java index 63ce040..93dcbbd 100644 --- a/src/main/java/com/bao/dating/config/RedisConfig.java +++ b/src/main/java/com/bao/dating/config/RedisConfig.java @@ -20,9 +20,13 @@ public class RedisConfig { // 设置redis的连接工厂对象 redisTemplate.setConnectionFactory(redisConnectionFactory); - // key 使用 String + // 设置redis key的序列化器 redisTemplate.setKeySerializer(new StringRedisSerializer()); + // 设置value的序列化器 redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); + // 设置hash类型的key和value的序列化器 + redisTemplate.setHashKeySerializer(new StringRedisSerializer()); + redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); return redisTemplate; } From 61c4c9d4422f3f1aa63754182c5a382283ec1a56 Mon Sep 17 00:00:00 2001 From: bao <19271189822@163.com> Date: Mon, 5 Jan 2026 09:55:41 +0800 Subject: [PATCH 35/37] =?UTF-8?q?=E7=BB=9F=E4=B8=80redis=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 30db5ad7066baefb51e8cfcbdb4291ddab1910d2) --- src/main/resources/application.yml | 4 +- .../dating/common/aliyun/OssUploadTest.java | 304 ++++++++++++++++++ 2 files changed, 306 insertions(+), 2 deletions(-) create mode 100644 src/test/java/com/bao/dating/common/aliyun/OssUploadTest.java diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 8009016..5cc67fa 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -13,8 +13,8 @@ spring: password: JoyeeServe2025 driver-class-name: com.mysql.cj.jdbc.Driver redis: - host: 127.0.0.1 - port: 6379 + host: 110.42.41.177 + port: 6389 password: "" database: 0 timeout: 10000 diff --git a/src/test/java/com/bao/dating/common/aliyun/OssUploadTest.java b/src/test/java/com/bao/dating/common/aliyun/OssUploadTest.java new file mode 100644 index 0000000..7211c09 --- /dev/null +++ b/src/test/java/com/bao/dating/common/aliyun/OssUploadTest.java @@ -0,0 +1,304 @@ +package com.bao.dating.common.aliyun; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.UUID; + +/** + * OSS图片上传测试类 + * @author KilLze + */ +@SpringBootTest +public class OssUploadTest { + + @Autowired + private AliOssUtil aliOssUtil; + + /** + * 测试上传本地图片文件 + */ + @Test + public void testUploadLocalImage() { + try { + // 本地图片文件路径(请修改为实际存在的图片路径) + String localImagePath = "D:/image/image.jpg"; // 请修改为实际路径 + + File imageFile = new File(localImagePath); + if (!imageFile.exists()) { + System.out.println("图片文件不存在: " + localImagePath); + System.out.println("请修改localImagePath为实际存在的图片路径"); + return; + } + + // 读取文件字节 + byte[] imageBytes = Files.readAllBytes(Paths.get(localImagePath)); + + // 生成OSS对象名称(使用时间戳和UUID确保唯一性) + String objectName = generateObjectName("test", "jpg"); + + // 上传到OSS + String fileUrl = aliOssUtil.upload(imageBytes, objectName); + + System.out.println("========== 本地图片上传测试 =========="); + System.out.println("本地文件路径: " + localImagePath); + System.out.println("文件大小: " + imageBytes.length + " 字节"); + System.out.println("OSS对象名称: " + objectName); + System.out.println("文件访问URL: " + fileUrl); + System.out.println("上传结果: 成功"); + System.out.println("====================================="); + + } catch (IOException e) { + System.out.println("上传失败: " + e.getMessage()); + e.printStackTrace(); + } + } + + /** + * 测试从网络URL下载图片并上传到OSS + */ + @Test + public void testUploadImageFromUrl() { + try { + // 网络图片URL(请修改为实际的图片URL) + String imageUrl = "https://example.com/image.jpg"; // 请修改为实际URL + + System.out.println("========== 网络图片上传测试 =========="); + System.out.println("开始下载图片: " + imageUrl); + + // 从URL下载图片 + URL url = new URL(imageUrl); + try (InputStream inputStream = url.openStream()) { + byte[] imageBytes = readAllBytes(inputStream); + + // 从URL中提取文件扩展名 + String extension = getFileExtensionFromUrl(imageUrl); + if (extension.isEmpty()) { + extension = "jpg"; // 默认扩展名 + } + + // 生成OSS对象名称 + String objectName = generateObjectName("download", extension); + + // 上传到OSS + String fileUrl = aliOssUtil.upload(imageBytes, objectName); + + System.out.println("图片下载成功"); + System.out.println("文件大小: " + imageBytes.length + " 字节"); + System.out.println("OSS对象名称: " + objectName); + System.out.println("文件访问URL: " + fileUrl); + System.out.println("上传结果: 成功"); + } + + System.out.println("====================================="); + + } catch (Exception e) { + System.out.println("上传失败: " + e.getMessage()); + e.printStackTrace(); + } + } + + /** + * 测试上传不同格式的图片 + */ + @Test + public void testUploadDifferentImageFormats() { + String[] imagePaths = { + "D:/test/image1.jpg", // 请修改为实际路径 + "D:/test/image2.png", // 请修改为实际路径 + "D:/test/image3.gif" // 请修改为实际路径 + }; + + System.out.println("========== 多格式图片上传测试 =========="); + + for (String imagePath : imagePaths) { + try { + File imageFile = new File(imagePath); + if (!imageFile.exists()) { + System.out.println("跳过不存在的文件: " + imagePath); + continue; + } + + // 读取文件 + byte[] imageBytes = Files.readAllBytes(Paths.get(imagePath)); + + // 获取文件扩展名 + String extension = getFileExtension(imagePath); + + // 生成OSS对象名称 + String objectName = generateObjectName("format-test", extension); + + // 上传 + String fileUrl = aliOssUtil.upload(imageBytes, objectName); + + System.out.println("\n文件: " + imagePath); + System.out.println("格式: " + extension); + System.out.println("大小: " + imageBytes.length + " 字节"); + System.out.println("URL: " + fileUrl); + System.out.println("状态: 成功"); + + } catch (Exception e) { + System.out.println("\n文件: " + imagePath); + System.out.println("状态: 失败 - " + e.getMessage()); + } + } + + System.out.println("\n====================================="); + } + + /** + * 测试上传图片到指定目录 + */ + @Test + public void testUploadImageToDirectory() { + try { + // 本地图片文件路径 + String localImagePath = "D:/test/image.jpg"; // 请修改为实际路径 + + File imageFile = new File(localImagePath); + if (!imageFile.exists()) { + System.out.println("图片文件不存在: " + localImagePath); + return; + } + + // 读取文件 + byte[] imageBytes = Files.readAllBytes(Paths.get(localImagePath)); + + // 上传到指定目录(例如:images/2025/12/24/xxx.jpg) + String directory = "images/" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd")); + String fileName = UUID.randomUUID().toString() + ".jpg"; + String objectName = directory + "/" + fileName; + + // 上传 + String fileUrl = aliOssUtil.upload(imageBytes, objectName); + + System.out.println("========== 目录上传测试 =========="); + System.out.println("目录: " + directory); + System.out.println("文件名: " + fileName); + System.out.println("完整路径: " + objectName); + System.out.println("文件访问URL: " + fileUrl); + System.out.println("上传结果: 成功"); + System.out.println("================================="); + + } catch (Exception e) { + System.out.println("上传失败: " + e.getMessage()); + e.printStackTrace(); + } + } + + /** + * 测试使用FileInputStream上传 + */ + @Test + public void testUploadWithFileInputStream() { + try { + // 本地图片文件路径 + String localImagePath = "D:/test/image.jpg"; // 请修改为实际路径 + + File imageFile = new File(localImagePath); + if (!imageFile.exists()) { + System.out.println("图片文件不存在: " + localImagePath); + return; + } + + // 使用FileInputStream读取文件 + try (FileInputStream fis = new FileInputStream(imageFile)) { + byte[] imageBytes = new byte[(int) imageFile.length()]; + fis.read(imageBytes); + + // 生成OSS对象名称 + String objectName = generateObjectName("stream", "jpg"); + + // 上传 + String fileUrl = aliOssUtil.upload(imageBytes, objectName); + + System.out.println("========== FileInputStream上传测试 =========="); + System.out.println("文件路径: " + localImagePath); + System.out.println("文件大小: " + imageBytes.length + " 字节"); + System.out.println("OSS对象名称: " + objectName); + System.out.println("文件访问URL: " + fileUrl); + System.out.println("上传结果: 成功"); + System.out.println("==========================================="); + } + + } catch (Exception e) { + System.out.println("上传失败: " + e.getMessage()); + e.printStackTrace(); + } + } + + /** + * 生成OSS对象名称 + * @param prefix 前缀 + * @param extension 文件扩展名 + * @return 对象名称 + */ + private String generateObjectName(String prefix, String extension) { + // 格式: prefix/yyyyMMdd/HHmmss-uuid.extension + String dateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd/HHmmss")); + String uuid = UUID.randomUUID().toString().substring(0, 8); + return String.format("%s/%s-%s.%s", prefix, dateTime, uuid, extension); + } + + /** + * 从文件路径获取扩展名 + * @param filePath 文件路径 + * @return 扩展名 + */ + private String getFileExtension(String filePath) { + int lastDot = filePath.lastIndexOf('.'); + if (lastDot > 0 && lastDot < filePath.length() - 1) { + return filePath.substring(lastDot + 1).toLowerCase(); + } + return "jpg"; // 默认扩展名 + } + + /** + * 从URL获取文件扩展名 + * @param url URL地址 + * @return 扩展名 + */ + private String getFileExtensionFromUrl(String url) { + try { + // 移除查询参数 + String path = url.split("\\?")[0]; + int lastDot = path.lastIndexOf('.'); + int lastSlash = path.lastIndexOf('/'); + + if (lastDot > lastSlash && lastDot < path.length() - 1) { + return path.substring(lastDot + 1).toLowerCase(); + } + } catch (Exception e) { + // 忽略异常 + } + return "jpg"; // 默认扩展名 + } + + /** + * 从InputStream读取所有字节(兼容方法) + * @param inputStream 输入流 + * @return 字节数组 + * @throws IOException IO异常 + */ + private byte[] readAllBytes(InputStream inputStream) throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + byte[] data = new byte[8192]; // 8KB缓冲区 + int nRead; + while ((nRead = inputStream.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, nRead); + } + return buffer.toByteArray(); + } +} + From 34cad7457b81039e4bb9534962f0b124894c022f Mon Sep 17 00:00:00 2001 From: bao <19271189822@163.com> Date: Mon, 5 Jan 2026 10:38:29 +0800 Subject: [PATCH 36/37] =?UTF-8?q?=E9=82=AE=E7=AE=B1=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit eb2b0cb999db2415d4086b177e27de281c78b0ab) --- pom.xml | 6 + .../com/bao/dating/common/ResultCode.java | 8 ++ .../com/bao/dating/common/aliyun/SmsUtil.java | 1 + .../VerificationCodeController.java | 90 +++++++++++++ .../service/VerificationCodeService.java | 31 +++++ .../impl/VerificationCodeServiceImpl.java | 122 ++++++++++++++++++ .../java/com/bao/dating/util/MD5Util.java | 93 ------------- .../service/VerificationCodeServiceTest.java | 91 +++++++++++++ .../com/bao/dating/util/EmailAndSmsTest.java | 1 + 9 files changed, 350 insertions(+), 93 deletions(-) create mode 100644 src/main/java/com/bao/dating/controller/VerificationCodeController.java create mode 100644 src/main/java/com/bao/dating/service/VerificationCodeService.java create mode 100644 src/main/java/com/bao/dating/service/impl/VerificationCodeServiceImpl.java create mode 100644 src/test/java/com/bao/dating/service/VerificationCodeServiceTest.java diff --git a/pom.xml b/pom.xml index 6a56776..c7629ea 100644 --- a/pom.xml +++ b/pom.xml @@ -159,6 +159,12 @@ spring-boot-starter-mail + + + org.springframework.boot + spring-boot-starter-data-redis + + diff --git a/src/main/java/com/bao/dating/common/ResultCode.java b/src/main/java/com/bao/dating/common/ResultCode.java index 2c7b892..9da6ee0 100644 --- a/src/main/java/com/bao/dating/common/ResultCode.java +++ b/src/main/java/com/bao/dating/common/ResultCode.java @@ -19,6 +19,14 @@ public enum ResultCode { FORBIDDEN(403, "无权限"), /** 数据不存在 */ NOT_FOUND(404, "数据不存在"), + /** 验证码已发送 */ + CODE_SENT(200, "验证码已发送"), + /** 验证码错误 */ + CODE_ERROR(400, "验证码错误"), + /** 验证码已过期 */ + CODE_EXPIRED(400, "验证码已过期"), + /** 验证码发送失败 */ + CODE_SEND_FAIL(500, "验证码发送失败"), /** 系统异常 */ SYSTEM_ERROR(500, "系统异常"), /** 操作失败 */ diff --git a/src/main/java/com/bao/dating/common/aliyun/SmsUtil.java b/src/main/java/com/bao/dating/common/aliyun/SmsUtil.java index b09f8bc..290c766 100644 --- a/src/main/java/com/bao/dating/common/aliyun/SmsUtil.java +++ b/src/main/java/com/bao/dating/common/aliyun/SmsUtil.java @@ -149,3 +149,4 @@ public class SmsUtil { + diff --git a/src/main/java/com/bao/dating/controller/VerificationCodeController.java b/src/main/java/com/bao/dating/controller/VerificationCodeController.java new file mode 100644 index 0000000..6d5084a --- /dev/null +++ b/src/main/java/com/bao/dating/controller/VerificationCodeController.java @@ -0,0 +1,90 @@ +package com.bao.dating.controller; + +import com.bao.dating.common.Result; +import com.bao.dating.common.ResultCode; +import com.bao.dating.service.VerificationCodeService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.*; + +/** + * 验证码控制器 + * @author KilLze + */ +@Slf4j +@RestController +@RequestMapping("/api/verification") +public class VerificationCodeController { + + @Autowired + private VerificationCodeService verificationCodeService; + + /** + * 发送邮箱验证码 + * @param email 邮箱地址 + * @return 结果 + */ + @PostMapping("/send-email-code") + public Result sendEmailCode(@RequestParam String email) { + // 参数校验 + if (!StringUtils.hasText(email)) { + return Result.error(ResultCode.PARAM_ERROR, "邮箱地址不能为空"); + } + + // 简单的邮箱格式校验 + if (!isValidEmail(email)) { + return Result.error(ResultCode.PARAM_ERROR, "邮箱格式不正确"); + } + + // 发送验证码 + boolean success = verificationCodeService.sendEmailCode(email); + + if (success) { + return Result.success(ResultCode.CODE_SENT, "验证码已发送到您的邮箱,请查收"); + } else { + return Result.error(ResultCode.CODE_SEND_FAIL, "验证码发送失败,请稍后重试"); + } + } + + /** + * 验证邮箱验证码 + * @param email 邮箱地址 + * @param code 验证码 + * @return 结果 + */ + @PostMapping("/verify-email-code") + public Result verifyEmailCode(@RequestParam String email, @RequestParam String code) { + // 参数校验 + if (!StringUtils.hasText(email)) { + return Result.error(ResultCode.PARAM_ERROR, "邮箱地址不能为空"); + } + + if (!StringUtils.hasText(code)) { + return Result.error(ResultCode.PARAM_ERROR, "验证码不能为空"); + } + + // 验证验证码 + boolean success = verificationCodeService.verifyEmailCode(email, code); + + if (success) { + return Result.success(ResultCode.SUCCESS, "验证码验证成功"); + } else { + return Result.error(ResultCode.CODE_ERROR, "验证码错误或已过期"); + } + } + + /** + * 简单的邮箱格式校验 + * @param email 邮箱地址 + * @return 是否有效 + */ + private boolean isValidEmail(String email) { + if (email == null || email.trim().isEmpty()) { + return false; + } + // 简单的邮箱格式校验:包含@和. + return email.contains("@") && email.contains(".") && email.length() > 5; + } +} + diff --git a/src/main/java/com/bao/dating/service/VerificationCodeService.java b/src/main/java/com/bao/dating/service/VerificationCodeService.java new file mode 100644 index 0000000..81bcd76 --- /dev/null +++ b/src/main/java/com/bao/dating/service/VerificationCodeService.java @@ -0,0 +1,31 @@ +package com.bao.dating.service; + +/** + * 验证码服务接口 + * @author KilLze + */ +public interface VerificationCodeService { + + /** + * 发送邮箱验证码 + * @param email 邮箱地址 + * @return 是否发送成功 + */ + boolean sendEmailCode(String email); + + /** + * 验证邮箱验证码 + * @param email 邮箱地址 + * @param code 验证码 + * @return 是否验证成功 + */ + boolean verifyEmailCode(String email, String code); + + /** + * 生成验证码 + * @param length 验证码长度(默认6位) + * @return 验证码字符串 + */ + String generateCode(int length); +} + diff --git a/src/main/java/com/bao/dating/service/impl/VerificationCodeServiceImpl.java b/src/main/java/com/bao/dating/service/impl/VerificationCodeServiceImpl.java new file mode 100644 index 0000000..19bae75 --- /dev/null +++ b/src/main/java/com/bao/dating/service/impl/VerificationCodeServiceImpl.java @@ -0,0 +1,122 @@ +package com.bao.dating.service.impl; + +import com.bao.dating.service.VerificationCodeService; +import com.bao.dating.util.EmailUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Service; + +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/** + * 验证码服务实现类 + * @author KilLze + */ +@Slf4j +@Service +public class VerificationCodeServiceImpl implements VerificationCodeService { + + @Autowired + private EmailUtil emailUtil; + + @Autowired + private StringRedisTemplate redisTemplate; + + /** + * Redis中验证码的key前缀 + */ + private static final String CODE_KEY_PREFIX = "email:code:"; + + /** + * 验证码过期时间(分钟) + */ + private static final long CODE_EXPIRE_MINUTES = 10; + + /** + * 验证码长度 + */ + private static final int CODE_LENGTH = 6; + + /** + * 发送邮箱验证码 + * @param email 邮箱地址 + * @return 是否发送成功 + */ + @Override + public boolean sendEmailCode(String email) { + try { + // 生成验证码 + String code = generateCode(CODE_LENGTH); + + // 存储到Redis,设置过期时间 + String key = CODE_KEY_PREFIX + email; + redisTemplate.opsForValue().set(key, code, CODE_EXPIRE_MINUTES, TimeUnit.MINUTES); + + // 发送邮件 + boolean sendResult = emailUtil.sendVerificationCode(email, code); + + if (sendResult) { + log.info("邮箱验证码发送成功,邮箱:{},验证码:{}", email, code); + return true; + } else { + // 如果发送失败,删除Redis中的验证码 + redisTemplate.delete(key); + log.error("邮箱验证码发送失败,邮箱:{}", email); + return false; + } + } catch (Exception e) { + log.error("发送邮箱验证码异常,邮箱:{},异常信息:{}", email, e.getMessage(), e); + return false; + } + } + + /** + * 验证邮箱验证码 + * @param email 邮箱地址 + * @param code 验证码 + * @return 是否验证成功 + */ + @Override + public boolean verifyEmailCode(String email, String code) { + try { + String key = CODE_KEY_PREFIX + email; + String storedCode = redisTemplate.opsForValue().get(key); + + if (storedCode == null) { + log.warn("验证码不存在或已过期,邮箱:{}", email); + return false; + } + + if (storedCode.equals(code)) { + // 验证成功后,删除验证码(防止重复使用) + redisTemplate.delete(key); + log.info("邮箱验证码验证成功,邮箱:{}", email); + return true; + } else { + log.warn("邮箱验证码错误,邮箱:{},输入的验证码:{},正确的验证码:{}", email, code, storedCode); + return false; + } + } catch (Exception e) { + log.error("验证邮箱验证码异常,邮箱:{},异常信息:{}", email, e.getMessage(), e); + return false; + } + } + + /** + * 生成验证码 + * @param length 验证码长度 + * @return 验证码字符串 + */ + @Override + public String generateCode(int length) { + Random random = new Random(); + StringBuilder code = new StringBuilder(); + for (int i = 0; i < length; i++) { + code.append(random.nextInt(10)); // 生成0-9的随机数字 + } + return code.toString(); + } +} + diff --git a/src/main/java/com/bao/dating/util/MD5Util.java b/src/main/java/com/bao/dating/util/MD5Util.java index 1e8cfc7..e69de29 100644 --- a/src/main/java/com/bao/dating/util/MD5Util.java +++ b/src/main/java/com/bao/dating/util/MD5Util.java @@ -1,93 +0,0 @@ -package com.bao.dating.util; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -/** - * MD5工具类 - * 提供MD5加密功能 - * @author KilLze - */ -public class MD5Util { - - /** - * 对字符串进行MD5加密 - * @param input 待加密的字符串 - * @return MD5加密后的32位小写字符串 - */ - public static String encrypt(String input) { - if (input == null || input.isEmpty()) { - return null; - } - - try { - MessageDigest md = MessageDigest.getInstance("MD5"); - byte[] digest = md.digest(input.getBytes()); - return bytesToHex(digest); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException("MD5算法不可用", e); - } - } - - /** - * 对字符串进行MD5加密(带盐值) - * @param input 待加密的字符串 - * @param salt 盐值 - * @return MD5加密后的32位小写字符串 - */ - public static String encryptWithSalt(String input, String salt) { - if (input == null || input.isEmpty()) { - return null; - } - if (salt == null) { - salt = ""; - } - return encrypt(input + salt); - } - - /** - * 验证字符串与MD5值是否匹配 - * @param input 原始字符串 - * @param md5Hash MD5哈希值 - * @return 是否匹配 - */ - public static boolean verify(String input, String md5Hash) { - if (input == null || md5Hash == null) { - return false; - } - return encrypt(input).equalsIgnoreCase(md5Hash); - } - - /** - * 验证字符串与MD5值是否匹配(带盐值) - * @param input 原始字符串 - * @param salt 盐值 - * @param md5Hash MD5哈希值 - * @return 是否匹配 - */ - public static boolean verifyWithSalt(String input, String salt, String md5Hash) { - if (input == null || md5Hash == null) { - return false; - } - if (salt == null) { - salt = ""; - } - return encryptWithSalt(input, salt).equalsIgnoreCase(md5Hash); - } - - /** - * 将字节数组转换为十六进制字符串 - * @param bytes 字节数组 - * @return 十六进制字符串 - */ - private static String bytesToHex(byte[] bytes) { - StringBuilder sb = new StringBuilder(); - for (byte b : bytes) { - sb.append(String.format("%02x", b)); - } - return sb.toString(); - } -} - - - diff --git a/src/test/java/com/bao/dating/service/VerificationCodeServiceTest.java b/src/test/java/com/bao/dating/service/VerificationCodeServiceTest.java new file mode 100644 index 0000000..b809304 --- /dev/null +++ b/src/test/java/com/bao/dating/service/VerificationCodeServiceTest.java @@ -0,0 +1,91 @@ +package com.bao.dating.service; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +/** + * 验证码服务测试类 + * @author KilLze + */ +@SpringBootTest +public class VerificationCodeServiceTest { + + @Autowired + private VerificationCodeService verificationCodeService; + + /** + * 测试发送邮箱验证码 + */ + @Test + public void testSendEmailCode() { + String email = "test@example.com"; // 请修改为实际邮箱地址 + + System.out.println("========== 发送邮箱验证码测试 =========="); + System.out.println("邮箱地址: " + email); + + boolean result = verificationCodeService.sendEmailCode(email); + + System.out.println("发送结果: " + (result ? "成功" : "失败")); + System.out.println("====================================="); + } + + /** + * 测试验证邮箱验证码 + */ + @Test + public void testVerifyEmailCode() { + String email = "test@example.com"; // 请修改为实际邮箱地址 + String code = "123456"; // 请修改为实际收到的验证码 + + System.out.println("========== 验证邮箱验证码测试 =========="); + System.out.println("邮箱地址: " + email); + System.out.println("验证码: " + code); + + boolean result = verificationCodeService.verifyEmailCode(email, code); + + System.out.println("验证结果: " + (result ? "成功" : "失败")); + System.out.println("====================================="); + } + + /** + * 测试完整流程:发送验证码 -> 验证验证码 + */ + @Test + public void testCompleteFlow() { + String email = "test@example.com"; // 请修改为实际邮箱地址 + + System.out.println("========== 完整流程测试 =========="); + System.out.println("邮箱地址: " + email); + + // 1. 发送验证码 + System.out.println("\n1. 发送验证码..."); + boolean sendResult = verificationCodeService.sendEmailCode(email); + System.out.println("发送结果: " + (sendResult ? "成功" : "失败")); + + if (sendResult) { + // 2. 等待用户输入验证码(这里模拟,实际应该从控制台或API获取) + System.out.println("\n2. 请查看邮箱获取验证码,然后手动测试验证功能"); + System.out.println(" 使用 testVerifyEmailCode() 方法进行验证"); + } + + System.out.println("\n====================================="); + } + + /** + * 测试生成验证码 + */ + @Test + public void testGenerateCode() { + System.out.println("========== 生成验证码测试 =========="); + + // 测试不同长度的验证码 + for (int length = 4; length <= 8; length++) { + String code = verificationCodeService.generateCode(length); + System.out.println(length + "位验证码: " + code); + } + + System.out.println("====================================="); + } +} + diff --git a/src/test/java/com/bao/dating/util/EmailAndSmsTest.java b/src/test/java/com/bao/dating/util/EmailAndSmsTest.java index 55014bf..86ced71 100644 --- a/src/test/java/com/bao/dating/util/EmailAndSmsTest.java +++ b/src/test/java/com/bao/dating/util/EmailAndSmsTest.java @@ -75,3 +75,4 @@ public class EmailAndSmsTest { + From a6259875f234b315deaf84bf7e72138316f0c719 Mon Sep 17 00:00:00 2001 From: KilLze Date: Mon, 5 Jan 2026 10:49:32 +0800 Subject: [PATCH 37/37] =?UTF-8?q?=E4=BF=AE=E6=B6=88=E5=A4=B1=E7=9A=84MD5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/bao/dating/util/MD5Util.java | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/src/main/java/com/bao/dating/util/MD5Util.java b/src/main/java/com/bao/dating/util/MD5Util.java index e69de29..1e8cfc7 100644 --- a/src/main/java/com/bao/dating/util/MD5Util.java +++ b/src/main/java/com/bao/dating/util/MD5Util.java @@ -0,0 +1,93 @@ +package com.bao.dating.util; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * MD5工具类 + * 提供MD5加密功能 + * @author KilLze + */ +public class MD5Util { + + /** + * 对字符串进行MD5加密 + * @param input 待加密的字符串 + * @return MD5加密后的32位小写字符串 + */ + public static String encrypt(String input) { + if (input == null || input.isEmpty()) { + return null; + } + + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] digest = md.digest(input.getBytes()); + return bytesToHex(digest); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("MD5算法不可用", e); + } + } + + /** + * 对字符串进行MD5加密(带盐值) + * @param input 待加密的字符串 + * @param salt 盐值 + * @return MD5加密后的32位小写字符串 + */ + public static String encryptWithSalt(String input, String salt) { + if (input == null || input.isEmpty()) { + return null; + } + if (salt == null) { + salt = ""; + } + return encrypt(input + salt); + } + + /** + * 验证字符串与MD5值是否匹配 + * @param input 原始字符串 + * @param md5Hash MD5哈希值 + * @return 是否匹配 + */ + public static boolean verify(String input, String md5Hash) { + if (input == null || md5Hash == null) { + return false; + } + return encrypt(input).equalsIgnoreCase(md5Hash); + } + + /** + * 验证字符串与MD5值是否匹配(带盐值) + * @param input 原始字符串 + * @param salt 盐值 + * @param md5Hash MD5哈希值 + * @return 是否匹配 + */ + public static boolean verifyWithSalt(String input, String salt, String md5Hash) { + if (input == null || md5Hash == null) { + return false; + } + if (salt == null) { + salt = ""; + } + return encryptWithSalt(input, salt).equalsIgnoreCase(md5Hash); + } + + /** + * 将字节数组转换为十六进制字符串 + * @param bytes 字节数组 + * @return 十六进制字符串 + */ + private static String bytesToHex(byte[] bytes) { + StringBuilder sb = new StringBuilder(); + for (byte b : bytes) { + sb.append(String.format("%02x", b)); + } + return sb.toString(); + } +} + + +