用 Java 实现简单的验证码功能及有关问题的思考

设置字体大小:

上个星期老师布置了一道题目:用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();
	}

}

 


赞 (1)   -->微信赞赏<--

微信扫描下方左侧二维码或搜索“sunriseydy”关注我的公众号,便捷地阅读博客内容,订阅博客更新
也可以扫描下方右侧的小程序码,进入我的微信小程序:“sunriseydy”,在手机上阅读文章

      

版权说明:

知识共享许可协议
作品 sunriseydy 采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
文章内容如未说明均为原创,欢迎转载,但请注明原作者和出处。部分来自互联网的文章,如有侵权,请联系我,24小时内删除,谢谢
Email:i@mail.sunriseydy.top

评论一下呗亲

电子邮件地址不会被公开。 必填项已用*标注

添加表情