Java综合案例 #采取控制台方式书写简单学生管理系统(含注册登录功能)---案例分析与编码全流程详细讲解(内含详细注释)

目录


前言        

该项目涉及的知识点

项目准备 

JDK

编程工具Idea 

需求文档-升级部分(参考黑马程序员)

学生管理系统升级版

需求

分析

登录界面

用户类

注册功能

登录功能

忘记密码

验证码规则

需求分析 

编码

新建项目-StudentManagement

Student类

User类 

核心方法类SystemCore的实现 

StudentManagementPro-系统的整合以及登录模块的实现(升级点)

主要框架(main方法)

 注册方法

判断用户名的合法性

密码输入

判断身份证号的合法性

判断电话号码的合法性 

注册方法整体实现

 登录方法

生成随机验证码

判断用户名和密码是否匹配

登录方法整体实现 

忘记密码方法 

判断用户名、身份证号和手机号码是否匹配

忘记密码方法整体实现

StudentManagementPro的全部代码

结语

前言        


  • 为了巩固目前掌握的知识,我从黑马程序员经典的基础练习题中选出了【创建一个简单的学生管理系统(升级版)】来进行练习和讲解。
  • 在简单学生管理系统的基础上,新系统增加了用户的注册和登录功能。这个项目的实现涉及以往学习的绝大部分内容(近乎所有),能极大促进我们的代码书写能力和编程逻辑能力,让我们对Java语言有更进一步的认知。
  • 本文代码内含丰富全面的注释,可以仔细阅读与琢磨。
  • 本文的源代码以及需求文档会上传至平台,可以到文章顶部找资料压缩包。

该项目涉及的知识点

知识点清单
Java基础语法(输入输出与随机数等),JVM运行原理,JDK,Idea工具的使用
关键字、变量、数据类型(基本数据类型、引用数据类型)
运算符和表达式
流程控制语句(for、while、switch、if)
数组以及数组算法
方法的构造
面向对象编程(类和对象),封装思想
String字符串类型(工具:StringBuilder)
集合ArrayList

项目准备 


  • JDK                        (本文采用JDK17)
  • 编程工具Idea         (本文采用Idea2023.3.7版本)
  • 需求文档                (下文)

JDK

        参考下文,我在前面的文章里面做了详细的操作(本文采用JDK17)JDK下载与安装icon-default.png?t=O83Ahttps://blog.csdn.net/q251932440/article/details/141369145?spm=1001.2014.3001.5502

编程工具Idea 

        移步官网下载,网址:IntelliJ IDEA – the Leading Java and Kotlin IDEIntelliJ IDEA is undoubtedly the top-choice IDE for software developers. It makes Java and Kotlin development a more productive and enjoyable experience.icon-default.png?t=O83Ahttps://www.jetbrains.com/idea/

        (本文采用Idea2023.3.7版本)

需求文档-升级部分(参考黑马程序员)

        升级前需求文档参考上一篇文章

学生管理系统书写icon-default.png?t=O83Ahttps://blog.csdn.net/q251932440/article/details/142070845?spm=1001.2014.3001.5501

学生管理系统升级版

需求
  • 为学生管理系统书写一个登陆、注册、忘记密码的功能。
  • 只有用户登录成功之后,才能进入到学生管理系统中进行增删改查操作。
分析
登录界面
System.out.println("欢迎来到学生管理系统");
System.out.println("请选择操作1登录 2注册 3忘记密码");
用户类

属性:用户名、密码、身份证号码、手机号码

注册功能
  • 用户名需要满足以下要求:
  • 验证要求:
    • 用户名唯一
    • 用户名长度必须在3~15位之间
    • 只能是字母加数字的组合,但是不能是纯数字
  • 密码键盘输入两次,两次一致才可以进行注册。
  • 身份证号码需要验证。
  • 验证要求:
    • 长度为18位
    • 不能以0为开头
    • 前17位,必须都是数字
    • 最为一位可以是数字,也可以是大写X或小写x
  • 手机号验证。
  • 验证要求:
    • 长度为11位
    • 不能以0为开头
    • 必须都是数字
登录功能
  • 键盘录入用户名
  • 键盘录入密码
  • 键盘录入验证码
  • 验证要求:
    • 用户名如果未注册,直接结束方法,并提示:用户名未注册,请先注册
    • 判断验证码是否正确,如不正确,重新输入
    • 再判断用户名和密码是否正确,有3次机会
忘记密码
  • 键盘录入用户名,判断当前用户名是否存在,如不存在,直接结束方法,并提示:未注册
  • 键盘录入身份证号码和手机号码
  • 判断当前用户的身份证号码和手机号码是否一致:
    • 如果一致,则提示输入密码,进行修改。
    • 如果不一致,则提示:账号信息不匹配,修改失败。
验证码规则
  • 长度为5
  • 由4位大写或者小写字母和1位数字组成,同一个字母可重复
  • 数字可以出现在任意位置
  • 比如:aQa1K

需求分析 


        参照上述需求文档,绘制一份需求分析,这是一个非常重要的环节。以下是本人绘制的需求分析图,把学生管理系统的登录模块分成了登陆方法注册方法以及忘记密码方法三个核心部分。在系统内,分成了增、删、改、查四个核心部分   

编码


新建项目-StudentManagement

  • 打开idea,新建一个java项目StudentManagement,并在项目内创建如下结构
    • Student类
    • User类
    • SystemCore:实现系统增删改查的核心功能
    • StudentManagementPro:系统的整合以及登录模块的实现

Student类

  • 创建学生类描述学生属性
    • id
    • 姓名
    • 年龄
    • 家庭住址
  • 实现代码:
    public class Student {
        private String id;
        private String name;
        private int age;
        private String address;
    
        //全参构造
        public Student(String id, String name, int age, String address) {
            this.id = id;
            this.name = name;
            this.age = age;
            this.address = address;
        }
        //无参构造
        public Student() {
        }
    
        //getter and setter
        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 getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    }

User类 

  • 创建用户类描述用户属性
    • 用户名
    • 密码
    • 身份证号码
    • 手机号码
  • 实现代码:
    public class User {
        //定义成员变量
        private String username;
        private String password;
        private String personId;
        private String phone;
    
        public User() {
        }
    
        //全参构造
        public User(String username, String password, String personId, String phone) {
            this.username = username;
            this.password = password;
            this.personId = personId;
            this.phone = phone;
        }
    
        //无参构造
        public String getUsername() {
            return username;
        }
    
        //getter and setter
        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 getPhone() {
            return phone;
        }
    
        public void setPhone(String phone) {
            this.phone = phone;
        }
    }

核心方法类SystemCore的实现 

  • 实现系统增删改查的核心功能

    该类的实现在前文有详细描述,可以参考如下链接:学生管理系统书写icon-default.png?t=O83Ahttps://blog.csdn.net/q251932440/article/details/142070845?spm=1001.2014.3001.5501

     需要注意的是:前文为了测试核心功能,将此类写了main方法,在升级的版本中,我们只把其作为一个核心方法类,所以我们将main方法改为  startSystem()

  • 实现代码:
    import java.util.ArrayList;
    import java.util.Scanner;
    
    public class SystemCore {
        public static void startSystem() {
            //创建一个集合放置Student类型的数据
            ArrayList<Student> list = new ArrayList<>();
    
            //创建Scanner类,为下方选择流程的输入操作服务
            Scanner sc = new Scanner(System.in);
    
            //循环操作
            while (true){
                System.out.println("-------欢迎进入Joe学生管理系统-------");
                System.out.println("1:添加学生信息");
                System.out.println("2:删除学生信息");
                System.out.println("3:修改学生信息");
                System.out.println("4:查询所有学生信息");
                System.out.println("5:退出");
                System.out.println("请输入您的选择:");
                //输入选择
                String chose = sc.next();
    
                //选择流程(->格式自带break;)
                switch (chose){
                    case "1" -> addStudent(list);       //添加学生信息
                    case "2" -> deleteStudent(list);    //删除学生信息
                    case "3" -> updateStudent(list);    //修改学生信息
                    case "4" -> selectStudent(list);    //查询所有学生信息
                    case "5" -> {                       //退出系统
                        System.out.println("##### 退出 #####");
                        System.exit(0);
                    }
                    default -> System.out.println("没有这个选项!");
                }
            }
        }
    
    
        //添加方法:对键盘录入的学生信息进行添加,要求id唯一
        //需求:list
        //返回?void
        public static void addStudent(ArrayList<Student> list){
            //打印提示信息
            System.out.println("##### 添加学生信息 #####");
    
            //创建Scanner类键入学生信息
            Scanner sc = new Scanner(System.in);
    
            //判断唯一性:如果id已经存在则需要重新输入一个新的id
            //循环直到输入一个在集合中不存在的id
            String id = null; //在循环外创建String,不然循环结束后,在循环中创建的String字符串会消失!!!
            while (true){
                //输入id
                System.out.println("输入id:");
                id = sc.next();
                //判断id唯一性
                int judgment = judgment(list,id);
                //judgment < 0代表不存在相同的id,退出循环,执行添加操作
                if (judgment < 0){
                    break;
                }else {
                    //id已经存在,继续输入
                    System.out.println("id重复,请重新输入!");
                }
            }
            //输入姓名
            System.out.println("输入姓名:");
            String name = sc.next();
            //输入年龄
            System.out.println("输入年龄:");
            int age = sc.nextInt();
            //输入地址
            System.out.println("输入地址:");
            String address = sc.next();
    
            //创建一个学生对象stu,将属性值放进对象中
            Student stu = new Student(id,name,age,address);
    
            //再将Student类的stu对象存放进list(集合)当中
            list.add(stu);
    
            //提示插入成功
            System.out.println("+++++添加成功+++++");
        }
    
    
        //删除输入id对应的学生信息
        //需求:list
        //返回?void
        public static void deleteStudent(ArrayList<Student> list){
            //打印提示信息
            System.out.println("##### 删除学生信息 #####");
    
            //获取要删除的学生id
            Scanner sc = new Scanner(System.in);
            System.out.println("输入要删除的学生id:");
            String sid = sc.next();
    
            //判断id是否存在
            int index = judgment(list, sid);
            if (index < 0){
                //id不存在,不能删除对应id的学生信息
                System.out.println("id不存在,删除失败");
            }else {
                //id存在,删除
                list.remove(index);
                System.out.println("-----删除成功-----");
            }
        }
    
    
        //修改输入id对应的学生信息
        //需求:list
        //返回?void
        public static void updateStudent(ArrayList<Student> list){
            //打印提示信息
            System.out.println("##### 修改学生信息 #####");
    
            //获取要修改的学生id
            Scanner sc = new Scanner(System.in);
            System.out.println("输入要修改的学生id:");
            String sid = sc.next();
    
            //判断id是否存在
            int index = judgment(list, sid);
            if (index < 0){
                //id不存在,不能修改对应id的学生信息
                System.out.println("id不存在,修改失败");
            }else {
                //id存在,修改
                //创建学生类
                Student stu = list.get(index);//list.get(index)的地址值给了stu,
                                              //所以stu用setter方法更改属性值后存放在地址中后
                                              //集合中遍历学生信息找到这个地址打印出来的就是修改后的属性值
    
                //输入要修改的属性值
                System.out.println("输入姓名:");
                String name = sc.next();
                stu.setName(name);
                System.out.println("输入年龄:");
                int age = sc.nextInt();
                stu.setAge(age);
                System.out.println("输入地址:");
                String address = sc.next();
                stu.setAddress(address);
    
                //提示信息
                System.out.println("uuuuu 修改成功 uuuuu");
            }
        }
    
    
        //查询打印所有学生信息
        //需求:list
        //返回?void
        public static void selectStudent(ArrayList<Student> list){
            //打印提示信息
            System.out.println("##### 查询所有学生信息 #####");
    
            //如果没有学生信息则提示:当前无学生信息,请添加后再查询
            if (list.size() == 0){
                System.out.println("当前无学生信息,请添加后再查询!");
                return;//如果没有学生信息就退出方法
            }
    
            //打印表头
            System.out.println("id\t姓名\t年龄\t家庭住址");
            //如果有学生信息则打印
            for (int i = 0; i < list.size(); i++) {
                Student stu = list.get(i);
                System.out.println(stu.getId()+'\t'+stu.getName()+'\t'+stu.getAge()+'\t'+stu.getAddress());
            }
        }
    
    
        /*注意list.size()一开始就为0(因为集合里面没有元素),不会执行循环,会直接返回-1*/
        //判断id是否已经存在
        //需求:id值,list
        //返回?如果id存在则返回id所在的索引值,如果不存在则返回-1
        public static int judgment(ArrayList<Student> list, String id){
            //遍历集合寻找是否存在相同的id
            for (int i = 0; i < list.size(); i++) {
                Student stu = list.get(i);
                String judgmentId = stu.getId();
                if (judgmentId.equals(id)){
                    //如果id存在则返回id所在的索引值
                    return i;
                }
            }
            //如果不存在则返回-1
            return -1;
        }
    }

