【项目】【在线判题系统】c端:个人中心
目录一、功能分析二、controller三、service四、缓存工具类五、拦截器修改六、tokenService修改一、功能分析个人中心我们要支持当前登录用户的信息展示以及对信息的编辑。并且展示获得用户信息详情的时候还需要加入redis缓存。二、controlleroj-modules/oj-friend/src/main/java/com/yj/friend/controller/user/UserController.java接口/** * 获取当前用户详情 * return */GetMapping(/detail)publicRUserVOdetail(){returnR.success(userService.detail());}/** * 编辑当前用户信息 * param userUpdateDTO * return */PutMapping(/edit)publicRVoidedit(RequestBodyUserUpdateDTOuserUpdateDTO){returntoR(userService.edit(userUpdateDTO));}oj-modules/oj-friend/src/main/java/com/yj/friend/domain/user/dto/UserUpdateDTO.java接收参数类packagecom.yj.friend.domain.user.dto;importlombok.Getter;importlombok.Setter;GetterSetterpublicclassUserUpdateDTO{privateStringheadImage;privateStringnickName;privateIntegersex;privateStringschoolName;privateStringmajorName;privateStringphone;privateStringemail;privateStringwechat;privateStringintroduce;}oj-modules/oj-friend/src/main/java/com/yj/friend/domain/user/vo/UserVO.java返回类packagecom.yj.friend.domain.user.vo;importcom.fasterxml.jackson.databind.annotation.JsonSerialize;importcom.fasterxml.jackson.databind.ser.std.ToStringSerializer;importlombok.Getter;importlombok.Setter;GetterSetterpublicclassUserVO{JsonSerialize(usingToStringSerializer.class)privateLonguserId;privateStringnickName;privateStringheadImage;privateIntegersex;privateStringphone;privateStringcode;privateStringemail;privateStringwechat;privateStringschoolName;privateStringmajorName;privateStringintroduce;privateIntegerstatus;}三、serviceoj-modules/oj-friend/src/main/java/com/yj/friend/service/user/IUserService.java接口方法UserVOdetail();intedit(UserUpdateDTOuserUpdateDTO);oj-modules/oj-friend/src/main/java/com/yj/friend/service/user/impl/UserService.java实现类。获取用户详情的时候先从redis缓存中获取如果没有从mysql获取并存入缓存。更新用户信息的时候也是缓存与数据库都更新。OverridepublicUserVOdetail(){//从threadLocal中获取用户idLonguserIdThreadLocalUtil.get(Constants.USER_ID,Long.class);//校验用户id是否存在if(userIdnull){thrownewServiceException(ResultCodeEnum.FAILED_USER_NOT_EXISTS);}UserVOuserVOuserCacheManager.getUserById(userId);if(userVOnull){thrownewServiceException(ResultCodeEnum.FAILED_USER_NOT_EXISTS);}if(StrUtil.isNotEmpty(userVO.getHeadImage())){userVO.setHeadImage(downloadUrluserVO.getHeadImage());}returnuserVO;}Overridepublicintedit(UserUpdateDTOuserUpdateDTO){//从threadLocal中获取用户idLonguserIdThreadLocalUtil.get(Constants.USER_ID,Long.class);//校验用户id是否存在if(userIdnull){thrownewServiceException(ResultCodeEnum.FAILED_USER_NOT_EXISTS);}UserDOuserDOuserMapper.selectById(userId);if(userDOnull){thrownewServiceException(ResultCodeEnum.FAILED_USER_NOT_EXISTS);}//更新用户信息userDO.setNickName(userUpdateDTO.getNickName());userDO.setHeadImage(userUpdateDTO.getHeadImage());userDO.setSex(userUpdateDTO.getSex());userDO.setPhone(userUpdateDTO.getPhone());userDO.setWechat(userUpdateDTO.getWechat());userDO.setSchoolName(userUpdateDTO.getSchoolName());userDO.setMajorName(userUpdateDTO.getMajorName());userDO.setIntroduce(userUpdateDTO.getIntroduce());userMapper.updateById(userDO);//更新缓存userCacheManager.refreshUser(userDO);//更新tokentokenService.refreshLoginUser(userDO.getNickName(),userDO.getHeadImage(),ThreadLocalUtil.get(Constants.USER_KEY,String.class));//更新数据库returnuserMapper.updateById(userDO);}四、缓存工具类oj-modules/oj-friend/src/main/java/com/yj/friend/manage/UserCacheManager.java提供获取缓存与更新缓存的方法。packagecom.yj.friend.manage;importcn.hutool.core.bean.BeanUtil;importcom.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;importcom.yj.common.core.constants.CacheConstants;importcom.yj.common.redis.service.RedisService;importcom.yj.friend.domain.user.UserDO;importcom.yj.friend.domain.user.vo.UserVO;importcom.yj.friend.mapper.user.UserMapper;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Component;importjava.util.concurrent.TimeUnit;ComponentpublicclassUserCacheManager{AutowiredprivateRedisServiceredisService;AutowiredprivateUserMapperuserMapper;publicUserVOgetUserById(LonguserId){//从缓存中获取用户信息StringuserKeygetUserKey(userId);UserVOuserVOredisService.getCacheObject(userKey,UserVO.class);if(userVO!null){//将缓存延长10minredisService.expire(userKey,CacheConstants.USER_EXP,TimeUnit.MINUTES);returnuserVO;}//缓存中不存在用户信息从数据库中查询UserDOuseruserMapper.selectOne(newLambdaQueryWrapperUserDO().select(UserDO::getUserId,UserDO::getNickName,UserDO::getHeadImage,UserDO::getSex,UserDO::getEmail,UserDO::getPhone,UserDO::getWechat,UserDO::getIntroduce,UserDO::getSchoolName,UserDO::getMajorName,UserDO::getStatus).eq(UserDO::getUserId,userId));//数据库中不存在用户信息if(usernull){returnnull;}//数据库中存在用户信息刷新用户缓存refreshUser(user);//将用户信息转换为用户VOuserVOnewUserVO();BeanUtil.copyProperties(user,userVO);returnuserVO;}//刷新用户缓存publicvoidrefreshUser(UserDOuser){//刷新用户缓存StringuserKeygetUserKey(user.getUserId());redisService.setCacheObject(userKey,user);//设置用户缓存有效期为10分钟redisService.expire(userKey,CacheConstants.USER_EXP,TimeUnit.MINUTES);}//获取用户缓存key//u:d:用户idprivateStringgetUserKey(LonguserId){returnCacheConstants.USER_DETAILuserId;}}五、拦截器修改oj-common/oj-common-security/src/main/java/com/yj/common/security/interceptor/TokenInterceptor.java加上userkeyOverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)throwsException{StringtokengetToken(request);ClaimsclaimstokenService.getClaims(token,jwtSecret);LonguserIdtokenService.getUserId(claims);StringuserKeytokenService.getUserKey(token,jwtSecret);ThreadLocalUtil.set(Constants.USER_ID,userId);ThreadLocalUtil.set(Constants.USER_KEY,userKey);tokenService.extendToken(token,jwtSecret);returntrue;}六、tokenService修改oj-common/oj-common-security/src/main/java/com/yj/common/security/service/TokenService.javapublicvoidrefreshLoginUser(StringnickName,StringheadImage,StringuserKey){StringtokenKeygetTokenKey(userKey);LoginUserloginUserredisService.getCacheObject(tokenKey,LoginUser.class);loginUser.setNickName(nickName);loginUser.setHeadImage(headImage);redisService.setCacheObject(tokenKey,loginUser);}

相关新闻

security-audit-skill:为编码助手构建代码安全审计技能包

security-audit-skill:为编码助手构建代码安全审计技能包

1. 从零拆解 security-audit-skill:一个让编码助手学会“自我安检”的技能包第一次看到security-audit-skill这个名字,我脑子里蹦出来的画面是机场安检——所有行李必须过一遍 X 光机,可疑物品当场拦下。这个项目本质上就是给编码助手&#x…

2026/10/17 6:21:45 阅读更多 →
龙芯LSDC显示控制器DRM驱动源码深度解析

龙芯LSDC显示控制器DRM驱动源码深度解析

读龙芯集成显示控制器的驱动源码之前,我一直觉得做国产平台的显示驱动无非就是"映射寄存器、填几个sync参数、把帧缓冲地址交给屏幕"三件事。真正把LS系列DCU对应到 Linux 内核的 DRM 驱动、完整梳理一遍 LSDC 的实现之后才明白,复杂度和风险点…

2026/10/17 6:21:45 阅读更多 →
C/C++调试实战:用GDB快速定位崩溃、死锁与内存问题

C/C++调试实战:用GDB快速定位崩溃、死锁与内存问题

写了几年C/C,我越来越觉得,调试能力和写代码能力完全是两码事。很多人写代码飞快,一遇到段错误就开始瞎猜,加printf、注释代码、重启程序,折腾几个小时也不一定定位到问题。其实大多数崩溃、死锁、内存越界&#xff0c…

2026/10/17 6:21:45 阅读更多 →

最新新闻

Harbor私有镜像仓库部署与运维实践:从架构到避坑指南

Harbor私有镜像仓库部署与运维实践:从架构到避坑指南

一套业务系统跑了一两年,环境中几十上百个容器,镜像分散在各台机器甚至每个人电脑里,等到要统一发版、回滚版本的时候,才发现连一个准确的镜像清单都凑不出来。这种场景我想很多团队都经历过。所以当我的某位合作伙伴第一次提出“…

2026/10/17 6:54:01 阅读更多 →
Multi-Raft架构设计:从单Raft瓶颈到分布式分片扩展实践

Multi-Raft架构设计:从单Raft瓶颈到分布式分片扩展实践

1. 项目概述与核心目标如果你维护过一个采用 Raft 共识的分布式数据库,大概率会碰到这个场景:单组 Raft 的写吞吐量撑不住业务增长,CPU 和磁盘的扩展能力已经到顶,数据量稍微上来一些,日志复制的压力就像滚雪球一样越滚…

2026/10/17 6:54:01 阅读更多 →
AI大模型面试:RAG怎么处理PDF中的表格?AI不会管你的成本,不会管实现难度

AI大模型面试:RAG怎么处理PDF中的表格?AI不会管你的成本,不会管实现难度

文章目录 一、面试现场:一个问题暴露真实水平 二、表格为什么是RAG的"噩梦"? 2.1 切片即毁灭:表头和数据行被生生拆开 2.2 真实企业场景:表格远比你想象的复杂 2.3 网上那些"方案"为什么不切实际? 三、企业级三大解决方案(核心干货) 3.1 方案一:多…

2026/10/17 6:54:01 阅读更多 →
Linux-多文件工程

Linux-多文件工程

vsp 文件名 :分屏操作Ctrl ww :切换屏幕Ctrl w :平分大小wq:退出1. 其他 文件 .c只需包含自己的 .h 用 “ ” 包含2. 此时对应的 .h定义自己那一套 包别人 声明(结构体,函数)eg&#xff…

2026/10/17 6:54:01 阅读更多 →
西邮Linux兴趣小组2024纳新面试题

西邮Linux兴趣小组2024纳新面试题

西邮Linux兴趣小组2024纳新面试题 0.聪明的吗喽 猴子每走一米会消耗掉三根香蕉,分别是往前走一米会消耗一根,返回起点会消耗一根,再搬另外50根会再消耗一根,一共消耗三根,所以我们只需要找到一个中转站,使香…

2026/10/17 6:54:01 阅读更多 →
Linux本地NTP时间服务器搭建与高可用运维实践

Linux本地NTP时间服务器搭建与高可用运维实践

1. 项目概述:为什么你需要一个本地时间服务器,而不是直接靠公网NTP?“ntpd建立本地时间服务器供所有本地linux服务器使用”——这句话背后藏着一个被很多运维新人忽略的硬伤:时间不同步不是小问题,而是系统性风险的导火…

2026/10/17 6:53:01 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →