一、前言
新增了登录注册的功能,代码量可能会有点大,所有代码加起来差不多560行。这个项目对于小白来说肯定是一大难关了。文章中的每张图都是作者亲手绘制的,简单明了,如果大家认同作者,希望可以支持一下作者。全套源代码一直会保持公开状态,有需要的话可以自行cv。
java专栏(从0开始的java之旅)
二、效果展示
注册功能展示
登录功能展示
忘记密码功能展示
三、逻辑分析
1. 登录功能
2. 注册功能
3. 忘记密码功能
四、代码分析
1. 登录
循环尝试登录:
for (int i = 0; i < 3; i++) {// 代码内容
}
使用了一个循环,最多允许用户尝试三次登录(包括第三次)。
输入用户名:
System.out.println("请输入用户名");
String username = sc.next();
用户输入用户名,然后检查是否在已注册用户列表中。
检查用户名是否注册:
boolean flag = comtains(users, username);
if (!flag) {System.out.println("用户名" + username + "未注册,请先注册在登录");System.exit(0);
}
如果用户名不在用户列表中,则提示用户未注册并退出程序。可能的改进是提供注册选项或重新提示输入。
输入密码和验证码:
System.out.println("请输入密码");
String password = sc.next();
用户输入密码,并且每次登录尝试都需要输入验证码。
while (true) {String rightCode = GetCode();// 显示验证码并接受用户输入
}
这段代码通过 GetCode()
方法获取验证码,用户需要输入正确的验证码才能继续登录。验证码大小写不敏感。
验证用户名和密码:
User userInfo = new User(username, password, null, null);
boolean result = checkUserInfo(users, userInfo);
checkUserInfo()
方法用于检查输入的用户名和密码是否在用户列表中匹配。如果匹配,则登录成功;否则,根据尝试次数给出失败提示。
登录结果处理:
if (result) {System.out.println("登录成功");// 启动系统SyuSystem ss = new SyuSystem();ss.StartStuSystem();break;
} else {// 登录失败处理
}
如果登录成功,显示成功消息并启动系统;否则,根据尝试次数给出失败消息,并在达到最大尝试次数时锁定账号。
2. 注册
输入用户名:
while (true) {System.out.println("请输入用户名");username = sc.next();boolean flag1 = checkUsername(username);if (!flag1) {System.out.println("格式不满足条件,需要重新输入");} else {boolean flag2 = contains(users, username);if (!flag2) {System.out.println("用户名" + username + "可用");break;} else {System.out.println("用户名" + username + "已存在,请重新输入");}}
}
用户首先输入用户名,程序会检查其格式是否符合要求(checkUsername(username)
方法的具体实现未给出,但通常会检查长度、字符等)。
如果用户名格式不正确,要求用户重新输入。
如果用户名已经存在于用户列表中(使用 contains(users, username)
方法判断),则要求用户重新输入。
输入密码:
String password;
while (true) {System.out.println("请输入要注册的密码");password = sc.next();System.out.println("请再次输入密码");String password2 = sc.next();if (password.equals(password2)) {System.out.println("两次密码一致,继续输入其他数据");break;} else {System.out.println("两次密码不一致,请重新输入");}
}
用户输入密码,并要求再次确认密码。
如果两次输入的密码不一致,提示用户重新输入。
输入身份证号码和手机号码:
String personId;
while (true) {System.out.println("请输入身份证号");personId = sc.next();boolean flag = checkPersonId(personId);if (flag) {System.out.println("身份证号码满足需求");break;} else {System.out.println("身份证号码不满足需求,请重新输入");}
}String phoneNumber;
while (true) {System.out.println("请输入手机号码");phoneNumber = sc.next();boolean flag = checkPhoneNumber(phoneNumber);if (flag) {System.out.println("手机号格式正确");break;} else {System.out.println("手机号格式有误,请重新输入");}
}
用户依次输入身份证号码和手机号码。
每次输入后,程序会调用相应的验证方法(checkPersonId(personId)
和 checkPhoneNumber(phoneNumber)
)来验证格式的正确性。
如果格式不正确,提示用户重新输入。
创建用户对象并添加到列表:
User user = new User(username, password, personId, phoneNumber);
users.add(user);
用户成功输入所有信息后,将信息封装成 User
对象,并将其添加到 users
列表中。
遍历集合打印用户信息:
printList(users);
最后调用 printList(users)
方法遍历并打印注册的用户信息。
3. 忘记密码
输入用户名:
System.out.println("请输入用户名");
String username = sc.next();
boolean flag = contains(users, username);
if (!flag) {System.out.println("当前用户" + username + "未注册,请先注册");return;
}
用户输入用户名,并检查该用户名是否存在于用户列表中(使用 contains(users, username)
方法)。
如果用户名不存在,提示用户先注册并结束函数。
输入身份证号和手机号:
System.out.println("请输入身份证号码");
String personId = sc.next();
System.out.println("请输入手机号码");
String phoneNumber = sc.next();
用户输入身份证号码和手机号码。
验证身份信息:
int index = findIndex(users, username);
User user = users.get(index);
if (!(user.getPersonId().equalsIgnoreCase(personId) && user.getPhoneNumber().equals(phoneNumber))) {System.out.println("身份证号码或手机号码输入有误,不能修改密码");return;
}
根据用户名找到对应的用户对象。
验证输入的身份证号码和手机号码是否与用户信息匹配,如果不匹配则提示信息输入有误并结束函数。
更改密码:
String password;
while (true) {System.out.println("请输入新密码");password = sc.next();System.out.println("请再次输入密码");String newPassword = sc.next();if (password.equals(newPassword)) {System.out.println("两次密码输入一致");break;} else {System.out.println("两次密码不一致,请重新输入");continue;}
}
用户输入新的密码,并要求再次确认密码。
如果两次输入的密码不一致,提示用户重新输入。
修改密码:
user.setPassword(password);
System.out.println("密码修改成功");
将用户对象中的密码字段更新为新输入的密码。
提示用户密码修改成功。
4. 方法
查找用户信息下标
方法签名和参数:
private static int findIndex(ArrayList<User> users, String username)
findIndex
是一个静态方法,用于在给定的 ArrayList<User>
中查找指定用户名的用户。
users
是包含用户对象的列表。
username
是要查找的用户名。
循环遍历列表:
for (int i = 0; i < users.size(); i++) {if (users.get(i).getUserName().equals(username)) {return i;}
}
使用 for
循环遍历 users
列表,从索引 0
开始逐个查找。
对于每个用户对象,通过 getUserName()
方法获取用户名,并与输入的 username
进行比较。
如果找到匹配的用户名,返回当前索引 i
,即找到的用户在列表中的位置。
未找到用户情况:
return -1;
如果循环结束后仍未找到匹配的用户名,返回 -1
,表示未找到该用户。
检查用户名和密码是否正确
方法签名和参数:
private static boolean checkUserInfo(ArrayList<User> users, User userInfo)
checkUserInfo
是一个静态方法,用于检查用户信息是否匹配。
users
是包含用户对象的列表。
userInfo
是要验证的用户信息对象,其中包含用户名和密码。
循环遍历列表:
for (int i = 0; i < users.size(); i++) {if (users.get(i).getUserName().equals(userInfo.getUserName()) && users.get(i).getPassword().equals(userInfo.getPassword())) {return true;}
}
使用 for
循环遍历 users
列表,从索引 0
开始逐个检查每个用户对象。
对于每个用户对象,通过 getUserName()
方法获取用户名,并通过 getPassword()
方法获取密码。
如果当前用户对象的用户名和密码与 userInfo
中的用户名和密码完全匹配,则返回 true
,表示找到匹配的用户信息。
未找到匹配的情况:
return false;
如果循环结束后未找到任何匹配的用户名和密码组合,则返回 false
,表示未找到匹配的用户信息。
检查手机号码
长度检查:
if (phoneNumber.length() != 11) {return false;
}
首先检查手机号的长度是否为 11 位。如果不是,则返回 false
。在大多数国家,手机号通常是固定长度的,这里假设长度为 11 位。
开头检查:
if (phoneNumber.startsWith("0")) {return false;
}
接着检查手机号码是否以 "0" 开头。在某些国家和地区,手机号码不能以 "0" 开头,因此这里排除以 "0" 开头的情况。
数字检查:
for (int i = 0; i < phoneNumber.length(); i++) {if (phoneNumber.charAt(i) > '9' || phoneNumber.charAt(i) < '0') {return false;}
}
然后通过循环遍历每个字符,检查是否都是数字。这是通过比较字符的 ASCII 值来实现的。条件 phoneNumber.charAt(i) > '9' || phoneNumber.charAt(i) < '0'
检查字符是否不在 '0' 到 '9' 的范围内。如果发现非数字字符,立即返回 false
。
检查身份证号码
长度检查:
if (personId.length() != 18) {return false;
}
首先检查身份证号的长度是否为 18 位。在大多数国家和地区,身份证号通常是固定长度的,因此这里假设长度为 18 位。
开头检查:
boolean flag = personId.startsWith("0");
if (flag) {return false;
}
检查身份证号码是否以 "0" 开头。根据常见的身份证号规则,有些国家或地区的身份证号不应以 "0" 开头,因此这里排除以 "0" 开头的情况。
前17位检查:
for (int i = 0; i < personId.length() - 1; i++) {if (personId.charAt(i) < '0' || personId.charAt(i) > '9') {return false;}
}
遍历身份证号的前 17 位,确保它们都是数字字符 ('0' 到 '9')。如果发现非数字字符,立即返回 false
。
第18位检查:
char endChar = personId.charAt(personId.length() - 1);
if ((endChar >= '0' && endChar <= '9') || (endChar == 'x') || (endChar == 'X')) {return true;
} else {return false;
}
检查身份证号的第 18 位。它可以是数字字符 ('0' 到 '9'),或者是 'x' 或 'X'(用于表示身份证号的最后一位可能是大写字母 X)。
检查用户名
长度检查:
int len = username.length();
if (len > 15 || len < 2) {return false;
}
首先检查用户名的长度是否在 2 到 15 之间。这个范围内的长度通常被认为是合适的,太短可能不够描述,太长则可能过于复杂。
字符组成检查:
for (int i = 0; i < username.length(); i++) {char ch = username.charAt(i);if (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9'))) {return false;}
}
遍历用户名的每个字符,确保它们只包含字母(大小写)和数字。如果发现非这些字符,则返回 false
。
字母检查:
int countnum = 0;
for (int i = 0; i < username.length(); i++) {char ch = username.charAt(i);if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {countnum++;}
}
计算用户名中字母的个数。这段代码似乎是想确保用户名中至少包含一个字母,因为 countnum
变量只有在字符是字母时才增加。
生成一个验证码
创建字母集合:
ArrayList<Character> code = new ArrayList<>();
for (int i = 0; i < 26; i++) {code.add((char) ('a' + i)); // 添加小写字母code.add((char) ('A' + i)); // 添加大写字母
}
首先创建了一个包含所有小写和大写字母的集合 code
,即 [a-zA-Z]
。
随机生成四个字母:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 4; i++) {int index = r.nextInt(code.size());char ch = code.get(index);sb.append(ch);
}
使用 Random
类生成四个随机位置的字母,并将它们添加到 StringBuilder
sb
中。
生成一个随机数字:
int num = r.nextInt(10);
sb.append(num);
使用 Random
类生成一个 0
到 9
之间的随机数字,并将其追加到 sb
中。
调整数字位置:
char[] arr = sb.toString().toCharArray();
int index = r.nextInt(arr.length);
char ch = arr[index];
arr[index] = arr[arr.length - 1];
arr[arr.length - 1] = ch;
将生成的验证码转换为字符数组 arr
,然后随机选择一个位置将最后一个字符(即数字)与之交换,以增加验证码的随机性。
五、全套源代码
APP.java
package com.von.StudentSystem;import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;public class App {public static void main(String[] args) {ArrayList<User> users = new ArrayList<>();Scanner sc = new Scanner(System.in);while (true) {System.out.println("欢迎来到VON学生管理系统");System.out.println("请选择操作:1登录 2注册 3忘记密码 4退出");String choose = sc.next();switch (choose) {case "1" -> login(users);case "2" -> register(users);case "3" -> forget(users);case "4" -> {System.out.println("谢谢使用,再见");System.exit(0);}default -> System.out.println("没有这个选项");}}}//忘记密码private static void forget(ArrayList<User> users) {Scanner sc = new Scanner(System.in);System.out.println("请输入用户名");String username = sc.next();boolean flag = comtains(users, username);if (!flag) {System.out.println("当前用户" + username + "未注册,请先注册");return;}//输入身份证号和手机号System.out.println("请输入身份证号码");String perdonId = sc.next();System.out.println("请输入手机号码");String phoneNumber = sc.next();//比较身份证号,和手机号是否一样int index = findIndex(users, username);User user = users.get(index);if (!(user.getPersonId().equalsIgnoreCase(perdonId) && user.getPhoneNumber().equals(phoneNumber))) {System.out.println("身份证号码或手机号码输入有误,不能修改密码");return;}//更改密码String password;while (true) {System.out.println("请输入新密码");password = sc.next();System.out.println("请再次输入密码");String newPassword = sc.next();if (password.equals(newPassword)) {System.out.println("两次密码输入一致");break;} else {System.out.println("两次密码不一致,请重新输入");continue;}}//修改密码user.setPassword(password);System.out.println("密码修改成功");}//查找用户下标private static int findIndex(ArrayList<User> users, String username) {for (int i = 0; i < users.size(); i++) {if (users.get(i).getUserName().equals(username)) {return i;}}return -1;}//登录private static void login(ArrayList<User> users) {Scanner sc = new Scanner(System.in);for (int i = 0; i < 3; i++) {System.out.println("请输入用户名");String username = sc.next();boolean flag = comtains(users, username);if (!flag) {System.out.println("用户名" + username + "未注册,请先注册在登录");System.exit(0);}System.out.println("请输入密码");String password = sc.next();while (true) {String rightCode = GetCode();System.out.println("当前验证码为:" + rightCode);System.out.println("请输入验证码");String code = sc.next();if (code.equalsIgnoreCase(rightCode)) {System.out.println("验证码正确");break;} else {System.out.println("验证码错误,请重新输入");continue;}}//检查用户名和密码是否正确User userInfo = new User(username, password, null, null);boolean result = checkUserInfo(users, userInfo);if (result) {System.out.println("登录成功");SyuSystem ss = new SyuSystem();ss.StartStuSystem();break;} else {System.out.println("登录失败,用户名或密码错误");if (i == 2) {System.out.println("当前账号" + username + "被锁定");return;} else {System.out.println("用户名或密码错误,还剩下" + i + "次机会");}}}}//检查用户名和密码是否正确private static boolean checkUserInfo(ArrayList<User> users, User userInfo) {for (int i = 0; i < users.size(); i++) {if (users.get(i).getUserName().equals(userInfo.getUserName()) && users.get(i).getPassword().equals(userInfo.getPassword())) {return true;}}return false;}//注册private static void register(ArrayList<User> users) {//1.输入用户名Scanner sc = new Scanner(System.in);String username;while (true) {System.out.println("请输入用户名");username = sc.next();boolean flag1 = checkUsername(username);if (!flag1) {System.out.println("格式不满足条件,需要重新输入");} else {//检测用户名是否唯一boolean flag2 = comtains(users, username);if (!flag2) {System.out.println("用户名" + username + "可用");break;} else {System.out.println("用户名" + username + "已存在,请重新输入");}}}//2.输入密码String password;while (true) {System.out.println("请输入要注册的密码");password = sc.next();System.out.println("请再次输入密码");String password2 = sc.next();if (password.equals(password2)) {System.out.println("两次密码一致,继续输入其他数据");break;} else {System.out.println("两次密码不一致,请重新输入");continue;}}//3.输入身份证号码String personId;while (true) {System.out.println("请输入身份证号");personId = sc.next();boolean flag = checkPersonId(personId);if (flag) {System.out.println("身份证号码满足需求");break;} else {System.out.println("身份证号码不满足需求,请重新输入");continue;}}//4.输入手机号码String phoneNumber;while (true) {System.out.println("请输入手机号码");phoneNumber = sc.next();boolean flag = checkPhoneNumber(phoneNumber);if (flag) {System.out.println("手机号格式正确");break;} else {System.out.println("手机号格式有误,请重新输入");continue;}}//5.用户名、密码、身份证号、手机号放到用户中User user = new User(username, password, personId, phoneNumber);users.add(user);//6.遍历集合printList(users);}//遍历集合private static void printList(ArrayList<User> users) {for (int i = 0; i < users.size(); i++) {User user = users.get(i);System.out.println(user.toString());}}//检查手机号码private static boolean checkPhoneNumber(String phoneNumber) {//长度为11位if (phoneNumber.length() != 11) {return false;}//不能0开头if (phoneNumber.startsWith("0")) {return false;}//必须都是数字for (int i = 0; i < phoneNumber.length(); i++) {if (phoneNumber.charAt(i) > '9' && phoneNumber.charAt(i) < '0') {return false;}}return true;}//检查身份证号private static boolean checkPersonId(String personId) {//身份证号长度if (personId.length() != 18) {return false;}//检查开头数据boolean flag = personId.startsWith("0");if (flag) {return false;}//判断前17位for (int i = 0; i < personId.length() - 1; i++) {if (personId.charAt(i) < '0' || personId.charAt(i) > '9') {return false;}}//判断第18位char endChar = personId.charAt(personId.length() - 1);if ((endChar >= '0' && endChar <= '9') || (endChar == 'x') || (endChar == 'X')) {return true;} else {return false;}}//检查用户是否在集合中private static boolean comtains(ArrayList<User> users, String username) {for (int i = 0; i < users.size(); i++) {if (users.get(i).getUserName().equals(username)) {return true;}}return false;}//检查用户名private static boolean checkUsername(String username) {//用户长度必须在3-15位之间int len = username.length();if (len > 15 || len < 2) {return false;}//只能是字母加数字,不能是纯数字for (int i = 0; i < username.length(); i++) {char ch = username.charAt(i);if (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9'))) {return false;}}//记录字母的个数int countnum = 0;for (int i = 0; i < username.length(); i++) {char ch = username.charAt(i);if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {countnum++;}}return countnum > 0;}//生成一个验证码private static String GetCode() {//创建一个集合存放字母ArrayList<Character> code = new ArrayList<>();for (int i = 0; i < 26; i++) {code.add((char) ('a' + i));code.add((char) ('A' + i));}//随机生成四个字母Random r = new Random();StringBuilder sb = new StringBuilder();for (int i = 0; i < 4; i++) {int index = r.nextInt(code.size());char ch = code.get(index);sb.append(ch);}//生成一个随机数字int num = r.nextInt(10);sb.append(num);//调整数字的位置char[] arr = sb.toString().toCharArray();int index = r.nextInt(arr.length);char ch = arr[index];arr[index] = arr[arr.length - 1];arr[arr.length - 1] = ch;return new String(arr);}
}
Student.java
package com.von.StudentSystem;public class Student {private String id;private String name;private int age;private String gender;private String address;public Student() {}public Student(String id, String name, int age, String gender, String address) {this.id = id;this.name = name;this.age = age;this.gender = gender;this.address = address;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}
}
SyuSystem.java
package com.von.StudentSystem;import java.util.ArrayList;
import java.util.Scanner;public class SyuSystem {public static void StartStuSystem() {ArrayList<Student> students = new ArrayList<Student>();//菜单loop: while(true) {System.out.println("===================欢迎来到VON学生管理系统===================");System.out.println("====================1:添加学生============================");System.out.println("====================2:删除学生============================");System.out.println("====================3:修改学生============================");System.out.println("====================4:查找学生============================");System.out.println("====================5:退出系统============================");System.out.println("请输入您的选择");Scanner sc = new Scanner(System.in);String choose = sc.nextLine();switch (choose) {case "1" -> addStudent(students);case "2" -> delStudent(students);case "3" -> changeStudent(students);case "4" -> findStudent(students);case "5" -> {System.out.println("系统退出成功。欢迎再次使用");break loop;}default -> System.out.println("没有该选项");}}}//1.添加学生public static void addStudent(ArrayList<Student> students) {Student student = new Student();Scanner sc = new Scanner(System.in);while(true) {System.out.println("请输入学生ID");String id = sc.next();boolean flag = contains(students, id);if(flag) {//已经存在System.out.println("id已经存在请重新录入");}else {//不存在student.setId(id);System.out.println("请输入学生的姓名");String name = sc.next();student.setName(name);System.out.println("请输入学生年龄");int age = sc.nextInt();student.setAge(age);System.out.println("请输入学生性别");String gender = sc.next();student.setGender(gender);System.out.println("请输入学生家庭住址");String address = sc.next();student.setAddress(address);students.add(student);System.out.println("学生信息添加成功");break;}}}//2.删除学生public static void delStudent(ArrayList<Student> students) {System.out.println("请输入你要删除学生的id");Scanner sc = new Scanner(System.in);String id = sc.next();boolean flag = contains(students, id);if(flag) {//id存在for (int i = 0; i < students.size(); i++) {if(students.get(i).getId().equals(id)) {students.remove(i);System.out.println("id为"+id+"的学生删除成功");break;}}}else{//id不存在System.out.println("id不存在,删除失败");}}//3.修改学生public static void changeStudent(ArrayList<Student> students) {System.out.println("请输入要修改学生的id");Scanner sc = new Scanner(System.in);String id = sc.next();boolean flag = contains(students, id);if(flag) {//id存在for (int i = 0; i < students.size(); i++) {if(students.get(i).getId().equals(id)) {System.out.println("请输入要修改的学生姓名");students.get(i).setName(sc.next());System.out.println("请输入要修改的学生年龄");students.get(i).setAge(sc.nextInt());System.out.println("请输入要修改的学生性别");students.get(i).setGender(sc.next());System.out.println("请输入要修改的学生地址");students.get(i).setAddress(sc.next());break;}}}else{//id不存在System.out.println("要修改的id"+id+"不存在,请重新输入");}}//4.查询学生public static void findStudent(ArrayList<Student> students) {if(students.size() == 0) {System.out.println("当前没有任何学生信息,请添加后再查询");return;}System.out.println("id\t\t"+"姓名\t\t"+"年龄\t\t"+"性别\t\t"+"家庭住址");for (int i = 0; i < students.size(); i++) {Student stu = students.get(i);System.out.println(stu.getId()+"\t\t"+stu.getName()+"\t\t"+stu.getAge()+"\t\t"+stu.getGender()+"\t\t"+stu.getAddress());}}//5.判断id是否在集合中存在public static boolean contains(ArrayList<Student> students, String id) {for (int i = 0; i < students.size(); i++) {if(students.get(i).getId().equals(id)) {return true;}}return false;}
}
User.java
package com.von.StudentSystem;public class User {private String userName;private String password;private String personId;private String phoneNumber;public User() {}public User(String userName, String password, String personId, String phoneNumber) {this.userName = userName;this.password = password;this.personId = personId;this.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 getPersonId() {return personId;}public void setPersonId(String personId) {this.personId = personId;}public String getPhoneNumber() {return phoneNumber;}public void setPhoneNumber(String phoneNumber) {this.phoneNumber = phoneNumber;}@Overridepublic String toString() {return "User{" +"userName='" + userName + '\'' +", password='" + password + '\'' +", personId='" + personId + '\'' +", phoneNumber='" + phoneNumber + '\'' +'}';}
}