StudentManagementPro-系统的整合以及登录模块的实现(升级点)

主要框架(main方法)

  • 根据需求分析,设计出系统的一个主体框架
  • 并创建一个ArrayList集合容器以存放User对象
  • 实现代码:
    public static void main(String[] args) {
            //新建一个集合以存放User对象
            ArrayList<User> list = new ArrayList<>();
            //新建一个Scanner类,接收选择信息
            Scanner sc = new Scanner(System.in);
    
            while (true) {
                //打印提示信息
                System.out.println("----欢迎来到学生管理系统Pro----");
                System.out.println("1.登录");
                System.out.println("2.注册");
                System.out.println("3.忘记密码");
                System.out.println("4.退出");
                System.out.println("--> 请选择您的操作:");
    
                //接收输入的信息
                String chose = sc.next();
    
                //选择流程
                switch (chose){
                    case "1" -> stuLogin(list);                 //登录系统
                    case "2" -> stuRegister(list);              //用户注册
                    case "3" -> stuForgetPassword(list);        //忘记密码操作
                    case "4" -> {                               //退出系统
                        System.out.println("---退出系统---");
                        System.exit(0);
                    }
                    default -> System.out.println("###-没有该选项-###");
                }
            }
        }

    按照需求分析,我们将新增的登录注册功能按实现顺序分为3个核心方法:

  • 注册方法
  • 登录方法
  • 忘记密码方法

    实际上,在我们登录方法中有一个明显需要一个配合登录方法实现的创建随机验证码方法,同时经过总体分析,我们还需要一个验证用户是否存在的方法。这是初步分析的结果,可能后续还需要按照开发需求添加其他方法,初步分析完成后即可开始编码。

 注册方法

  • 需求文档对应需求:

注册功能

  • 用户名需要满足以下要求:
  • 验证要求:
    • 用户名唯一
    • 用户名长度必须在3~15位之间
    • 只能是字母加数字的组合,但是不能是纯数字
  • 密码键盘输入两次,两次一致才可以进行注册。
  • 身份证号码需要验证。
  • 验证要求:
    • 长度为18位
    • 不能以0为开头
    • 前17位,必须都是数字
    • 最为一位可以是数字,也可以是大写X或小写x
  • 手机号验证。
  • 验证要求:
    • 长度为11位
    • 不能以0为开头
    • 必须都是数字
判断用户名的合法性
  • 按照需求内容,我们首先要请求用户输入一个用户名,然后判断用户名的合法性 
    • 而判断其合法性我们可以先新建一个判断方法usernameJudgment,返回一个boolean值
      • 合法返回true
      • 不合法返回false

  该判断方法代码如下:

