首先我们要先把项目的整体结构搭建起来,如下图
common包用来放公共类,config用来放置配置类(在瑞吉外卖项目-01配置前端资源映射器文章下有详细讲解)下面四个分别是控制层,实体类,dao层,业务层,各层中的代码如下
common(R.java为通用返回结果类,后端接受前端参数后进行处理,经处理好的结果封装到这个类里面,对于业务比较多的情况下,用此种方式比较方便)
@Data
public class R<T> {
private Integer code; //编码:1成功,0和其它数字为失败
private String msg; //错误信息
private T data; //数据
private Map map = new HashMap(); //动态数据
public static <T> R<T> success(T object) {
R<T> r = new R<T>();
r.data = object;
r.code = 1;
return r;
}
public static <T> R<T> error(String msg) {
R r = new R();
r.msg = msg;
r.code = 0;
return r;
}
public R<T> add(String key, Object value) {
this.map.put(key, value);
return this;
}
}
controller
因为前端登录请求的地址是×××/employee/login,所以在类和方法上都要写请求地址,在方法上应写@PostMapping与前端请求方式(post方法)对应,方法中传入HttpServletRequest,用来获取Session ,@requestbody注解用于接收json格式的字符串,因为前端传过来的是此种方式,所以要在此处写上此注解,
@Slf4j
@RequestMapping("/employee")
@RestController
public class Employeecontroller {
@Autowired
private Employeeservice employeeservice;
@PostMapping("/login")
public R<Employee> login(HttpServletRequest request, @RequestBody Employee employee){
//将页面提交的密码password进行md5加密处理
String password=employee.getPassword();
password= DigestUtils.md5DigestAsHex(password.getBytes());
//根据页面提交的用户名username查询数据库
LambdaQueryWrapper<Employee> queryWrapper=new LambdaQueryWrapper<>();
queryWrapper.eq(Employee::getUsername,employee.getUsername());
Employee emp=employeeservice.getOne(queryWrapper);
//如果没有查询到将返回查询失败结果
if (emp == null){
return R.error("登陆失败");
}
//密码比对,如果不一致将返回登陆失败结果
if (!emp.getPassword().equals(password)){
return R.error("登陆失败");
}
//查询员工状态,如果为已禁用状态,将返回员工已禁用结果
if (emp.getStatus()==0){
return R.error("账号已禁用");
}
//登陆成功,将员工id存入session并返回登陆成功结果
request.getSession().setAttribute("employee",emp.getId());
return R.success(emp);
}
}
entity
@Data
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String username;
private String name;
private String password;
private String phone;
private String sex;
private String idNumber;
private Integer status;
private LocalDateTime createTime;
private LocalDateTime updateTime;
@TableField(fill = FieldFill.INSERT)
private Long createUser;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateUser;
}
mapper(因为这里使用mybatis-plus,所以可以直接继承其提供的类,不需要再写其他的,比较方便)
@Mapper
public interface Employeemapper extends BaseMapper<Employee> {
}
service(因为这里使用mybatis-plus,所以可以直接继承其提供的类,不需要再写其他的,比较方便)
public interface Employeeservice extends IService<Employee> {
}
service实现类(因为这里使用mybatis-plus,所以可以直接继承其提供的类,不需要再写其他的,比较方便)
@Service
public class Employeeserviceimpl extends ServiceImpl<Employeemapper, Employee> implements Employeeservice {
}
项目结构搭建完成后,接下来我们进行登录业务的开发,这里我们把登录流程分成六个步骤,
1. 获取前端页面提交的密码,并将这个密码进行md5加密(提高安全性)
spring的工具类--DigestUtils集成了基本的加密算法,直接调用就行。
//将页面提交的密码password进行md5加密处理
String password=employee.getPassword();
password= DigestUtils.md5DigestAsHex(password.getBytes());
2. 根据前端页面提交的用户名username查询数据库
//根据页面提交的用户名username查询数据库
LambdaQueryWrapper<Employee> queryWrapper=new LambdaQueryWrapper<>();
queryWrapper.eq(Employee::getUsername,employee.getUsername());
Employee emp=employeeservice.getOne(queryWrapper);
LambdaQueryWrapper是mybatis-plus的一个工具类,他的一些常见功能如下图
我们此时调用的是他的eq方法,如图可知,eq即相当于等于,在此处用于判断在数据库中遍历出的用户名是否和前端页面用户输入的用户名相同,相同的话即代表数据库中有这个值,反之则无
getOne是mybatis-plus的一个方法,用来获取一条数据,如果取得多条数据会报错,要么换其他方法,要么只选择其中一条,在条件构造器Wrapper结尾加上.last(“limit 1”)即可只选一条
3. 对第二步从数据库中查询到的用户结果进行判断,并将结果返回到通用结果类
//如果没有查询到将返回查询失败结果
if (emp == null){
return R.error("登陆失败");
}
4. 将从前端页面获取的密码与数据库中的密码进行比对,并将结果返回到通用结果类
//密码比对,如果不一致将返回登陆失败结果
if (!emp.getPassword().equals(password)){
return R.error("登陆失败");
}
5. 判断员工状态,因为在前端做了js判断,当status为0的时候为禁用状态,此时将无法登录,为1 的时候状态正常,可以正常登录
//查询员工状态,如果为已禁用状态,将返回员工已禁用结果
if (emp.getStatus()==0){
return R.error("账号已禁用");
}
6. 上面几个if语句都是用来判断登陆失败的因素,如果都不满足,证明登陆条件都满足,此刻应成 功登录,为了记住用户信息,我们将把用户的id存入session中,到此,登录流程便完成了
//登陆成功,将员工id存入session并返回登陆成功结果
request.getSession().setAttribute("employee",emp.getId());
return R.success(emp);