走进Java:学生管理系统进阶

走进Java:学生管理系统进阶

❀❀❀  大佬求个关注吧~祝您开心每一天  ❀❀❀

目录

一、系统设计图

 二、添加用户类

三、系统功能设计

3.1 系统菜单打印

3.2 系统注册

3.2.1 检测账号是否存在

3.2.2 检测密码是否满足要求

3.2.3 检测身份证号是否满足要求

3.3 系统登陆

3.3.1 限制登录次数

3.4 忘记密码

3.4.1 重置密码


上一篇文章当中,写了一个简单的学生管理系统,今天在这个系统的基础上,实现一个基于用户登录注册的学生管理系统。

走进Java:实现一个简单的学生管理系统-ZEEKLOG博客

一、系统设计图

系统流程图大致如上,图中有有一些部分在这里省略掉了,用简单的方式展示一下系统的功能。

主要包含三个模块,登录、注册和忘记密码。

登录功能包含验证码校验(只是模拟简单的验证码校验,不涉及短信等服务),还有密码重试次数,当密码重试达到一定次数后,就会禁止登陆。

注册功能在使用的时候还会填写姓名和身份证号码,用于忘记密码时候的密保信息,注册功能确保注册的用户的账号不重复。

忘记密码功能,会校验用户输入的密保信息,信息正确则提示用户修改密码,然后重新跳转登录(图中未体现)。

 二、添加用户类

对于用户类的设计,除了基本的账号、密码、姓名和身份证号外,应该还有一些其他的信息,比如我们提到了会记录用户登录时输入密码的次数,我们可以考虑在用户类中添加一个属性,来记录用户输入密码错误的次数。引入错误次数后,还要考虑,将错误次数清除,我们可以设计在第二天的时候,清空错误次数,不然用户就无法登陆了。所以还要有一个字段记录第一次错误时候的时间。只要用户可以在规定次数内输入正确,就把这个错误次数清空。

public class User { private String username; private String password; private String nickname; private String idNumber; private String errorDate; private Integer errorCount; } 

代码中的get和set方法我去掉了在这里,因为太长了,大家可以自己补全一下,使用Alt+Insert键,选择getter和setter就可以自动生成。

三、系统功能设计

3.1 系统菜单打印