//用户名合法性验证----
    private static boolean usernameJudgment(ArrayList<User> list, String username) {
        //用户名长度必须在3-15之间
        //用一个变量接受字符串长度,不用调用两次length(),效率更高
        int length = username.length();
        if (!(length >= 3 && length <= 15)){
            //如果长度不在这个范围,返回false
            System.out.println("请重新输入一个3-15位的用户名!");
            return false;
        }
        //只能是数字加字母的组合
        //遍历的到字符串中的每一个字符
        for (int i = 0; i < username.length(); i++) {
            char c = username.charAt(i);
            if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))){
                //如果不是数字加字母的组合,返回false
                System.out.println("用户名只能是字母加数字的组合,请重新输入!");
                return false;
            }
        }
        //不能是纯数字
        //遍历user中的每一个字符,计算字母的数量
        int count = 0;
        for (int i = 0; i < username.length(); i++) {
            char c = username.charAt(i);
            if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')){
                count++;
                break;//如果有一个字母,直接退出循环,提高效率
            }
        }
        //通过count判断用户名是不是纯数字
        if (count == 0){
            System.out.println("用户名不能为纯数字组合,请重新输入!");
            return false;
        }
        //判断用户名的唯一性
        int index = getIndex(list,username);
        if (index >= 0){
            System.out.println("该用户已存在,请重新输入!");
            return false;
        }else {
            return true;
        }
    }
  • 我们注意到,在用户名合法性判断方法usernameJudgment中,需要嵌套一个getIndex方法来判断用户是否存在以验证用户名的唯一性
  • 接下来我们创建一个getIndex方法
    • 用户存在返回其对应集合的索引值
    • 不存在则返回-1
  • 实现代码:
    //判断用户名的唯一性,并获取存在用户的索引值---+
        private static int getIndex(ArrayList<User> list,String username) {
            //遍历集合
            for (int i = 0; i < list.size(); i++) {
                User u = list.get(i);
                if (u.getUsername().equals(username)){
                    //如果存在该用户名,返回索引
                    return i;
                }
            }
            //不存在该用户
            return -1;
        }
密码输入
  • 实现代码:
    String password2;
            while (true) {
                //输入两次密码,对两次密码进行比对
                System.out.println("请输入您的密码:");
                String password1 = sc.next();
                System.out.println("请再次输入您的密码:");
                password2 = sc.next();
                if (password1.equals(password2)){
                    //相同则退出循环进入下一步
                    break;
                }else {
                    System.out.println("两次密码不一致,请重新输入!");
                }
            }
判断身份证号的合法性
  • 完成对用户名的合法性判断后,我们继续输入身份证号,并对身份证号的合法性进行判断
  • 新建一个personIdJudgment方法,返回一个boolean值:
    • 合法返回true
    • 不合法返回false

  该判断方法代码如下:

//身份证号合法性验证----
    private static boolean personIdJudgment(String personId) {
        //长度为18
        if (personId.length() != 18){
            System.out.println("身份证号的长度必须为18位,请重新输入!");
            return false;
        }
        //不能以'0'开头
        if (personId.startsWith("0")){
            System.out.println("身份证号不能以‘0’为开头,请重新输入!");
            return false;
        }
        //前面17位必须是数字
        for (int i = 0; i < personId.length() - 1; i++) {
            char c = personId.charAt(i);
            if (!(c >= '0' && c <= '9')){
                System.out.println("身份证号前面17位必须是数字,请重新输入!");
                return false;
            }
        }
        //最后一位可以是数字或者大小写X
        char c2 = personId.charAt(personId.length()-1);
        if ((c2 >= '0' && c2 <= '9') || c2 == 'X' || c2 == 'x'){
            return true;
        }else {
            System.out.println("身份证号最后一位必须是数字或者大小写X,请重新输入!");
            return false;
        }
    }

startsWith("F"),F为新字符串的首字符,用来判断原字符串的首字符

判断电话号码的合法性 
  • 新建一个phoneJudgment方法,返回一个boolean值:
    • 合法返回true
    • 不合法返回false

该判断方法代码如下:

//手机号码合法性验证----
    private static boolean phoneJudgment(String phone) {
        //长度为11
        if (phone.length() != 11){
            System.out.println("手机号的长度必须为11位,请重新输入!");
            return false;
        }
        //不能以'0'开头-----拓展(字符转字符串):String Str = Character.toString('c');
        if (phone.startsWith("0")){
            System.out.println("手机号不能以‘0’为开头,请重新输入!");
            return false;
        }
        //必须都是数字
        for (int i = 0; i < phone.length(); i++) {
            char c = phone.charAt(i);
            if (!(c >= '0' && c <= '9')){
                System.out.println("手机号必须是纯数字组合,请重新输入!");
                return false;
            }
        }
        return true;
    }
