当抽象方法已经设计好了,就应该在实现类中实现以上抽象方法:
@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进行测试。