ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

【项目】【在线判题系统】c端:个人中心

【项目】【在线判题系统】c端:个人中心

目录

  • 一、功能分析
  • 二、controller
  • 三、service
  • 四、缓存工具类
  • 五、拦截器修改
  • 六、tokenService修改

一、功能分析

个人中心,我们要支持当前登录用户的信息展示以及对信息的编辑。并且展示获得用户信息详情的时候还需要加入redis缓存。

二、controller

oj-modules/oj-friend/src/main/java/com/yj/friend/controller/user/UserController.java,接口

/** * 获取当前用户详情 * @return */@GetMapping("/detail")publicR<UserVO>detail(){returnR.success(userService.detail());}/** * 编辑当前用户信息 * @param userUpdateDTO * @return */@PutMapping("/edit")publicR<Void>edit(@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;@Getter@SetterpublicclassUserUpdateDTO{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;@Getter@SetterpublicclassUserVO{@JsonSerialize(using=ToStringSerializer.class)privateLonguserId;privateStringnickName;privateStringheadImage;privateIntegersex;privateStringphone;privateStringcode;privateStringemail;privateStringwechat;privateStringschoolName;privateStringmajorName;privateStringintroduce;privateIntegerstatus;}

三、service

oj-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中获取用户idLonguserId=ThreadLocalUtil.get(Constants.USER_ID,Long.class);//校验用户id是否存在if(userId==null){thrownewServiceException(ResultCodeEnum.FAILED_USER_NOT_EXISTS);}UserVOuserVO=userCacheManager.getUserById(userId);if(userVO==null){thrownewServiceException(ResultCodeEnum.FAILED_USER_NOT_EXISTS);}if(StrUtil.isNotEmpty(userVO.getHeadImage())){userVO.setHeadImage(downloadUrl+userVO.getHeadImage());}returnuserVO;}@Overridepublicintedit(UserUpdateDTOuserUpdateDTO){//从threadLocal中获取用户idLonguserId=ThreadLocalUtil.get(Constants.USER_ID,Long.class);//校验用户id是否存在if(userId==null){thrownewServiceException(ResultCodeEnum.FAILED_USER_NOT_EXISTS);}UserDOuserDO=userMapper.selectById(userId);if(userDO==null){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){//从缓存中获取用户信息StringuserKey=getUserKey(userId);UserVOuserVO=redisService.getCacheObject(userKey,UserVO.class);if(userVO!=null){//将缓存延长10minredisService.expire(userKey,CacheConstants.USER_EXP,TimeUnit.MINUTES);returnuserVO;}//缓存中不存在用户信息,从数据库中查询UserDOuser=userMapper.selectOne(newLambdaQueryWrapper<UserDO>().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(user==null){returnnull;}//数据库中存在用户信息,刷新用户缓存refreshUser(user);//将用户信息转换为用户VOuserVO=newUserVO();BeanUtil.copyProperties(user,userVO);returnuserVO;}//刷新用户缓存publicvoidrefreshUser(UserDOuser){//刷新用户缓存StringuserKey=getUserKey(user.getUserId());redisService.setCacheObject(userKey,user);//设置用户缓存有效期为10分钟redisService.expire(userKey,CacheConstants.USER_EXP,TimeUnit.MINUTES);}//获取用户缓存key//u:d:用户idprivateStringgetUserKey(LonguserId){returnCacheConstants.USER_DETAIL+userId;}}

五、拦截器修改

oj-common/oj-common-security/src/main/java/com/yj/common/security/interceptor/TokenInterceptor.java,加上userkey

@OverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)throwsException{Stringtoken=getToken(request);Claimsclaims=tokenService.getClaims(token,jwtSecret);LonguserId=tokenService.getUserId(claims);StringuserKey=tokenService.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.java

publicvoidrefreshLoginUser(StringnickName,StringheadImage,StringuserKey){StringtokenKey=getTokenKey(userKey);LoginUserloginUser=redisService.getCacheObject(tokenKey,LoginUser.class);loginUser.setNickName(nickName);loginUser.setHeadImage(headImage);redisService.setCacheObject(tokenKey,loginUser);}
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进