注册方法整体实现
  • 对上述四个方法进行循环,让用户在输入错误信息后重新输入(注意把后面要用到的变量抽取到循环外面,不然循环结束后变量就会消失
  • 最后新建一个User对象,把用户输入的信息封装在对象中
  • 把对象存放在list集合容器内

注册方法整体实现代码如下:

//用户注册方法(优先实现,先注册才能验证其他功能)
    private static void stuRegister(ArrayList<User> list) {
        //提示信息
        System.out.println("----开始注册----");
        //新建一个Scanner类,获取用户名
        Scanner sc = new Scanner(System.in);

        String username;//将变量提取在循环外定义,以便后续能够使用
        while (true) {
            //获取用户名
            System.out.println("请输入一个新的用户名:");
            username = sc.next();
            //新建一个方法判断用户名的合法性,如果合法:true;如果不合法:false;
            boolean b = usernameJudgment(list,username);
            if (b){
                //如果合法,跳出循环,进入下一步
                //如果用户名不符合要求,则进入下一次循环重新输入
                break;
            }
        }

        String password2;
        while (true) {
            //输入两次密码,对两次密码进行比对
            System.out.println("请输入您的密码:");
            String password1 = sc.next();
            System.out.println("请再次输入您的密码:");
            password2 = sc.next();
            if (password1.equals(password2)){
                //相同则退出循环进入下一步
                break;
            }else {
                System.out.println("两次密码不一致,请重新输入!");
            }
        }

        String personId;
        while (true) {
            //输入身份证号
            System.out.println("请输入您的身份证号:");
            personId = sc.next();
            //定义方法对身份证号合法性进行验证,如果合法:true;如果不合法:false;
            boolean b = personIdJudgment(personId);
            if (b){
                //如果验证结果为true,则退出循环,进入下一步
                break;
            }
        }

        String phone;
        while (true) {
            //输入手机号
            System.out.println("请输入您的手机号码:");
            phone = sc.next();
            //判断手机号的合法性,如果合法:true;如果不合法:false;
            boolean b = phoneJudgment(phone);
            if (b){
                //如果验证结果为true,则退出循环,进入下一步
                break;
            }
        }

        //创建一个User对象,把接收到的属性值封装进去
        User user = new User(username,password2,personId,phone);
        //并将user添加到集合中
        list.add(user);

        //提示信息
        System.out.println("注册成功!");
    }

 登录方法

  • 对应需求文档

登录功能

  • 键盘录入用户名
  • 键盘录入密码
  • 键盘录入验证码
  • 验证要求:
    • 用户名如果未注册,直接结束方法,并提示:用户名未注册,请先注册
    • 判断验证码是否正确,如不正确,重新输入
    • 再判断用户名和密码是否正确,有3次机会
生成随机验证码
  • 根据需求分析,我们需要在登录方法中使用到创建一个随机验证码的功能
  • 我们先来对生成验证码的方法进行实现(该方法涉及到StringBuilder的知识点)
  • 其规则如下:

验证码规则

  • 长度为5
  • 由4位大写或者小写字母和1位数字组成,同一个字母可重复
  • 数字可以出现在任意位置
  • 比如:aQa1K
  • 实现代码:
    //生成随机验证码
        private static String getCaptcha() {
            //创建一个集合容器存放字母
            ArrayList<Character> list = new ArrayList<>();
            //将小写英文字母存放进集合中
            for (int i = 0; i < 26; i++) {
                list.add((char)('a' + i));
            }
            //将大写英文字母存放进集合中
            for (int i = 0; i < 26; i++) {
                list.add((char)('A' + i));
            }
    
            //新建一个随机类
            Random r = new Random();
    
            //创建一个容器拼接字符串
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 4; i++) {
                //调用随机类方法生成随机索引
                int index = r.nextInt(list.size());
                //拼接到容器
                sb.append(list.get(index));
            }
    
            //最后生成一个数字
            int num = r.nextInt(10);
            //char n = (char)(num+48);
            sb.append(num);//拼接会把数字转换成字符串
    
            //把字符串变成数组,将数字打乱顺序
            char[] c = sb.toString().toCharArray();
            int newIndex = r.nextInt(c.length);
            char temp = c[newIndex];
            c[newIndex] = c[c.length-1];
            c[c.length-1] = temp;
    
            return new String(c);//参考String的构造方法
        }
判断用户名和密码是否匹配
  • 想要完成登陆操作,需要验证用户输入的用户名和密码是否匹配
  • 新建一个判断方法checkUserPassword,返回一个boolean值:
    • 合法返回true
    • 不合法返回false
  • 实现代码:
    //验证密码与用户名是否匹配
        private static boolean checkUserPassword(ArrayList<User> list,User u) {
            //遍历集合,查找是否有与该用户名和密码匹配的账号
            for (int i = 0; i < list.size(); i++) {
                User user = list.get(i);
                if (user.getPassword().equals(u.getPassword()) && user.getUsername().equals(u.getUsername())){
                    return true;
                }
            }
            return false;
        }
登录方法整体实现 
  • 注意,在通过用户名和密码匹配以及验证码验证后,需要新建一个SystemCore对象,调用该类中的startSystem方法以进入学生管理系统

登陆方法整体实现代码:

//用户登录方法
    private static void stuLogin(ArrayList<User> list) {
        //提示信息
        System.out.println("----开始登录----");
        //新建Scanner类接收数据
        Scanner sc = new Scanner(System.in);

        for (int i = 0; i < 3; i++) {
            //这里的警告(Condition 'i < 3' is always 'true')
            //可能是因为在循环中存在return操作,中途结束方法会导致i永远小于3
            //验证:把‘return;’注释掉就不会继续警告了。可以忽略这个警告!

            //接收用户名
            System.out.println("用户名:");
            String username = sc.next();
            //通过判断getIndex方法的返回值,判断用户是否存在
            int index = getIndex(list, username);
            if (index < 0) {
                //不存在索引,用户不存在
                System.out.println("用户名未注册,请先注册!");
                //结束方法
                return;
            }

            //接收密码
            System.out.println("密码:");
            String password = sc.next();

            while (true) {
                //getCaptcha()调用创建验证码的方法
                String captcha = getCaptcha();

                //输入验证码
                System.out.println("请输入验证码:" + captcha);
                String enterCaptcha = sc.next();
                //判断验证码
                if (!(enterCaptcha.equalsIgnoreCase(captcha))) {
                    System.out.println("验证码错误!");
                }else {
                    System.out.println("验证码正确!");
                    break;
                }
            }

            //定义一个方法判断密码是否正确
            //以后传递参数直接传递一个整体即可,不必理会零散数据
            User u = new User(username,password,null,null);
            boolean b = checkUserPassword(list,u);
            if (b){
                System.out.println("登录成功");
                //登录成功,进入管理系统
                SystemCore ss = new SystemCore();//警告原因(暂时不必理会):在对象的Class中只存在static静态变量,这里再new一个对象就多余了
                ss.startSystem();
                break;
            }else {
                System.out.println("密码和用户名不匹配!");
                if(i == 2){
                    System.out.println("当前电脑被锁定!");
                    return;
                }else {
                    System.out.println("您还剩"+(2-i)+"次机会!");
                }
            }
        }
    }

忘记密码方法 

  • 对应需求文档

忘记密码

  • 键盘录入用户名,判断当前用户名是否存在,如不存在,直接结束方法,并提示:未注册
  • 键盘录入身份证号码和手机号码
  • 判断当前用户的身份证号码和手机号码是否一致:
    • 如果一致,则提示输入密码,进行修改。
    • 如果不一致,则提示:账号信息不匹配,修改失败。