和上次的文章一样,系统菜单的打印差不多,主要就是登录、注册和忘记密码功能。

 public static void main(String[] args) { Scanner sc = new Scanner(System.in); while(true){ printMenu(); System.out.print("请输入要进入的功能:"); int option = sc.nextInt(); switch (option){ case 1: System.out.println("登录"); break; case 2: System.out.println("注册"); break; case 3: System.out.println("忘记密码"); break; case 0: System.out.println("退出系统"); break; default: System.out.println("输入的选项有误"); break; } } } public static void printMenu() { // 打印菜单界面 System.out.println("┌──────────────────────────┐"); System.out.println("│ 学生信息管理系统登录 │"); System.out.println("├──────────────────────────┤"); System.out.println("│ 1. 登录 │"); System.out.println("│ 2. 注册 │"); System.out.println("│ 3. 忘记密码 │"); System.out.println("│ 0. 退出系统 │"); System.out.println("└──────────────────────────┘"); }

3.2 系统注册

系统的注册功能在这里我做了两个校验:

  1. 密码安全性校验:要求密码是6-10位且包含字母和数字的组合
  2. 身份证号校验:身份证号必须满足真实身份证号的规则(可以用自己的,本地程序不会有信息泄露)

注册功能代码如下,详细内容可以看代码中的注释。有些逻辑还是可以补充的,比如密码输入错误可以使用循环重试,这里我直接返回了。

 public static void registerUser(List<User> users){ // 注册用户首先保证用户名不能重复 // 模拟信息的填写过程 Scanner sc = new Scanner(System.in); System.out.print("请输入用户名:"); String username = sc.next(); // 检查用户是否存在了 boolean checkUserExist = checkUserExist(users, username); if(checkUserExist){ // 用户存在了 System.out.println("该用户已被注册!"); // 跳出到系统页面 return; } System.out.print("请输入密码(6-10位,且包含数字和字母):"); String password = sc.next(); // 进行密码强度的检测 我们要求密码是6-10位的数字和字母组成 boolean safe = checkPassword(password); if(!safe){ // 相当于 if(safe == false) System.out.println("您的密码输入格式有误!"); // 这里直接返回了,其实这里可以用循环去操作 // 但是这里设定,输入密码有误直接跳出到登录页面重新尝试 return; } System.out.print("确认密码:"); String ensurePassword = sc.next(); if(!password.equals(ensurePassword)){ // 如果两次密码不一致,直接返回 System.out.println("您输入的两次密码不一致!"); return; } System.out.print("请输入您的姓名(用作密保信息):"); String nickname = sc.next(); System.out.print("请输入您的身份证号码(仅用作密码信息):"); String idNumber = sc.next(); // 校验输入的身份证号码 boolean checkNumber = checkIDNumber(idNumber); if(!checkNumber){ // 相当于 checkNumber == false // 身份证号不符合规则 // 这里不跳出去了,毕竟都输入了那么多信息了,这里给两次重试机会 for (int i = 0; i < 2 && !checkNumber; i++) { System.out.println("您输入的身份证号码有误,请重新尝试!"); System.out.print("请输入您的身份证号码(仅用作密码信息):"); idNumber = sc.next(); checkNumber = checkIDNumber(idNumber); } //这里在判断一下身份证对不对 if(!checkNumber){ // 输入了两次还是不对 System.out.println("您输入的身份证有误,失败次数过多,退出系统"); return; } } // 走到这里就说明有一次是输入正确的 User user = new User(); user.setUsername(username); user.setPassword(password); user.setNickname(nickname); user.setIdNumber(idNumber); user.setErrorCount(0); user.setErrorDate(SimpleDateFormat.getDateInstance().format(new Date())); users.add(user); System.out.println("注册成功!"); return; }

在上方的代码中,用到了三个方法,分别用户检测账号是否被注册、检测输入的密码是否正确以及检测输入的身份证号是否满足真实身份证号的信息。

3.2.1 检测账号是否存在

private static boolean checkUserExist(List<User> users, String username) { for (User user : users) { if(user.getUsername().equals(username)){ return true; } } return false; }

3.2.2 检测密码是否满足要求

这个正则表达式不用太在意,我也是在网上搜索的,大家有时间可以自己学习一下。

 private static boolean checkPassword(String password) { Pattern pattern = Pattern.compile("^(?!^\\d+$)(?!^[a-zA-Z]+$)[a-zA-Z0-9]{6,10}$"); Matcher matcher = pattern.matcher(password); /*if(matcher.matches()){ // 证明符合规则 return true }else{ return false; }*/ return matcher.matches(); }

3.2.3 检测身份证号是否满足要求

private static boolean checkIDNumber(String idNumber) { // 身份证号码正则表达式,我们直接上网搜索,这里不在讲解正则表达式了 Pattern pattern = Pattern.compile("^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$"); Matcher matcher = pattern.matcher(idNumber); /*if(matcher.matches()){ // 证明符合规则 return true }else{ return false; }*/ return matcher.matches(); }

3.3 系统登陆

public static boolean loginUser(List<User> users){ Scanner sc = new Scanner(System.in); // 模拟一个验证码 Random random = new Random(); String sendCode = String.valueOf(1000 + random.nextInt(9000)); System.out.println("系统向您的手机发送了验证码,请查收"); System.out.println("您的验证码是:" + sendCode); System.out.print("请输入账号:"); String username = sc.next(); // 判断用户是否存在 boolean checkUserExist = checkUserExist(users, username); if(!checkUserExist){ // 如果不存在 System.out.println("该账号未注册!"); return false; } // 添加验证码校验 System.out.print("请输入验证码:"); String code = sc.next(); if(!code.equals(sendCode)){ // 验证码不正确 return false; } System.out.print("请输入密码"); String password = sc.next(); boolean checkLogin = false; // 判断密码是否正确 // 这里我没有写新的方法,其实是可以单独写一个方法的 for (User user : users) { if(user.getUsername().equals(username) && user.getPassword().equals(password)){ // 密码验证正确 checkLogin = true; } } if(!checkLogin){ // 如果密码不正确 System.out.println("您的密码有误!"); return false; } // 登录成功 return true; }

登录的代码的逻辑都写到了注释当中了,当我们登录成功后,是要登录到学生管理系统的,对比之前写过的管理系统的代码,应该调整一下之前的代码,不能在main方法中启动程序了。调整到普通的方法当中,其中的静态方法也要 改为静态,且私有,只有展示菜单的方法,我们设置为公有。

public static void -》 private void

然后把main方法的内容写到startApp方法中,删掉main方法。

public void startApp(){ List<Student> students = new ArrayList<>(); printMenu(); while (true) { int option; Scanner sc = new Scanner(System.in); System.out.print("请选择要进行的操作:"); option = sc.nextInt(); switch (option) { case 1: getStudentInfo(students); break; case 2: addStudent(students); break; case 3: updateStudentInfo(students); break; case 4: deleteStudentInfo(students); break; case 0: System.out.println("退出系统"); System.exit(0); break; default: System.out.println("请输入正确的选项"); break; } } }

调整我们写的登录的代码,switch中的。

switch (option){ case 1: if(loginUser(users)){ Runtime.getRuntime().exec("cls"); // 把我们展示系统功能的页面打印出来 new StudentManagement().startApp(); } break; case 2: registerUser(users); break; case 3: System.out.println("忘记密码"); break; case 0: System.out.println("退出系统"); System.exit(0); break; default: System.out.println("输入的选项有误"); break; }

我在测试的时候发现,在学生管理页面输入0的时候,直接退出系统了,并没有跳转到这个登录页面,检查管理系统的页面发现,使用了这行命令。这行代码直接让我们的程序退出了,会影响到我们的登录功能,所以要调整一下。

调整后的代码如下:

 在这里如果是0的话直接return。

3.3.1 限制登录次数

当我们密码输入错误的时候,就会记录到errorCount属性中。

具体的逻辑都在注释当中了。

public static boolean loginUser(List<User> users){ Scanner sc = new Scanner(System.in); // 模拟一个验证码 Random random = new Random(); String sendCode = String.valueOf(1000 + random.nextInt(9000)); System.out.println("系统向您的手机发送了验证码,请查收"); System.out.println("您的验证码是:" + sendCode); System.out.print("请输入账号:"); String username = sc.next(); // 判断用户是否存在 boolean checkUserExist = checkUserExist(users, username); if(!checkUserExist){ // 如果不存在 System.out.println("该账号未注册!"); return false; } // 判断账号今日是否封禁了 密码重试次数达到上线 for (User user : users) { if(user.getUsername().equals(username)){ String errorDate = user.getErrorDate(); String currentDate = SimpleDateFormat.getDateInstance().format(new Date()); if(user.getErrorCount() >= 3 && errorDate!= null && errorDate.equals(currentDate)){ System.out.println("您的密码重试次数达到上限,今日无法登录!"); return false; } } } // 添加验证码校验 System.out.print("请输入验证码:"); String code = sc.next(); if(!code.equals(sendCode)){ // 验证码不正确 return false; } System.out.print("请输入密码:"); String password = sc.next(); boolean checkLogin = false; // 判断密码是否正确 // 这里我没有写新的方法,其实是可以单独写一个方法的 for (User user : users) { if(user.getUsername().equals(username) && user.getPassword().equals(password)){ // 密码验证正确 checkLogin = true; }else if(user.getUsername().equals(username) && !user.getPassword().equals(password)){ // 判断是不是当天第一次错误 int errorCount = user.getErrorCount(); String errorDate = user.getErrorDate(); String currentDate = SimpleDateFormat.getDateInstance().format(new Date()); // 如果错误日期为空,说明我们还没有错误过 证明是第一次错误 // 如果错误日期不为空,那么判断错误日期是否是当前日期,如果不是,说明记录的是之前错误的次数 也是当天第一次错误 if(errorDate == null || !errorDate.equals(currentDate)){ // 当天第一次错误 user.setErrorCount(1); user.setErrorDate(currentDate); }else{ // 不是当天第一次错误 user.setErrorCount(errorCount + 1); if(user.getErrorCount() >= 3){ // 如果错误次数大于等于3了,就不让用户登陆了 System.out.println("您的密码重试次数达到上限,今日无法登录!"); return false; } } } } if(!checkLogin){ // 如果密码不正确 System.out.println("您的密码有误!"); return false; } // 登录成功 return true; }

3.4 忘记密码

最后就是忘记密码的功能了,在选择忘记密码时,首先输入忘记密码的账号,然后首先要判断一下账号是否存在。当密保信息校验正确后,重置密码。

private static void forgetPassword(List<User> users) { Scanner sc = new Scanner(System.in); System.out.print("请输入账号:"); String username = sc.next(); // 从users中查出这个用户 // 这里用之前写的checkUserExist那个方法 boolean userExist = checkUserExist(users, username); if(!userExist){ System.out.println("该账号未注册!"); return; } // 但是这样写就会重复循环 // 因为要获取用户的密保信息 User user = new User(); for (User u : users) { if(user.getUsername().equals(username)){ user = u; break; } } System.out.print("请输入绑定的姓名:"); String nickname = sc.next(); System.out.println("请输入绑定的身份证号:"); String idNumber = sc.next(); if(nickname.equals(user.getNickname()) && idNumber.equals(user.getIdNumber())){ // 校验成功 重新修改密码 changePassword(user); return; } System.out.println("密保信息校验失败!"); }

3.4.1 重置密码

之前说到过,Java中是值传递的,这样子可以修改到users中对应用户的密码。

private static void changePassword(User user) { Scanner sc = new Scanner(System.in); System.out.print("请输入新的密码(6-10位,且包含数字和字母):"); String password = sc.next(); boolean checkPassword = checkPassword(password); if(!checkPassword){ for (int i = 0; i < 2 && !checkPassword; i++) { System.out.print("您输入的密码格式有误,请重新输入密码:"); password = sc.next(); checkPassword = checkPassword(password); } } if(!checkPassword){ System.out.println("失败次数过多!"); return; } user.setPassword(password); }

Read more

【问题反馈】JNI 开发:为什么 C++ 在 Debug 正常,Release 却返回 NaN?

【问题反馈】JNI 开发:为什么 C++ 在 Debug 正常,Release 却返回 NaN?

摘要: 在 Android NDK / JNI 开发中,经常会遇到这样一种“诡异”问题:Debug 模式下运行完全正常,而 Release 模式却出现 NaN、Infinity 甚至随机结果。 本文通过一次真实的 JNI 坐标转换案例,深入分析了该问题的根本原因——C++ 返回局部栈内存指针所导致的未定义行为(Undefined Behavior)。 【问题反馈】JNI 开发:为什么 C++ 在 Debug 正常,Release 却返回 NaN? 本文为以下问题的解决记录。由于问题较为典型,故梳理备忘。 https://github.com/eqgis/Sceneform-EQR/discussions/16 一、问题现象描述 1. 现象

By Ne0inhk

C++ 重载、隐藏、覆盖

结合这C++ 代码,深入理解重载(Overload)、隐藏(Hide) 和覆盖(Override,也叫重写) 这三个核心概念,用这段代码作为核心案例,由浅入深地拆解它们的区别和本质。 一、先明确三个概念的核心定义 这三个概念都是 C++ 中函数名复用的场景,但适用范围、规则和目的完全不同,先看一张对比表建立整体认知: 概念中文名称适用范围核心特征本质目的Overload重载同一个作用域内函数名相同,参数列表(个数/类型/顺序)不同,返回值不影响方便同一功能的不同参数调用Override覆盖/重写子类与父类之间子类重写父类的虚函数,函数签名(名+参数+const)完全一致实现多态(运行时动态绑定)Hide隐藏/遮蔽子类与父类之间子类函数名覆盖父类同名函数(无论参数/虚函数与否),编译期静态屏蔽作用域优先原则导致的“遮蔽” 覆盖是特殊的隐藏。 二、结合代码逐个拆解 逐个分析这三个概念,并用扩展代码演示效果。 1. 重载(Overload)—— 同一作用域内的“同名不同参”

By Ne0inhk
基于SpringBoot+Vue的图书电子商务网站管理系统设计与实现【Java+MySQL+MyBatis完整源码】

基于SpringBoot+Vue的图书电子商务网站管理系统设计与实现【Java+MySQL+MyBatis完整源码】

摘要 随着互联网技术的快速发展,电子商务已成为现代商业活动的重要组成部分。图书作为文化传播的重要载体,其线上销售模式逐渐成为主流趋势。传统的图书销售模式受限于时间和空间,难以满足消费者多样化的需求。基于此背景,设计并实现一个高效、便捷的图书电子商务网站管理系统具有重要意义。该系统能够为用户提供在线浏览、购买、评价等功能,同时为管理员提供图书管理、订单处理、用户管理等后台支持。通过整合现代信息技术,该系统旨在提升图书销售的效率与用户体验,推动图书行业的数字化转型。关键词:电子商务、图书管理、SpringBoot、Vue、MySQL。 本系统采用前后端分离的架构设计,后端基于SpringBoot框架实现,前端采用Vue.js框架开发,数据库使用MySQL进行数据存储,并通过MyBatis实现数据持久化操作。系统功能模块包括用户模块、图书模块、订单模块和后台管理模块。用户模块支持注册、登录、个人信息管理等功能;图书模块实现图书分类、搜索、详情展示等功能;订单模块涵盖购物车、订单生成与支付等功能;后台管理模块提供图书上下架、订单处理、用户数据统计等功能。系统通过RESTful API实现前

By Ne0inhk
基于飞算JavaAI的在线图书借阅平台设计与实现

基于飞算JavaAI的在线图书借阅平台设计与实现

引言 在数字化转型背景下,高校图书管理系统面临智能化升级需求。本文以飞算JavaAI为开发工具,通过智能引导式开发流程,实现一个包含用户管理、图书借阅、权限控制等核心功能的在线平台。系统采用Spring Boot + MyBatis技术栈,结合飞算AI的代码生成能力,将传统3周的开发周期压缩至3天,验证了AI辅助开发在Java企业级应用中的高效性。 文章目录 * 引言 * 飞算介绍 * 环境准备 * 1. 下载“IDEA” * 2.安装 * 3. 下载“飞算Java AI”扩展 * 4.登录 * 需求分析与规划 * 核心功能模块 * 技术选型 * 系统实现 * 1. 自然语言描述需求 * 2. 理解需求 * 3. 设计接口 * 4. 表结构设计 * 5. 处理逻辑接口 * 6. 生成源码 * 优化与调试心得 * 遇到的问题 * 调试技巧 * 成果展示与总结

By Ne0inhk