0


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

一、今日目标

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

二、🎈SpringBoot部分类的添加

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

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

2.2 UserQueryParam添加

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

  1. @Data
  2. public class UserQueryParam extends PageParam {
  3. private String loginName;
  4. }

2.3 UserSaveParam添加

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

  1. @Data
  2. public class UserSaveParam {
  3. private Long id;
  4. @NotNull(message = "【用户名】不能为空")
  5. private String loginName;
  6. @NotNull(message = "【昵称】不能为空")
  7. private String name;
  8. @NotNull(message = "【密码】不能为空")
  9. @Pattern(regexp = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,32}$", message = "【密码】至少包含 数字和英文,长度6-32")
  10. private String password;
  11. }

2.4 UserResetPasswordParam添加

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

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

2.5 UserQueryVo添加

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

  1. @Data
  2. @NoArgsConstructor
  3. @AllArgsConstructor
  4. public class UserQueryVo {
  5. private Long id;
  6. private String loginName;
  7. private String name;
  8. private String password;
  9. }

2.6 SnowFlake工具类

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

  1. /**
  2. * Twitter的分布式自增ID雪花算法
  3. **/
  4. @Component
  5. public class SnowFlake {
  6. /**
  7. * 起始的时间戳
  8. */
  9. private final static long START_STMP = 1609459200000L; // 2021-01-01 00:00:00
  10. /**
  11. * 每一部分占用的位数
  12. */
  13. private final static long SEQUENCE_BIT = 12; //序列号占用的位数
  14. private final static long MACHINE_BIT = 5; //机器标识占用的位数
  15. private final static long DATACENTER_BIT = 5;//数据中心占用的位数
  16. /**
  17. * 每一部分的最大值
  18. */
  19. private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);
  20. private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
  21. private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);
  22. /**
  23. * 每一部分向左的位移
  24. */
  25. private final static long MACHINE_LEFT = SEQUENCE_BIT;
  26. private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
  27. private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;
  28. private long datacenterId = 1; //数据中心
  29. private long machineId = 1; //机器标识
  30. private long sequence = 0L; //序列号
  31. private long lastStmp = -1L;//上一次时间戳
  32. public SnowFlake() {
  33. }
  34. public SnowFlake(long datacenterId, long machineId) {
  35. if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) {
  36. throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0");
  37. }
  38. if (machineId > MAX_MACHINE_NUM || machineId < 0) {
  39. throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0");
  40. }
  41. this.datacenterId = datacenterId;
  42. this.machineId = machineId;
  43. }
  44. /**
  45. * 产生下一个ID
  46. *
  47. * @return
  48. */
  49. public synchronized long nextId() {
  50. long currStmp = getNewstmp();
  51. if (currStmp < lastStmp) {
  52. throw new RuntimeException("Clock moved backwards. Refusing to generate id");
  53. }
  54. if (currStmp == lastStmp) {
  55. //相同毫秒内,序列号自增
  56. sequence = (sequence + 1) & MAX_SEQUENCE;
  57. //同一毫秒的序列数已经达到最大
  58. if (sequence == 0L) {
  59. currStmp = getNextMill();
  60. }
  61. } else {
  62. //不同毫秒内,序列号置为0
  63. sequence = 0L;
  64. }
  65. lastStmp = currStmp;
  66. return (currStmp - START_STMP) << TIMESTMP_LEFT //时间戳部分
  67. | datacenterId << DATACENTER_LEFT //数据中心部分
  68. | machineId << MACHINE_LEFT //机器标识部分
  69. | sequence; //序列号部分
  70. }
  71. private long getNextMill() {
  72. long mill = getNewstmp();
  73. while (mill <= lastStmp) {
  74. mill = getNewstmp();
  75. }
  76. return mill;
  77. }
  78. private long getNewstmp() {
  79. return System.currentTimeMillis();
  80. }
  81. }

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

三、🚆后端新增接口

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

  1. @RestController
  2. @RequestMapping("/user")
  3. public class UserController {
  4. @Autowired
  5. private UserService userService;
  6. }