判断用户名、身份证号和手机号码是否匹配
  • 有两个实现方法,方法一是在忘记密码方法里直接实现,方法二是新建一个判断方法,把获取到的用户名、身份证号和手机号码封装进一个User对象中传给方法,方法返回一个布尔值
    • 匹配返回true
    • 不匹配返回false
  • 我们在该项目中采用方法一,但我们先来展示方法二
    • 新建一个checkIdAndPhone方法
  • 方法二实现代码:
  • //判断该用户的身份证号和手机号是否一致
        //方法二:
        /*private static boolean checkIdAndPhone(ArrayList<User> list, User user) {
            for (int i = 0; i < list.size(); i++) {
                User u = list.get(i);
                if (u.getPersonId().equalsIgnoreCase(user.getPersonId()) && u.getPhone().equals(user.getPhone()) && u.getUsername().equals(user.getUsername())){
                    return true;
                }
            }
            System.out.println("身份证与手机号不匹配!");
            return false;
        }*/
  • 方法一实现代码:
  • //判断该用户的身份证号和手机号是否一致----方法一:
            //创建对象存放索引所对应的地址值(getIndex获取)
            User user = list.get(index);
            if (!(user.getPersonId().equalsIgnoreCase(personId) && user.getPhone().equals(phone))){
                System.out.println("身份证与手机号不匹配!");
                return;
            }
忘记密码方法整体实现

忘记密码方法整体实现代码:

//忘记密码方法
    private static void stuForgetPassword(ArrayList<User> list) {
        //提示信息
        System.out.println("++++正在找回密码++++");
        //新建Scanner接收数据
        Scanner sc = new Scanner(System.in);

        //接收用户名
        System.out.println("请输入您的用户名:");
        String username = sc.next();
        //验证用户名是否存在
        int index = getIndex(list, username);
        if (index < 0){
            //用户不存在
            System.out.println("该用户未注册!");
            return;
        }

        //接收身份证号和手机号
        System.out.println("请输入您的身份证号码:");
        String personId = sc.next();
        System.out.println("请输入您的手机号码:");
        String phone = sc.next();

        //判断该用户的身份证号和手机号是否一致----方法一:
        //创建对象存放索引所对应的地址值(getIndex获取)
        User user = list.get(index);
        if (!(user.getPersonId().equalsIgnoreCase(personId) && user.getPhone().equals(phone))){
            System.out.println("身份证与手机号不匹配!");
            return;
        }

        /*创建方法判断该用户的身份证号和手机号是否一致----方法二:
        //创建一个对象存放信息
        User user = new User(username,null,personId,phone);
        boolean b = checkIdAndPhone(list,user);
        if (!b){
            return;
        }*/
        //输入密码进行修改

        String newPassword; //警告原因(不必理会):有相同功能代码块;
        while (true) {
            //输入两次密码,对两次密码进行比对
            System.out.println("请输入您的密码:");
            String password1 = sc.next();
            System.out.println("请再次输入您的密码:");
            newPassword = sc.next();
            if (password1.equals(newPassword)){
                //相同则退出循环进入下一步
                break;
            }else {
                System.out.println("两次密码不一致,请重新输入!");
            }
        }

        //修改密码
        user.setPassword(newPassword);//list.get(index).setPassword(newPassword);
        System.out.println("修改成功");
    }

完成到这一步,我们整个项目的代码就书写完成啦!

StudentManagementPro的全部代码

  • 代码中有非常详细的注释,可以仔细阅读和琢磨哦~
  • 项目的源代码也会打包上传到平台,可以在文章最上方的获取项目压缩包

整体代码:

import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;

public class StudentManagementPro {
    public static void main(String[] args) {
        //新建一个集合以存放User对象
        ArrayList<User> list = new ArrayList<>();
        //新建一个Scanner类,接收选择信息
        Scanner sc = new Scanner(System.in);

        while (true) {
            //打印提示信息
            System.out.println("----欢迎来到学生管理系统Pro----");
            System.out.println("1.登录");
            System.out.println("2.注册");
            System.out.println("3.忘记密码");
            System.out.println("4.退出");
            System.out.println("--> 请选择您的操作:");

            //接收输入的信息
            String chose = sc.next();

            //选择流程
            switch (chose){
                case "1" -> stuLogin(list);                 //登录系统
                case "2" -> stuRegister(list);              //用户注册
                case "3" -> stuForgetPassword(list);        //忘记密码操作
                case "4" -> {                               //退出系统
                    System.out.println("---退出系统---");
                    System.exit(0);
                }
                default -> System.out.println("###-没有该选项-###");
            }
        }
    }

