【wiki知识库】07.用户管理后端SpringBoot部分

目录

一、今日目标

二、🎈SpringBoot部分类的添加

[2.1 使用逆向工程新增User模块](#2.1 使用逆向工程新增User模块)

[2.2 UserQueryParam添加](#2.2 UserQueryParam添加)

[2.3 UserSaveParam添加](#2.3 UserSaveParam添加)

[2.4 UserResetPasswordParam添加](#2.4 UserResetPasswordParam添加)

[2.5 UserQueryVo添加](#2.5 UserQueryVo添加)

[2.6 SnowFlake工具类](#2.6 SnowFlake工具类)

三、🚆后端新增接口

[3.1 /user/list接口添加](#3.1 /user/list接口添加)

[3.2 /user/save接口添加](#3.2 /user/save接口添加)

[3.3 /user/delete接口添加](#3.3 /user/delete接口添加)

[3.4 /user/reset-password接口添加](#3.4 /user/reset-password接口添加)


一、今日目标

上一篇文章我把前端部分的代码给大家了,这篇文章就来实现上一篇文章没有完成的接口。

二、🎈SpringBoot部分类的添加

2.1 使用逆向工程新增User模块

这一块的代码和之前的相同,我们找到逆向工程的工具类后,把类的部分改为user即可。

2.2 UserQueryParam添加

这个类看名字也知道是用来用户查询的,要继承之前的分页类。

java 复制代码
@Data
public class UserQueryParam extends PageParam {
    private String loginName;
}

2.3 UserSaveParam添加

这个类是用来作为用户新增参数接收用的。这个类作为用户信息保存的参数类,在这个类中对于属性的值做了一些限制。用户名、昵称和密码不能为空,同时密码要匹配正则表达式,这个正则表达式限制了密码由数字和字母组成,并且长度在6-32位,如果上边有条件不满足,那么就会抛出message中的错误。

java 复制代码
@Data
public class UserSaveParam {
    private Long id;

    @NotNull(message = "【用户名】不能为空")
    private String loginName;

    @NotNull(message = "【昵称】不能为空")
    private String name;

    @NotNull(message = "【密码】不能为空")
    @Pattern(regexp = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,32}$", message = "【密码】至少包含 数字和英文,长度6-32")
    private String password;

}

2.4 UserResetPasswordParam添加

这个类用于重置用户密码,传入账号的id还有用户的新密码。同样也做了密码的安全性校验。

java 复制代码
@Data
public class UserResetPasswordParam {
    private Long id;

    @NotNull(message = "【密码】不能为空")
    @Pattern(regexp = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,32}$", message = "【密码】至少包含 数字和英文,长度6-32")
    private String password;
}

2.5 UserQueryVo添加

这个类作为用户查询结果返回。

java 复制代码
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserQueryVo {
    private Long id;

    private String loginName;

    private String name;

    private String password;

}

2.6 SnowFlake工具类

这个工具类的作用就是生成一个不会重复的id值,想要了解具体内容的小伙伴可以搜索一下雪花算法。现在我先不过多介绍,可能之后会补上这一部分。现在只要记住这个类可以帮你生成一个不会重复的id值就可以了。

java 复制代码
/**
 * Twitter的分布式自增ID雪花算法
 **/
@Component
public class SnowFlake {

    /**
     * 起始的时间戳
     */
    private final static long START_STMP = 1609459200000L; // 2021-01-01 00:00:00

    /**
     * 每一部分占用的位数
     */
    private final static long SEQUENCE_BIT = 12; //序列号占用的位数
    private final static long MACHINE_BIT = 5;   //机器标识占用的位数
    private final static long DATACENTER_BIT = 5;//数据中心占用的位数

    /**
     * 每一部分的最大值
     */
    private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);
    private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
    private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);

    /**
     * 每一部分向左的位移
     */
    private final static long MACHINE_LEFT = SEQUENCE_BIT;
    private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
    private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;

    private long datacenterId = 1;  //数据中心
    private long machineId = 1;     //机器标识
    private long sequence = 0L; //序列号
    private long lastStmp = -1L;//上一次时间戳

    public SnowFlake() {
    }

    public SnowFlake(long datacenterId, long machineId) {
        if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) {
            throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0");
        }
        if (machineId > MAX_MACHINE_NUM || machineId < 0) {
            throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0");
        }
        this.datacenterId = datacenterId;
        this.machineId = machineId;
    }

    /**
     * 产生下一个ID
     *
     * @return
     */
    public synchronized long nextId() {
        long currStmp = getNewstmp();
        if (currStmp < lastStmp) {
            throw new RuntimeException("Clock moved backwards.  Refusing to generate id");
        }

        if (currStmp == lastStmp) {
            //相同毫秒内,序列号自增
            sequence = (sequence + 1) & MAX_SEQUENCE;
            //同一毫秒的序列数已经达到最大
            if (sequence == 0L) {
                currStmp = getNextMill();
            }
        } else {
            //不同毫秒内,序列号置为0
            sequence = 0L;
        }

        lastStmp = currStmp;

        return (currStmp - START_STMP) << TIMESTMP_LEFT //时间戳部分
                | datacenterId << DATACENTER_LEFT       //数据中心部分
                | machineId << MACHINE_LEFT             //机器标识部分
                | sequence;                             //序列号部分
    }

    private long getNextMill() {
        long mill = getNewstmp();
        while (mill <= lastStmp) {
            mill = getNewstmp();
        }
        return mill;
    }

    private long getNewstmp() {
        return System.currentTimeMillis();
    }
}

上边的代码都没有什么难度,下面就开始实现用户管理的逻辑部分。

三、🚆后端新增接口

在UserController类中需要小小的修改一下。

java 复制代码
@RestController
@RequestMapping("/user")
public class UserController {
  @Autowired
  private UserService userService;
}

3.1 /user/list接口添加

其实这样的代码已经写了不少了,这样的list查询并没有什么难度,

java 复制代码
@RequestMapping("/list")
  public CommonResp list(@Validated UserQueryParam userQueryParam){
    PageVo<UserQueryVo> list = userService.list(userQueryParam);
    return new CommonResp(true,"查找成功", list);
  }

UserServiceImpl中的list接口。

java 复制代码
 public PageVo<UserQueryVo> list(UserQueryParam userQueryParam) {
        // 构建一个表达式来筛选用户
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotBlank(userQueryParam.getLoginName()),
                User::getLoginName,userQueryParam.getLoginName());
        // 创建分页查询的对象
        Page<User> page = new Page<>(userQueryParam.getPage(),userQueryParam.getSize());
        // 接收分页查询的结果
        Page<User> resultPage = userMapper.selectPage(page, queryWrapper);
        // 这个对象用于返回给前端
        PageVo<UserQueryVo> pageVo = new PageVo<>();
        // 将分页查询的结果转换一下 User-》UserQueryVo
        List<UserQueryVo> users = CopyUtil.copyList(resultPage.getRecords(),UserQueryVo.class);
        pageVo.setList(users);
        pageVo.setTotal(resultPage.getTotal());
        return pageVo;
    }

3.2 /user/save接口添加

值得注意的是,在数据库当中,用户的密码我们不在进行明文存储了,我们存储的都是加密后的代码,这里仅仅使用了简单的md5加密算法,实际的加密码算法有很多种类型。

java 复制代码
@PostMapping("/save")
  public CommonResp save(@Valid @RequestBody UserSaveParam userSaveParam) {
    userSaveParam.setPassword(DigestUtils.md5DigestAsHex(userSaveParam.getPassword().getBytes()));
    boolean save = userService.save(userSaveParam);
    String message = Boolean.TRUE.equals(save) ? "添加成功":"添加失败";
    return new CommonResp<>(save,message,null);
  }

UserServiceImpl中的save接口。

java 复制代码
 public boolean save(UserSaveParam userSaveParam) {
        User user = CopyUtil.copy(userSaveParam, User.class);
        if (ObjectUtils.isEmpty(userSaveParam.getId())) {
            User userDB = selectByLoginName(userSaveParam.getLoginName());
            if (ObjectUtils.isEmpty(userDB)) {
                // 新增
                user.setId(snowFlake.nextId());
                userMapper.insert(user);
            } else {
                // 用户名已存在
                throw new RuntimeException("用户存在");
            }
        } else {
            // 更新
            user.setLoginName(null);
            user.setPassword(null);
            userMapper.updateById(user);
        }
        return true;
    }

 private User selectByLoginName(String loginName) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("login_name", loginName);
        return userMapper.selectOne(queryWrapper);
    }

3.3 /user/delete接口添加

这一部分就更简单了。

java 复制代码
  @DeleteMapping("/delete/{id}")
  public CommonResp delete(@PathVariable Long id) {
    boolean res = userService.removeById(id);
    String message = Boolean.TRUE.equals(res) ? "删除成功":"删除失败";
    return new CommonResp<>(res,message,null);
  }

3.4 /user/reset-password接口添加

java 复制代码
  @PostMapping("/reset-password")
  public CommonResp resetPassword(@Valid @RequestBody UserResetPasswordParam req) {
    req.setPassword(DigestUtils.md5DigestAsHex(req.getPassword().getBytes()));
    userService.resetPassword(req);
    return new CommonResp(true,"密码重置成功",null);
  }

UserServiceImpl中的resetPassword接口。

java 复制代码
    public void resetPassword(UserResetPasswordParam req) {
        User user = CopyUtil.copy(req, User.class);
        userMapper.updateById(user);
    }
相关推荐
qq_2518364572 分钟前
基于springboot+vue学生宿舍管理系统设计与实现
vue.js·spring boot·mfc
音符犹如代码6 分钟前
第十四届蓝桥杯真题Java c组D.平均(持续更新)
java·蓝桥杯
不修×蝙蝠11 分钟前
后端(实例)08
java·后端·servlet·eclipse
Pandaconda23 分钟前
【计算机网络 - 基础问题】每日 3 题(二十八)
开发语言·网络·经验分享·笔记·后端·计算机网络·面试
fieldsss31 分钟前
JAVA基础语法 day07
java·开发语言
芜婳32 分钟前
JVM 内存模型
java·开发语言·jvm
夏河始溢33 分钟前
一六九、go使用泛型封装一个可以应用于任何字段的模糊匹配
开发语言·后端·golang
码农研究僧35 分钟前
详细分析Mybatis中的动态Sql(附Demo)
xml·java·数据库·sql·mybatis
曲邹萌1 小时前
使用xml编写查询前提下MyBatisPlus分页IPage用法
java·前端·spring boot
黄俊懿1 小时前
【图解秒杀系列】秒杀技术点——隔离、熔断、限流、降级
分布式·后端·中间件·架构·秒杀