从项目出发学习后端接口开发
第3天 实现注册、登录接口
前言
第2天我们已经连接了本地数据库,也模拟往数据库插入数据了,但插入的数据是在后端写死的,所以今天,我们将更真实地模拟前端发送数据到后端接口进行处理。
继续在第2天的项目基础上做延伸。
一、开发环境
数据库:8.0.18 MySQL Community Server - GPL
数据库管理工具:Navicat12.1.11(x64)
接口测试工具:Postman v9.14.7
没有安装的小伙伴自行去官网下载,也可以找我拿安装包
软件安装、破解及基本使用就不废话了,自己去百度
二、逻辑梳理
写代码前理清逻辑会使我们事半功倍,也能更好地去理解代码为什么这么写;
首先,我们明确目标:一个注册接口和一个登录接口;
1、注册
流程:前端通过接口发送用户信息(用户名、密码和手机号),后端收到信息后进行注册(也就是数据库插入新增用户信息);
**分析:**在后端收到数据后,首先是否应该对数据进行判空验证;不为空时,如果数据库已经有这个用户了呢?(前提是用户名在我们的规则里是唯一的,这里我们就规定用户名是唯一字段)只有当数据库不存在该用户时,才允许插入操作,接下来就是数据库插入操;所以,这样来看这个注册流程就很清晰了;
2、登录
流程:前端通过接口发送用户基本信息(用户名、密码),这里手机号就不需要了;后端收到信息后进行数据库查询,如果有就允许登录,其实登录在我们这只是一个逻辑登陆,没有实际操作;
分析:一样的,后端收到数据进行判空验证;当数据正常时,可以怎么查数据库呢?第一种,可以根据用户名查是否存在数据,如果存在则对比密码;第二种,则是直接根据两个条件:用户名、密码,对数据库查询;那么回到注册分析时,我们有一步是查该用户名是否存在于数据库;所以,我们不用再另写一条查询语句,直接通过第一种查询即可。
三、实体类entity修改
1、User类
字段不变,仍是用户名 userName、密码 password、手机号 phoneNumber,新增构造器;
package com.saxon.thirdday.entity;
public class User {
private String userName;
private String password;
private String phoneNumber;
public User(String userName, String password, String phoneNumber) {
this.userName = userName;
this.password = password;
this.phoneNumber = phoneNumber;
}
@Override
public String toString() {
return "User{" +
"userName='" + userName + '\'' +
", password='" + password + '\'' +
", phoneNumber='" + phoneNumber + '\'' +
'}';
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
2、Response类
接口回调类,新增字段 isOk(boolean),表示接口是否执行成功;以及构造器;
package com.saxon.thirdday.entity;
public class Response {
private boolean isOk;
private String msg;
private int code;
public Response(boolean isOk, String msg, int code) {
this.isOk = isOk;
this.msg = msg;
this.code = code;
}
public boolean getIsOk() {
return isOk;
}
public void setIsOk(boolean isOk) {
this.isOk = isOk;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
四、Service修改
1、UserService
新增查询方法,返回一个User集合(其实我们这里用User即可,因为我们规定数据库userName是唯一的,我们这里是功能性扩展预留);新增用户方法返回整形是为了通过返回值来告诉我们是否插入成功;当然我们需要通过接口来插入数据,就需要接收前端传的用户信息值;
package com.saxon.thirdday.service;
import com.saxon.thirdday.entity.User;
import java.util.List;
public interface UserService {
int createUser(String userName,String password,String phoneNumber);
List<User> queryByUserName(String userName);
}
2、UserServiceImpl
UserService的实现类,顾名思义实现Service的方法;
package com.saxon.thirdday.service.impl;
import com.saxon.thirdday.entity.User;
import com.saxon.thirdday.mapper.UserMapper;
import com.saxon.thirdday.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserMapper userMapper;
@Override
public List<User> queryByUserName(String userName) {
return userMapper.queryByUserName(userName);
}
@Override
public int createUser(String userName,String password,String phoneNumber) {
User user=new User(userName,password,phoneNumber);
return userMapper.createUser(user);
}
}
这里代码报错是正常的,因为我们还没有修改mapper,继续往下走;
五、Mapper修改
1、UserMapper
首先修改根路径下的UserMapper接口,新增 queryByUserName(String userName)方法;修改新增用户方法的方法类型为 int;
package com.saxon.thirdday.mapper;
import com.saxon.thirdday.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
@Mapper
public interface UserMapper {
int createUser(User user);
List<User>queryByUserName(String userName);
}
代码修改完,回到UserServiceImpl,发现报错消失;
2、UserMapper.xml
资源路径下的UserMapper.xml,这里主要新增数据库查询语句;
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.saxon.thirdday.mapper.UserMapper">
<resultMap id="BaseResultMap" type="com.saxon.thirdday.entity.User">
<result column="userName" jdbcType="VARCHAR" property="userName" />
<result column="password" jdbcType="VARCHAR" property="password" />
<result column="phoneNumber" jdbcType="VARCHAR" property="phoneNumber" />
</resultMap>
<insert id="createUser" parameterType="com.saxon.thirdday.entity.User">
INSERT INTO `user` VALUES(#{userName},#{password},#{phoneNumber})
</insert>
<select id="queryByUserName" resultType="com.saxon.thirdday.entity.User">
SELECT * FROM `user` WHERE username = #{userName}
</select >
</mapper>
六、UserController修改
修改接口请求方式及方法体;这里为什么修改请求方式,具体自己百度一下接口规则,不再细说了;
调用服务类的逻辑在第二点就分析的很清楚了;
package com.saxon.thirdday.controller;
import com.saxon.thirdday.entity.Response;
import com.saxon.thirdday.entity.User;
import com.saxon.thirdday.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
@RestController
public class UserController {
@Autowired
UserService userService;
@RequestMapping(value = "/login",method = RequestMethod.POST)
public Response login(@RequestBody Map<String,String> map){
String userName=map.get("userName");
String password=map.get("password");
if(userName != null && password != null ){ //不能为空
List<User> userList = userService.queryByUserName(userName);
if(userList!=null && userList.size()>0){ //判断是否存在
User user = userList.get(0);
if(password.equals(user.getPassword())){ //判断密码是否正确
return new Response(true,"登陆成功",1);
}else {
return new Response(false,"登陆失败,密码错误",-1);
}
}else {
return new Response(false,"登陆失败,用户不存在",-1);
}
}else {
return new Response(false,"登陆失败,请检查用户名、密码是否为空",-1);
}
}
@RequestMapping(value = "/register",method = RequestMethod.POST)
public Response register(@RequestBody Map<String,String> map){
String userName=map.get("userName");
String password=map.get("password");
String phoneNumber=map.get("phoneNumber");
if (userName!=null&&password!=null&&phoneNumber!=null){ //判断不能为空
List<User>userList=userService.queryByUserName(userName); //查询数据库当前用户是否存在
if (userList!=null&&userList.size()!=0){
return new Response(false,"注册失败,用户名重复",-1);
}else {
int count=userService.createUser(userName,password,phoneNumber);
if (count>0){
return new Response(true,"注册成功",1);
}else {
return new Response(false,"注册失败",-1);
}
}
}else{
return new Response(false,"注册失败,请检查用户名、密码、手机号是否为空",-1);
}
}
}
七、激动人心的接口验证
今天的验证方式不同以往,需要借助postman工具来检验;postman基本使用不做过多的介绍了,看不明白的自己百度一下吧,也不复杂;
1、首先运行idea服务;
2、配置postman参数,以注册接口示例,如下:
返回注册成功后,查看数据库,可以看到我们新增的用户;
3、登录接口验证
总结
相比较第2天,我们今天的实践可以说很接近实际项目中的开发了,不仅学习了接口发送数据也简单学习了 postman的使用;
总结一下容易出错的地方:
1、最容易错的地方,字段单词前后文不一致,往往一个大小写错误,需要查找好久;
2、方法名相应的需要保持统一,比如mapper的接口方法与marpper.xml中的数据库语句中的id要保持统一;
3、数据库配置、文件路径、导包路径等等;
总而言之,谨小慎微,不能马虎。