    /*以下为三个核心功能的方法*/
    //用户注册方法(优先实现,先注册才能验证其他功能)
    private static void stuRegister(ArrayList<User> list) {
        //提示信息
        System.out.println("----开始注册----");
        //新建一个Scanner类,获取用户名
        Scanner sc = new Scanner(System.in);

        String username;//将变量提取在循环外定义,以便后续能够使用
        while (true) {
            //获取用户名
            System.out.println("请输入一个新的用户名:");
            username = sc.next();
            //新建一个方法判断用户名的合法性,如果合法:true;如果不合法:false;
            boolean b = usernameJudgment(list,username);
            if (b){
                //如果合法,跳出循环,进入下一步
                //如果用户名不符合要求,则进入下一次循环重新输入
                break;
            }
        }

        String password2;
        while (true) {
            //输入两次密码,对两次密码进行比对
            System.out.println("请输入您的密码:");
            String password1 = sc.next();
            System.out.println("请再次输入您的密码:");
            password2 = sc.next();
            if (password1.equals(password2)){
                //相同则退出循环进入下一步
                break;
            }else {
                System.out.println("两次密码不一致,请重新输入!");
            }
        }

        String personId;
        while (true) {
            //输入身份证号
            System.out.println("请输入您的身份证号:");
            personId = sc.next();
            //定义方法对身份证号合法性进行验证,如果合法:true;如果不合法:false;
            boolean b = personIdJudgment(personId);
            if (b){
                //如果验证结果为true,则退出循环,进入下一步
                break;
            }
        }

        String phone;
        while (true) {
            //输入手机号
            System.out.println("请输入您的手机号码:");
            phone = sc.next();
            //判断手机号的合法性,如果合法:true;如果不合法:false;
            boolean b = phoneJudgment(phone);
            if (b){
                //如果验证结果为true,则退出循环,进入下一步
                break;
            }
        }

        //创建一个User对象,把接收到的属性值封装进去
        User user = new User(username,password2,personId,phone);
        //并将user添加到集合中
        list.add(user);

        //提示信息
        System.out.println("注册成功!");
    }

    //用户登录方法
    private static void stuLogin(ArrayList<User> list) {
        //提示信息
        System.out.println("----开始登录----");
        //新建Scanner类接收数据
        Scanner sc = new Scanner(System.in);

        for (int i = 0; i < 3; i++) {
            //这里的警告(Condition 'i < 3' is always 'true')
            //可能是因为在循环中存在return操作,中途结束方法会导致i永远小于3
            //验证:把‘return;’注释掉就不会继续警告了。可以忽略这个警告!

            //接收用户名
            System.out.println("用户名:");
            String username = sc.next();
            //通过判断getIndex方法的返回值,判断用户是否存在
            int index = getIndex(list, username);
            if (index < 0) {
                //不存在索引,用户不存在
                System.out.println("用户名未注册,请先注册!");
                //结束方法
                return;
            }

            //接收密码
            System.out.println("密码:");
            String password = sc.next();

            while (true) {
                //getCaptcha()调用创建验证码的方法
                String captcha = getCaptcha();

                //输入验证码
                System.out.println("请输入验证码:" + captcha);
                String enterCaptcha = sc.next();
                //判断验证码
                if (!(enterCaptcha.equalsIgnoreCase(captcha))) {
                    System.out.println("验证码错误!");
                }else {
                    System.out.println("验证码正确!");
                    break;
                }
            }

            //定义一个方法判断密码是否正确
            //以后传递参数直接传递一个整体即可,不必理会零散数据
            User u = new User(username,password,null,null);
            boolean b = checkUserPassword(list,u);
            if (b){
                System.out.println("登录成功");
                //登录成功,进入管理系统
                SystemCore ss = new SystemCore();//警告原因(暂时不必理会):在对象的Class中只存在static静态变量,这里再new一个对象就多余了
                ss.startSystem();
                break;
            }else {
                System.out.println("密码和用户名不匹配!");
                if(i == 2){
                    System.out.println("当前电脑被锁定!");
                    return;
                }else {
                    System.out.println("您还剩"+(2-i)+"次机会!");
                }
            }
        }
    }

    //忘记密码方法
    private static void stuForgetPassword(ArrayList<User> list) {
        //提示信息
        System.out.println("++++正在找回密码++++");
        //新建Scanner接收数据
        Scanner sc = new Scanner(System.in);

        //接收用户名
        System.out.println("请输入您的用户名:");
        String username = sc.next();
        //验证用户名是否存在
        int index = getIndex(list, username);
        if (index < 0){
            //用户不存在
            System.out.println("该用户未注册!");
            return;
        }

        //接收身份证号和手机号
        System.out.println("请输入您的身份证号码:");
        String personId = sc.next();
        System.out.println("请输入您的手机号码:");
        String phone = sc.next();

        //判断该用户的身份证号和手机号是否一致----方法一:
        //创建对象存放索引所对应的地址值(getIndex获取)
        User user = list.get(index);
        if (!(user.getPersonId().equalsIgnoreCase(personId) && user.getPhone().equals(phone))){
            System.out.println("身份证与手机号不匹配!");
            return;
        }

        /*创建方法判断该用户的身份证号和手机号是否一致----方法二:
        //创建一个对象存放信息
        User user = new User(username,null,personId,phone);
        boolean b = checkIdAndPhone(list,user);
        if (!b){
            return;
        }*/
        //输入密码进行修改

        String newPassword; //警告原因(不必理会):有相同功能代码块;
        while (true) {
            //输入两次密码,对两次密码进行比对
            System.out.println("请输入您的密码:");
            String password1 = sc.next();
            System.out.println("请再次输入您的密码:");
            newPassword = sc.next();
            if (password1.equals(newPassword)){
                //相同则退出循环进入下一步
                break;
            }else {
                System.out.println("两次密码不一致,请重新输入!");
            }
        }

        //修改密码
        user.setPassword(newPassword);//list.get(index).setPassword(newPassword);
        System.out.println("修改成功");
    }



    /*以下为配合三个核心功能实现的其他方法*/
    //手机号码合法性验证----
    private static boolean phoneJudgment(String phone) {
        //长度为11
        if (phone.length() != 11){
            System.out.println("手机号的长度必须为11位,请重新输入!");
            return false;
        }
        //不能以'0'开头-----拓展(字符转字符串):String Str = Character.toString('c');
        if (phone.startsWith("0")){
            System.out.println("手机号不能以‘0’为开头,请重新输入!");
            return false;
        }
        //必须都是数字
        for (int i = 0; i < phone.length(); i++) {
            char c = phone.charAt(i);
            if (!(c >= '0' && c <= '9')){
                System.out.println("手机号必须是纯数字组合,请重新输入!");
                return false;
            }
        }
        return true;
    }

