修改个人账号信息功能开发

 1、修改个人信息,在后端来看,就是对数据库表里面对应的字段进行更新,修改操作,我们用BO把前端的这些参数封装起来,统一传入我们的接口,同时用 @Valid 注解进行统一的参数校验

API接口编写

// 修改/完善账户信息 1:
    @ApiOperation(value = "修改/完善用户信息",notes = "修改/完善用户信息",httpMethod = "POST")
    @PostMapping("/updateUserInfo")
    public GraceJSONResult updateUserInfo(@RequestBody @Valid UpdateUserInfoBO updateUserInfoBO
                                          // feign的统一参数校验 1: 不可以写两个对象参数,认为传了两个body,统一异常处理进行封装
                                          );

2、 controller层代码编写,首先还是对前端传入进来的参数进行校验,判空

    @Override
    public GraceJSONResult updateUserInfo(@Valid UpdateUserInfoBO updateUserInfoBO) {
//                                          BindingResult bindingResult) {
//
//        // 0. 检验bo的前端参数
//        if (bindingResult.hasErrors()){
//            Map<String, String> map = getErrors(bindingResult);
//            return GraceJSONResult.errorMap(map);
//        }

        // 1. 执行更新操作  sevice层编写业务代码
        // 修改/完善账户信息 5:
        userService.updateUserInfo(updateUserInfoBO);
        return GraceJSONResult.ok();
    }

3、我们在service层进而编写我们的业务代码,由于用户的信息,在我们的网站里面,是经常访问到的信息,是一个高并发的数据,当网站的用户数量庞大的时候,频繁的获取用户的信息,对我们的数据库,存在很大的压力,所以我们会把用户的一个基本信息放到我们的redis里面进行缓存,查询用户信息的时候,首先查询我们的redis,redis查不到了再查询我们的数据库,在保存到redis里面,当涉及到更新用户的信息时,我们会先删掉我们redis里面的缓存信息,然后执行更新操作,在更新操作完成后,让这个更新的线程休眠一下,再次删掉我们的redis里面缓存

当有用户再次访问到这个用户信息的时候,就会先查询我们的redis,这些内容已在我们的查询用户的服务里面实现。

service 里面 对更新操作进行缓存延时双删的操作

// 修改/完善账户信息 4:
    @Override
    public void updateUserInfo(UpdateUserInfoBO updateUserInfoBO) {

        // 0. 更新的话,肯定是根据用户的主键id做更新的, 同时用持久层的对象做更新\
        String userId = updateUserInfoBO.getId();

        /**
         * 双写一致,缓存双删 1: 修改.更新时,先删除redis,后更新数据库
         */
        redis.del(REDIS_USER_INFO + ":" + userId);

        // 1. 同时用持久层的对象做更新, 把bo中的参数对象拷贝进入我们的持久层对象里面
        AppUser userInfo = new AppUser();
        BeanUtils.copyProperties(updateUserInfoBO,userInfo);

        // 2. 数据持久层对象里面的 更新时间需要做一个更新,同时信息完善后,对应激活状态做更改
        userInfo.setUpdatedTime(new Date());
        userInfo.setActiveStatus(UserStatus.ACTIVE.type);

        // 3. 更新到数据库里面
        // .updateByPrimaryKeySelective 会对为空的参数进行忽略,不会让空数据覆盖数据库里面原有的数据
        int result = appUserMapper.updateByPrimaryKeySelective(userInfo);
        if (result != 1){
            // 不为1 说明更新操作出了问题
            // 这样写的好处: 以往出了问题会会回传一个 FALSE ,在controller又进行判断,返回一个错误信息
            // 使用自定义异常,在这进行一个解耦,没有必要把一些多余的参数返回controller,在进行处理  详见 "统一异常处理 2"
            GraceException.display(ResponseStatusEnum.USER_UPDATE_ERROR);
        }

        // redis 缓存用户信息 5: 存在更新操作的地方,再次查询用户信息,更新覆盖到redis中
        AppUser user = getUser(userId);
        redis.set(REDIS_USER_INFO + ":" + userId, JsonUtils.objectToJson(user));

        /**
         * 双写一致,缓存双删 2: 更新完数据后,休眠一下,再删一次缓存
         */
        try {
            Thread.sleep(100);
            redis.del(REDIS_USER_INFO + ":" + userId);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }



    }

总结 :       

         // redis 缓存用户信息 6: 解决分布式并发访问的问题
        /**
         * 缓存双写不一致解决方案:
         * 用户做更新操作的时候,先去redis里面删除旧的数据,然后去数据库更新
         * 更新完数据库,其他用户来访问的时候,redis里面没有数据,去数据库查找,查到新的数据后更新到redis里面
         *
         * 缓存双删:  设置之前删除,设置之后删除
         * 上面的方案也有漏洞,有可能,用户删除redis的旧数据到更新数据库的这段时间里面,
         * 其他的用户,访问的时候,新的数据还没存入数据库,查到了旧的数据,然后把旧的放入了redis,这样新的数据就不能写入数据库了
         * 解决办法: 延时双删,当我们把新的数据放入数据库时,让这个线程休眠1秒钟,再次对redis的key进行删除
         *          就有可能把其他用户放入的redis旧数据删除
         */

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值