当抽象方法已经设计好了,就应该在实现类中实现以上抽象方法:
@Autowired ClassInfoMapper classInfoMapper; @Autowired UserMapper userMapper; public void registerStudent(User user, String inviteCode) { // 【由于当前项目设计的规则是“学生账号通过手机号码注册、登录”,必须保证手机号码唯一】 // 调用ClassInfoMapper对象的selectOne()方法,根据参数inviteCode邀请码,查询class_info表 // 判断查询结果是否为空 // 是:表示没有找到有效的邀请码,不允许注册,抛出InviteCodeException // 从以上查询到的班级信息中取出enabled,判断是否为0 // 是:表示该班级已禁用,不允许注册该班级的学生账号,抛出ClassDisabledException // 从参数user中取出手机号码 // 调用UserMapper对象的selectOne()方法,根据手机号码查询学生账号信息 // 判断查询结果是否不为null // 是:找到了学生信息,表示手机号码已经被占用,则不允许注册,抛出PhoneDuplicateException // 没有找到学生信息,表示手机号码没有被占用,则允许注册…… // 确保参数user中的数据全部是有效的 // - 取出参数user中的密码,调用私有的encode()方法进行加密,并将加密后的密码封装回到user中 // - classId:此前验证邀请码时得到的结果 // - createdTime:当前时间,LocalDateTime.now() // - enabled:1,允许使用 // - locked:0,不锁定 // - type:0,表示学生 // 调用UserMapper对象的insert()方法,根据参数user插入数据,获取返回值 // 判断返回值(受影响的行数)是否不为1 // 是:受影响的行数不是1,则插入用户数据失败,抛出InsertException } @Autowired PasswordEncoder passwordEncoder; // 将密码进行加密的方法 private String encode(String rawPassword) { String encodePassword = passwordEncoder.encode(rawPassword); return encodePassword; }
在编写业务代码时,尽量根据“能够抛出异常”或其它能够使得方法运行结束为标准来写if语句的判断条件,以避免出现太多的if嵌套!
具体实现代码为:
package cn.tedu.straw.portal.service.impl; import cn.tedu.straw.portal.mapper.ClassInfoMapper; import cn.tedu.straw.portal.mapper.UserMapper; import cn.tedu.straw.portal.model.ClassInfo; import cn.tedu.straw.portal.model.User; import cn.tedu.straw.portal.service.IUserService; import cn.tedu.straw.portal.service.ex.ClassDisabledException; import cn.tedu.straw.portal.service.ex.InsertException; import cn.tedu.straw.portal.service.ex.InviteCodeException; import cn.tedu.straw.portal.service.ex.PhoneDuplicateException; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import java.time.LocalDateTime; /** * <p> * 服务实现类 * </p> * * @author tedu.cn * @since 2020-07-14 */ @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService { @Autowired private ClassInfoMapper classInfoMapper; @Autowired private UserMapper userMapper; @Autowired private PasswordEncoder passwordEncoder; @Override public void registerStudent(User user, String inviteCode) { // 【由于当前项目设计的规则是“学生账号通过手机号码注册、登录”,必须保证手机号码唯一】 // 调用ClassInfoMapper对象的selectOne()方法,根据参数inviteCode邀请码,查询class_info表 QueryWrapper<ClassInfo> classQueryWrapper = new QueryWrapper<>(); classQueryWrapper.eq("invite_code", inviteCode); ClassInfo classInfo = classInfoMapper.selectOne(classQueryWrapper); // 判断查询结果是否为空 if (classInfo == null) { // 是:表示没有找到有效的邀请码,不允许注册,抛出InviteCodeException throw new InviteCodeException(); } // 从以上查询到的班级信息中取出enabled,判断是否为0 if (classInfo.getEnabled() == 0) { // 是:表示该班级已禁用,不允许注册该班级的学生账号,抛出ClassDisabledException throw new ClassDisabledException(); } // 从参数user中取出手机号码 String phone = user.getPhone(); // 调用UserMapper对象的selectOne()方法,根据手机号码查询学生账号信息 QueryWrapper<User> userQueryWrapper = new QueryWrapper<>(); userQueryWrapper.eq("phone", user.getPhone()); User result = userMapper.selectOne(userQueryWrapper); // 判断查询结果是否不为null if (result != null) { // 是:找到了学生信息,表示手机号码已经被占用,则不允许注册,抛出PhoneDuplicateException throw new PhoneDuplicateException(); } // 没有找到学生信息,表示手机号码没有被占用,则允许注册…… // 确保参数user中的数据全部是有效的 // - 取出参数user中的密码,调用私有的encode()方法进行加密,并将加密后的密码封装回到user中 String rawPassword = user.getPassword(); String encodePassword = encode(rawPassword); user.setPassword(encodePassword); // - classId:此前验证邀请码时得到的结果 user.setClassId(classInfo.getId()); // - createdTime:当前时间,LocalDateTime.now() user.setCreatedTime(LocalDateTime.now()); // - enabled:1,允许使用 user.setEnabled(1); // - locked:0,不锁定 user.setLocked(0); // - type:0,表示学生 user.setType(0); // 调用UserMapper对象的insert()方法,根据参数user插入数据,获取返回值 int rows = userMapper.insert(user); // 判断返回值(受影响的行数)是否不为1 if (rows != 1) { // 是:受影响的行数不是1,则插入用户数据失败,抛出InsertException throw new InsertException(); } } /** * 执行密码加密 * * @param rawPassword 原密码 * @return 根据原密码执行加密得到的密文 */ private String encode(String rawPassword) { String encodePassword = passwordEncoder.encode(rawPassword); return encodePassword; } }
然后,调整控制器中处理请求的方法:
package cn.tedu.straw.portal.controller; import cn.tedu.straw.portal.model.User; import cn.tedu.straw.portal.service.IUserService; import cn.tedu.straw.portal.service.ex.ClassDisabledException; import cn.tedu.straw.portal.service.ex.InsertException; import cn.tedu.straw.portal.service.ex.InviteCodeException; import cn.tedu.straw.portal.service.ex.PhoneDuplicateException; import cn.tedu.straw.portal.vo.R; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * <p> * 前端控制器 * </p> * * @author tedu.cn * @since 2020-07-14 */ @RestController @RequestMapping("/portal/user") public class UserController { @Autowired private IUserService userService; // http://localhost:8080/portal/user/student/register?inviteCode=JSD2003-111111&nickname=Hello&phone=13800138002&password=1234 @RequestMapping("/student/register") public R studentRegister(User user, String inviteCode) { try { userService.registerStudent(user, inviteCode); return new R().setState(1).setMessage("注册成功!"); } catch (InviteCodeException e) { return new R().setState(2).setMessage("注册失败!邀请码错误!"); } catch (ClassDisabledException e) { return new R().setState(3).setMessage("注册失败!班级已经被禁用!"); } catch (PhoneDuplicateException e) { return new R().setState(4).setMessage("注册失败! 手机号码已经被注册!"); } catch (InsertException e) { return new R().setState(5).setMessage("注册失败!服务器忙,请稍后再次尝试!"); } } }
完成后,重启项目,打开浏览器,登录后,通过以上URL进行测试。