    //身份证号合法性验证----
    private static boolean personIdJudgment(String personId) {
        //长度为18
        if (personId.length() != 18){
            System.out.println("身份证号的长度必须为18位,请重新输入!");
            return false;
        }
        //不能以'0'开头
        if (personId.startsWith("0")){
            System.out.println("身份证号不能以‘0’为开头,请重新输入!");
            return false;
        }
        //前面17位必须是数字
        for (int i = 0; i < personId.length() - 1; i++) {
            char c = personId.charAt(i);
            if (!(c >= '0' && c <= '9')){
                System.out.println("身份证号前面17位必须是数字,请重新输入!");
                return false;
            }
        }
        //最后一位可以是数字或者大小写X
        char c2 = personId.charAt(personId.length()-1);
        if ((c2 >= '0' && c2 <= '9') || c2 == 'X' || c2 == 'x'){
            return true;
        }else {
            System.out.println("身份证号最后一位必须是数字或者大小写X,请重新输入!");
            return false;
        }
    }

    //用户名合法性验证----
    private static boolean usernameJudgment(ArrayList<User> list, String username) {
        //用户名长度必须在3-15之间
        //用一个变量接受字符串长度,不用调用两次length(),效率更高
        int length = username.length();
        if (!(length >= 3 && length <= 15)){
            //如果长度不在这个范围,返回false
            System.out.println("请重新输入一个3-15位的用户名!");
            return false;
        }
        //只能是数字加字母的组合
        //遍历的到字符串中的每一个字符
        for (int i = 0; i < username.length(); i++) {
            char c = username.charAt(i);
            if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))){
                //如果不是数字加字母的组合,返回false
                System.out.println("用户名只能是字母加数字的组合,请重新输入!");
                return false;
            }
        }
        //不能是纯数字
        //遍历user中的每一个字符,计算字母的数量
        int count = 0;
        for (int i = 0; i < username.length(); i++) {
            char c = username.charAt(i);
            if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')){
                count++;
                break;//如果有一个字母,直接退出循环,提高效率
            }
        }
        //通过count判断用户名是不是纯数字
        if (count == 0){
            System.out.println("用户名不能为纯数字组合,请重新输入!");
            return false;
        }
        //判断用户名的唯一性
        int index = getIndex(list,username);
        if (index >= 0){
            System.out.println("该用户已存在,请重新输入!");
            return false;
        }else {
            return true;
        }
    }

    //判断用户名的唯一性,并获取存在用户的索引值---+
    private static int getIndex(ArrayList<User> list,String username) {
        //遍历集合
        for (int i = 0; i < list.size(); i++) {
            User u = list.get(i);
            if (u.getUsername().equals(username)){
                //如果存在该用户名,返回索引
                return i;
            }
        }
        //不存在该用户
        return -1;
    }

    //验证密码与用户名是否匹配
    private static boolean checkUserPassword(ArrayList<User> list,User u) {
        //遍历集合,查找是否有与该用户名和密码匹配的账号
        for (int i = 0; i < list.size(); i++) {
            User user = list.get(i);
            if (user.getPassword().equals(u.getPassword()) && user.getUsername().equals(u.getUsername())){
                return true;
            }
        }
        return false;
    }

    //生成随机验证码
    private static String getCaptcha() {
        //创建一个集合容器存放字母
        ArrayList<Character> list = new ArrayList<>();
        //将小写英文字母存放进集合中
        for (int i = 0; i < 26; i++) {
            list.add((char)('a' + i));
        }
        //将大写英文字母存放进集合中
        for (int i = 0; i < 26; i++) {
            list.add((char)('A' + i));
        }

        //新建一个随机类
        Random r = new Random();

        //创建一个容器拼接字符串
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 4; i++) {
            //调用随机类方法生成随机索引
            int index = r.nextInt(list.size());
            //拼接到容器
            sb.append(list.get(index));
        }

        //最后生成一个数字
        int num = r.nextInt(10);
        //char n = (char)(num+48);
        sb.append(num);//拼接会把数字转换成字符串

        //把字符串变成数组,将数字打乱顺序
        char[] c = sb.toString().toCharArray();
        int newIndex = r.nextInt(c.length);
        char temp = c[newIndex];
        c[newIndex] = c[c.length-1];
        c[c.length-1] = temp;

        return new String(c);//参考String的构造方法
    }

    //判断该用户的身份证号和手机号是否一致
    //方法二:
    /*private static boolean checkIdAndPhone(ArrayList<User> list, User user) {
        for (int i = 0; i < list.size(); i++) {
            User u = list.get(i);
            if (u.getPersonId().equalsIgnoreCase(user.getPersonId()) && u.getPhone().equals(user.getPhone()) && u.getUsername().equals(user.getUsername())){
                return true;
            }
        }
        System.out.println("身份证与手机号不匹配!");
        return false;
    }*/
}

结语


    经过漫长的分析和编码过程,相信大家都有很多收获。这个综合项目给我的个人感觉是:

  • 编程需要有分析思维,先分析后编码是一个非常重要的习惯
  • 打代码要保持一个清晰的思路,非常考验注意力的集中
  • 代码虽然实现过程很辛苦,但练习了就会有收获,编码速度和编程逻辑能力也会有很大提升
  • 努力学习,坚持运动,劳逸结合!

I‘m Joe, byebye~ 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值