上个星期老师布置了一道题目:用Java实现验证码的功能。想了一下要用到 Random 类、输入输出和字符串吧。写完之后才发现出现了很多问题,在这里记录一下遇到的问题和暂时性的解决方法。
一、String 类使用的问题
在 Java 里面 字符串 String 是一个类,所以里面包含了很多方法,其中就有实现忽略大小写的比较方法:”Boolean equalsIgnoreCase(String str)”。这个方法就很符合这里的需求,所以我把验证码和用户输入的验证码设置为 String 类的对象,然后就出现了问题:在用户输入错误后重新输入时出现错误。这时才想到老师说过 String 类的对象的值是无法改变,也就是说在新建对象时赋给它什么值,它就始终是这个值,不能再给它赋值,所以我这里出现了错误。怎么解决呢?可以用 StringBuilder 类来替代 String 类,同时呢,StringBuilder 类也提供了一个’toString()’方法。这个方法将 StringBuilder 对象转化为 String,返回的是 String 类的对象。这样子就可以既使用 StringBuilder 又使用 String 的方法了:
this.code.toString().equalsIgnoreCase(this.usrInputCode.toString())
二、产生随机字符的方法
如何产生随机字符呢?一开始我的想法是用 Random 类中的方法来产生随机数字和随机字母。可是找了一下没发现有能产生随机字母的方法。最后想了一个折中的办法:创建一个字符串,里面是按顺序排列的小写字母、大写字母和数字。然后通过产生一个随机的偏移量来获取字符串中的一个字符。具体的代码如下:
private String s = "abcdefghijklmnomqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
/*
* s.charAt(int index) 方法返回s字符串中偏移量为index的字符
* random.nextInt(int num) 方法返回一个范围在[0,num]的随机整数
* s.length()返回字符串s的长度(例如String s="12", s.length()= 2
* 所以下面这条语句的作用是:循环创建一个从字符串s中随机选出的字符,使用append
*/
for(int i = 0; i < numOfCode; i++) {
this.code.append(s.charAt(random.nextInt(s.length())));
}
具体的使用会在后面给出的完整代码中注释
三、Scanner 类的连续输入问题
由于我加入了用户重新输入的功能,这就需要程序能够连续接收用户的输入并存到 usrInputCode 这个变量中。但是在用 Scanner 类的时候总是出错,所用的方法是:
private void getUsrInputCode() {
System.out.println("\nPlease input what you see above\nInput '1' to refresh the code");
/**
* 判断用户是否有输入,若有,则将用户输入的字符串添加到usrInputCode
*/
Scanner in = new Scanner(system.in);
if(in.hasNext()){
this.usrInputCode.append(in.next());
}
in.close();
}
结果第二次调用这个方法的时候就一直在循环,不接收用户的输入。查了百度才知道这是 Scanner 的常见错误之一:一旦 Scanner 类用 close() 关闭之后就不能再被使用,想要再次输入就必须重新创建一个对象,要么就是等到不再使用时再关闭它。我呢,就选择最后不用的时候再关闭它。
四、完整代码
import java.util.Random;
import java.util.Scanner;
import java.lang.StringBuilder;
class VerificationCode {
/**
* 默认的初始化,验证码位数为4,并刷新验证码
*/
public VerificationCode() {
this.numOfCode=4;
this.refreshCode();
}
/**
* 带有参数的构造方法,参数是int类型,代表验证码的位数,并刷新验证码
*/
public VerificationCode(int numOfCode) {
this.numOfCode = numOfCode;
this.refreshCode();
}
/*随机字符表,验证码中的每一位选取该表中的一个元素,包括数字和大小写字母*/
private String s = "abcdefghijklmnomqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
/**
* 验证码保存为 StringBuilder 类型,这里直接进行初始化,具体的赋值在refreshCode 方法
*/
private StringBuilder code = new StringBuilder();
/**
* 用户输入的验证码保存为StringBuilder 类型,这里直接进行初始化,具体的赋值在getUsrInput方法
*/
private StringBuilder usrInputCode = new StringBuilder();
/**
* 验证码的位数,整数
*/
private int numOfCode;
public int getNumOfCode() {
return numOfCode;
}
public void setNumOfCode(int numOfCode) {
this.numOfCode = numOfCode;
}
/**
* 用于接收用户的输入
*/
private Scanner in = new Scanner(System.in);
/**
* 刷新方法,用于清空code 和 usrInputCode,刷新验证码
*/
private void refreshCode() {
Random random = new Random(); //创建一个Random对象,用于产生随机整数
/*
* 将之前的 code 和 usrInputCode 内容清空,以存储下一轮的值
*/
this.code.delete(0, this.code.length());
this.usrInputCode.delete(0, this.usrInputCode.length());
/*
* s.charAt(int index) 方法返回s字符串中偏移量为index的字符
* random.nextInt(int num) 方法返回一个范围在[0,num]的随机整数
* s.length()返回字符串s的长度(例如String s="12", s.length()= 2
* 所以下面这条语句的作用是:循环创建一个从字符串s中随机选出的字符,使用append
*/
for(int i = 0; i < numOfCode; i++) {
this.code.append(s.charAt(random.nextInt(s.length())));
}
}
/**
*在屏幕上显示验证码
*/
private void printCode(){
System.out.println("Your Verification Code is " + this.code);
}
/**
* 接收用户输入的字符
*/
private void getUsrInputCode() {
System.out.println("\nPlease input what you see above\nInput '1' to refresh the code");
/**
* 判断用户是否有输入,若有,则将用户输入的字符串添加到usrInputCode
*/
if(in.hasNext()){
this.usrInputCode.append(in.next());
}
}
/**
* 校验方法,用于检验用户输入的字符串是否等于验证码,返回值是布尔变量
*/
private Boolean verify() {
/**
* 将code 和 usrInputCode 用'toString()'方法转化为字符串
* 然后用字符串的比较方法'equalsIgnoreCase(String str)'来比较字符串是否相等,忽略大小写
*/
if (this.code.toString().equalsIgnoreCase(this.usrInputCode.toString())) {
System.out.println("\nCorrect\n"); //相等则输出正确,并返回true
return true;
}
else {
System.out.println("\nWrong! Please Try Again!\n"); //不匹配则输出错误,提示重试,返回false
return false;
}
}
/**
* 入口方法,该方法集成了验证码的所有功能:刷新、打印、输入、匹配验证码
*/
public void start() {
while (true) {
this.refreshCode();
this.printCode();
this.getUsrInputCode();
/**
* 如果用户输入的是'1',刷新验证码
*/
if (this.usrInputCode.toString().equals("1") ) {
continue;
}
if (this.verify()) {
break; //如果匹配成功,跳出循环,结束
}
}
}
/**
* 关闭Scanner对象:in.close()
*/
public void finish() {
in.close();
}
}
public class VerificationCodeTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
VerificationCode t = new VerificationCode(4);
t.start();
t.setNumOfCode(16);
t.start();
t.finish();
}
}
本作品由 sunriseydy 采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
文章内容如未说明均为原创,欢迎转载,但请注明原作者(sunriseydy)和原文链接(https://blog.sunriseydy.top/technology/java/java-verification-code/)
部分来自互联网的文章,如有侵权,请联系我,24小时内删除,谢谢
感谢您的支持,SunriseYDY 会继续努力的!



打开支付宝扫一扫,即可进行扫码打赏哦
日出一点一 | 在探索的路上永不止步