3.1 /user/list接口添加

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

  1. @RequestMapping("/list")
  2. public CommonResp list(@Validated UserQueryParam userQueryParam){
  3. PageVo<UserQueryVo> list = userService.list(userQueryParam);
  4. return new CommonResp(true,"查找成功", list);
  5. }

UserServiceImpl中的list接口。

  1. public PageVo<UserQueryVo> list(UserQueryParam userQueryParam) {
  2. // 构建一个表达式来筛选用户
  3. LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
  4. queryWrapper.eq(StringUtils.isNotBlank(userQueryParam.getLoginName()),
  5. User::getLoginName,userQueryParam.getLoginName());
  6. // 创建分页查询的对象
  7. Page<User> page = new Page<>(userQueryParam.getPage(),userQueryParam.getSize());
  8. // 接收分页查询的结果
  9. Page<User> resultPage = userMapper.selectPage(page, queryWrapper);
  10. // 这个对象用于返回给前端
  11. PageVo<UserQueryVo> pageVo = new PageVo<>();
  12. // 将分页查询的结果转换一下 User-》UserQueryVo
  13. List<UserQueryVo> users = CopyUtil.copyList(resultPage.getRecords(),UserQueryVo.class);
  14. pageVo.setList(users);
  15. pageVo.setTotal(resultPage.getTotal());
  16. return pageVo;
  17. }

3.2 /user/save接口添加

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

  1. @PostMapping("/save")
  2. public CommonResp save(@Valid @RequestBody UserSaveParam userSaveParam) {
  3. userSaveParam.setPassword(DigestUtils.md5DigestAsHex(userSaveParam.getPassword().getBytes()));
  4. boolean save = userService.save(userSaveParam);
  5. String message = Boolean.TRUE.equals(save) ? "添加成功":"添加失败";
  6. return new CommonResp<>(save,message,null);
  7. }

UserServiceImpl中的save接口。

  1. public boolean save(UserSaveParam userSaveParam) {
  2. User user = CopyUtil.copy(userSaveParam, User.class);
  3. if (ObjectUtils.isEmpty(userSaveParam.getId())) {
  4. User userDB = selectByLoginName(userSaveParam.getLoginName());
  5. if (ObjectUtils.isEmpty(userDB)) {
  6. // 新增
  7. user.setId(snowFlake.nextId());
  8. userMapper.insert(user);
  9. } else {
  10. // 用户名已存在
  11. throw new RuntimeException("用户存在");
  12. }
  13. } else {
  14. // 更新
  15. user.setLoginName(null);
  16. user.setPassword(null);
  17. userMapper.updateById(user);
  18. }
  19. return true;
  20. }
  21. private User selectByLoginName(String loginName) {
  22. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  23. queryWrapper.eq("login_name", loginName);
  24. return userMapper.selectOne(queryWrapper);
  25. }

3.3 /user/delete接口添加

这一部分就更简单了。

  1. @DeleteMapping("/delete/{id}")
  2. public CommonResp delete(@PathVariable Long id) {
  3. boolean res = userService.removeById(id);
  4. String message = Boolean.TRUE.equals(res) ? "删除成功":"删除失败";
  5. return new CommonResp<>(res,message,null);
  6. }

3.4 /user/reset-password接口添加

  1. @PostMapping("/reset-password")
  2. public CommonResp resetPassword(@Valid @RequestBody UserResetPasswordParam req) {
  3. req.setPassword(DigestUtils.md5DigestAsHex(req.getPassword().getBytes()));
  4. userService.resetPassword(req);
  5. return new CommonResp(true,"密码重置成功",null);
  6. }

UserServiceImpl中的resetPassword接口。

  1. public void resetPassword(UserResetPasswordParam req) {
  2. User user = CopyUtil.copy(req, User.class);
  3. userMapper.updateById(user);
  4. }
标签: spring boot 后端 java

本文转载自: https://blog.csdn.net/qq_61024956/article/details/140884754
版权归原作者 熊哈哈O_o 所有, 如有侵权,请联系我们删除。

“【wiki知识库】07.用户管理后端SpringBoot部分”的评论:

还没有评论