趁热打铁:用户模块剩余服务层接口实现

接下来我们将趁热打铁完成UserService剩余的接口定义和实现。在这之前我们先完善下user实体的设计,增加一个个性签名的字段personal_signature

新增用户表个性签名

显然,我们第一个要改的就是pdm模型,

在这里插入图片描述

然后改本地h2库,右键新增column,

在这里插入图片描述

在这里插入图片描述

然后,放开build.gradle中注释掉的apply from: 'mbgen.gradle',刷新下gradle,user生成的model和mapper则更新完成。

完善UserService接口定义

下面我们一鼓作气,把剩余的用户接口都定义出来:

package com.xiaojuan.boot.service;

import ...

public interface UserService {

    ...

    UserInfoDTO login(String username, String password) throws BusinessException;

    void updatePersonalSignature(long userId, String signature);

    void checkAdminRole(byte role) throws BusinessException;

}

温馨提醒

当我们的接口命名做到见名知意的话,可以不写接口的文档注释

这里我们定义了一个用来保存登录成功后的用户信息的DTO:

package com.xiaojuan.boot.dto;

import ...

@Data
public class UserInfoDTO {
    /** 用户id */
    private Long id;
    private String userName;
    /** 用户角色 1-普通用户 2-管理员 */
    private Byte role;
    private String personalSignature;
}

实现用户登录逻辑

UserServiceImpl中实现:

@Override
public UserInfoDTO login(String username, String password) throws BusinessException {
    Assert.hasText(username, "用户名不能为空");
    Assert.hasText(password, "密码不能为空");
    // 按照用户名查询用户
    Optional<User> userOptional = userMapper.selectOne(c -> c.where(UserDynamicSqlSupport.username, isEqualTo(username)));
    if (!userOptional.isPresent()) {
        throw new BusinessException("用户名错误");
    }
    User user = userOptional.get();
    if (!passwordEncoder.matches(password, user.getPassword())) {
        throw new BusinessException("密码错误");
    }
    UserInfoDTO userInfoDTO = new UserInfoDTO();
    BeanUtils.copyProperties(user, userInfoDTO);
    return userInfoDTO;
}

代码说明

注意这里灵活运用了mybatis3的dynamic sql的特性来查询单条记录。

密码的匹配不能直接加密后和数据库比较,要先查出来,再用spring安全框架的PasswordEncodermatches来匹配,解铃还须系铃人嘛。

最后,因为UserInfoDTO中的字段都在User实体类中被涵盖了,因此我们无需手动一个个赋值,直接用spring提供的工具类,进行相同属性的拷贝即可。

剩余逻辑实现

@Override
public void updatePersonalSignature(long userId, String signature) {
    userMapper.update(c -> c.set(personalSignature).equalTo(signature)
                      .set(updateTime).equalTo(new Date())
                      .where(id, isEqualTo(userId)));
}

@Override
public void checkAdminRole(byte role) throws BusinessException {
    if (Role.ADMIN.getValue() != role) {
        throw new BusinessException("非管理员角色,不能操作!");
    }
}

代码说明

同样根据用户id来更新签名信息,我们也采用mybatis dynamic sql的形式。

在检查用户角色时,我们不是直接取管理员的角色数值进行比较,而是将角色维护为一个枚举:

package com.xiaojuan.boot.enums;

import ...

@Getter
@AllArgsConstructor
public enum Role {

    USER("普通用户", (byte)1),
    ADMIN("管理员", (byte)2);

    private final String label;
    private final Byte value;
}

因为在生成model时,对数据库的tinyint类型映射为java的byte类型,而不是int类型,虽然这不是我们的本意,但生成器也没提供很好的字段类型映射用户配置方式,我们就保留byte类型,勉为其难的做一次转换吧。

常量提取

不知道大家发现没有,我们在抛出异常消息和断言异常消息时,会写重复的字符串,很显然,更好的做法是将它们提取为常量。下面是提取技巧:

右键,Refactor:

在这里插入图片描述

提取为常量:

在这里插入图片描述

在这里插入图片描述

全部提取出来,放到UserService接口中

package com.xiaojuan.boot.service;

import ...

public interface UserService {

    String MSG_USERNAME_REQUIRED = "用户名不能为空";
    String MSG_USERNAME_EXISTS = "用户名已存在";
    String MSG_USERNAME_ERROR = "用户名错误";
    String MSG_PASSWORD_REQUIRED = "密码不能为空";
    String MSG_PASSWORD_ERROR = "密码错误";
    String MSG_ADMIN_ROLE_REQUIRED = "非管理员角色,不能操作!";

    ...
}

这样我们在单元测试中直接引用这些常量即可。

完善单元测试

最后将我们的service层单元测试完善下:

@Test
public void testComposition() {
    // 先登录失败
    assertThatExceptionOfType(BusinessException.class).isThrownBy(() -> {
        userService.login("zhangsan", "123");
    }).withMessage(MSG_USERNAME_ERROR);

    // 注册张三用户
    userService.register(new UserRegisterDTO("zhangsan", "123"));

    // 密码错误
    assertThatExceptionOfType(BusinessException.class).isThrownBy(() -> {
        userService.login("zhangsan", "666");
    }).withMessage(MSG_PASSWORD_ERROR);

    // 登录成功
    UserInfoDTO user = userService.login("zhangsan", "123");

    // 检查没有权限
    assertThatExceptionOfType(BusinessException.class).isThrownBy(() -> {
        userService.checkAdminRole(user.getRole());
    }).withMessage(MSG_ADMIN_ROLE_REQUIRED);
}

我们把所有的单元测试跑下:

在这里插入图片描述

在这里插入图片描述

ok!都搞定!

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java小卷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值