Extjs4学习笔记-ExtJS 4 图片验证码的实现(部分摘自《Extjs4.0学习指南(中文)

      上几篇文章,主要学习了 Extjs4 Grid 的使用方法,从本篇开始,我们开始其他组件的
学习,使用。在登录、注册甚至是发表文章或帖子的时候,都会用到验证码这个东西,那
么在 EXTJS 中,可以使用验证码功能么?答案是肯定的,在 EXTJS4 之前,也有很多验证
码的实现,在 Extjs4 中,验证码到底如何实现呢?
        暂时,我们将验证码组件,命名为 CheckCode。此组件继承自 Ext.form.field.Text,在
实现之前,我们需要写两个样式,分别用来控制验证码的输入框和验证码图片的大小。
CSS 样式为:

#CheckCode{ float:left;} 
.x-form-code{width:73px;height:20px;vertical-align:middle;cursor:pointer; float:left; margin-left:7px;} 

         记住这两个样式的定义,后面,我们会用到它。
验证码的 JS 代码(CheckCode.js):

 

Ext.define('SMS.view.CheckCode', {
    extend: 'Ext.form.field.Text',
    alias: 'widget.checkcode',
    inputType: 'codefield',
    codeUrl: Ext.BLANK_IMAGE_URL,
    isLoader: true,
    
    onRender: function(ct, position) {
        this.callParent(arguments);
        this.codeEl = ct.createChild({
            tag: 'img',
            src: Ext.BLANK_IMAGE_URL
        });
        this.codeEl.addCls('x-form-code');
        this.codeEl.on('click', this.loadCodeImg, this);
        
        if(this.isLoader) {
            this.loadCodeImg();
        }
    },
    
    aliasErrorIcon: function() {
        this.errorIcon.alignTo(this.codeEl, 'tl-tr', [2, 0]);
    },
    
    loadCodeImg: function() {
        //如果浏览器发现url不变,就认为图片没有改变,就会使用缓存中的图片,而不是重新向服务器请求,所以需要加一个参数,改变url 
        this.codeEl.set({
            src: this.codeUrl + '?id=' + Math.random()
        });
    }
});

         以上代码中,定义了一个―类‖,名字是:SMS.view.CheckCode,其实这个名字,相当
于 extjs 3.x 之中的命名空间,以前也提到过。它继承自 Ext.form.field.Text,在它的
onRender 中,我们写了一些代码。其中 this.callParent(arguments);  代替了
xxxx.superclass.onRender.call(this, ct, position);在 Ext.form.field.Text 的基础上,使用
createChild 方法,创建了一个图片,并为其添加了一个名为 x-form-code,而后,给其创建
了一个 click 事件,这个事件实现的功能是,当我们点击验证码图片时,换另外一张图片,
也就是常说的:―看不清?换一张功能。‖,最后,如果 isLoader 为 True 时,调用
loadCodeImg 方法。至此,验证码功能全部完成了。下面,我们看看如何使用。
新建 Login.js 文件,定义―类‖SMS.view.Login,其全部代码为(Login.js):

 

Ext.define('SMS.view.Login', {
    extend: 'Ext.window.Window',
    alias: 'widget.loginForm',
    requires: [
    	'Ext.form.*', 
    	'SMS.view.CheckCode'
    ],
    
    initComponent: function() {
        
        var checkcode = Ext.create('SMS.view.CheckCode', {
            cls: 'key',
            fieldLabel: '验证码',
            name: 'checkcode',
            id: 'checkcode',
            allowBlank: false,
            isLoader: true,
            blankText: '验证码不能为空',
            codeUrl: 'rand.action',
            width: 160
        });
        
        var form = Ext.widget('form', {
            border: false,
            bodyPadding: 10,
            fieldDefaults: {
                labelAlign: 'left',
                labelWidth: 55,
                labelStyle: 'font-weight: bold'                
            },
            defaults: {
                margins: '0 0 10 0'
            },
            items: [{
                xtype: 'textfield',
                id: 'username',
                name: 'username',
                fieldLabel: '用户名',
                blankText: '用户名不能为空',
                allowBlank: false,
                width: 240
            }, {
                xtype: 'textfield',
                id: 'password',
                name: 'password',
                fieldLabel: '密   码',
                allowBlank: false,
                blankText: '密码不能为空',
                width: 240,
                inputType: 'password'
            }, checkcode],
            
            buttons: [{
                text: '登录',
                handler: function() {
                //获取当前的表单form
                var form = this.up('form').getForm();
                //判断否通过了表单验证,如果不能空的为空则不能提交
                if (form.isValid()) {
                    //alert("可以提交");
                    form.submit({
                        clientValidation : true,
                        waitMsg : '请稍候',
                        waitTitle : '正在验证登录',
                        url : 'login.action',
                        success : function(form, action) {
                            //登录成功后的操作,这里只是提示一下
                            Ext.MessageBox.show({
                                width : 150,
                                title : "登录成功",
                                buttons : Ext.MessageBox.OK,
                                msg : action.result.msg
                            })
                        },
                        failure : function(form, action) {
                            Ext.MessageBox.show({
                                width : 150,
                                title : "登录失败",
                                buttons : Ext.MessageBox.OK,
                                msg : action.result.msg
                            })
                        }
                    })
                }
                }
            }, {
                text: '取消',
                handler: function() {
                    //点击取消,关闭登录窗口
                    // var form = this.up('form');
                    // form.close();
                }
            }]
        });
        
        Ext.apply(this, {
            height: 160,
            width: 280,
            title: '用户登录',
            closeAction: 'hide',
            closable: false,
            iconCls: 'login',
            layout: 'fit',
            modal: true,
            plain: true, 
            resizable: false,
            items: form
        });
        this.callParent(arguments);
    }
});

 程序的入口(app.js):

 

Ext.application({
    name: 'SMS',
    
    appFolder: 'app',
    
    launch: function() {
        requires: ['SMS.view.Login']
        var win;
        win = Ext.create('SMS.view.Login').show();
    }   
    
});

 

 

login.jsp:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>用户登录</title>
		
	<link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css" />
	<script type="text/javascript" src="extjs/ext-all.js"></script>
	<script type="text/javascript" src="extjs/ext-lang-zh_CN.js"></script>
	<script type="text/javascript" src="app.js"></script>

	<style type="text/css">
		#checkcode {
			float: left;
		}
		
		.x-form-code {
			width: 73px;
			height: 20px;
			vertical-align: middle;
			cursor: pointer;
			float: left;
			margin-left: 7px;
		}
	</style>

  </head>
  
  <body>
  </body>
</html>

生成随机验证码的类( RandomNumUtil.java):

 

package org.changkong.sms.utils;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;

/**
 * 生成验证码的类文件
 * 
 */
public class RandomNumUtil {
	private ByteArrayInputStream image; 	//图像
	private String str;		//验证码

	private RandomNumUtil() {
		init();		//初始化属性
	}

	/*
	 * 取得RandomNumUtil实例
	 */
	public static RandomNumUtil Instance() {
		return new RandomNumUtil();
	}

	/*
	 * 取得验证码图片
	 */
	public ByteArrayInputStream getImage() {
		return this.image;
	}

	/*
	 * 取得图片的验证码
	 */
	public String getString() {
		return this.str;
	}

	private void init() {
		//在内存中创建图象
		//图像的高度和宽度
		int width = 55, height = 20;
		BufferedImage image = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_RGB);
		//获取图形上下文
		Graphics g = image.getGraphics();
		//生成随机类
		Random random = new Random();
		//设定背景色
		g.setColor(getRandColor(200, 250));
		g.fillRect(0, 0, width, height);
		//设定字体
		g.setFont(new Font("Times New Roman", Font.PLAIN, 18));
		//随机产生155条干扰线,使图象中的认证码不易被其它程序探测到
		g.setColor(getRandColor(160, 200));
		for (int i = 0; i < 155; i++) {
			int x = random.nextInt(width);
			int y = random.nextInt(height);
			int xl = random.nextInt(12);
			int yl = random.nextInt(12);
			g.drawLine(x, y, x + xl, y + yl);
		}
		//取随机产生的认证码(6位数字)
		String sRand = "";
		for (int i = 0; i < 4; i++) {
			String rand = String.valueOf(random.nextInt(10));
			sRand += rand;
			//将认证码显示到图象中
			g.setColor(new Color(20 + random.nextInt(110), 20 + random
					.nextInt(110), 20 + random.nextInt(110)));
			//调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
			g.drawString(rand, 13 * i + 6, 16);
		}
		//赋值验证码
		this.str = sRand;

		//图象生效
		g.dispose();
		ByteArrayInputStream input = null;
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		try {
			ImageOutputStream imageOut = ImageIO
					.createImageOutputStream(output);
			ImageIO.write(image, "JPEG", imageOut);
			imageOut.close();
			input = new ByteArrayInputStream(output.toByteArray());
		} catch (Exception e) {
			System.out.println("验证码图片产生出现错误:" + e.toString());
		}
		this.image = input;/* 赋值图像 */
	}

	/*
	 * 给定范围获得随机颜色
	 */
	private Color getRandColor(int fc, int bc) {
		Random random = new Random();
		if (fc > 255)
			fc = 255;
		if (bc > 255)
			bc = 255;
		int r = fc + random.nextInt(bc - fc);
		int g = fc + random.nextInt(bc - fc);
		int b = fc + random.nextInt(bc - fc);
		return new Color(r, g, b);
	}
}

 验证码的Action(SecurityCodeAction.java):

 

package org.changkong.sms.action;

import java.io.ByteArrayInputStream;

import org.changkong.sms.utils.RandomNumUtil;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

/**
 * 验证码的Action
 * 使用SSH集成开发,Action由Spring管理
 */
@Controller("sercurityCodeAction")
@Scope("prototype")
public class SecurityCodeAction extends ActionSupport {
	
	private ByteArrayInputStream inputStream;

	public String execute() throws Exception {
		
		RandomNumUtil rdnu = RandomNumUtil.Instance();
		
		//取得带有随机字符串的图片
		this.setInputStream(rdnu.getImage());	
		
		//取得随机字符串放入HttpSession
		ActionContext.getContext().getSession().put("random", rdnu.getString());	
		return SUCCESS;
	}

	public void setInputStream(ByteArrayInputStream inputStream) {
		this.inputStream = inputStream;
	}

	public ByteArrayInputStream getInputStream() {
		return inputStream;
	}
	
}

 登录Action(LoginAction.java):

package org.changkong.sms.action;

import org.apache.struts2.ServletActionContext;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.opensymphony.xwork2.ActionContext;

/**
 * 登录Action
 */
@Controller("loginAction")
@Scope("prototype")
public class LoginAction {

	private String username;
	private String password;
	private String checkcode; // 表单中的rand

	//从session中取出RandomAction.java 中生成的验证码random
	String arandom = (String) (ActionContext.getContext().getSession().get("random"));

	public String execute() {
		
		if(!arandom.equals(checkcode)) {
			System.out.println("验证码不正确");
		} else if(!"admin".equals(username)) {
			System.out.println("用户不存在");
		} else if("admin".equals(password)) {
			System.out.println("密码错误");
		}
		return "success";

	}

	public String logout() {
		ServletActionContext.getRequest().getSession().invalidate();
		return "logout";
	}

	public String getCheckcode() {
		return checkcode;
	}

	public void setCheckcode(String checkcode) {
		this.checkcode = checkcode;
	}

	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;
	}
}

 Struts.xml:

 

<!-- 用户登陆 -->
		<action name="login" class="loginAction">
			<!-- LoginAction无需经过LoginInterceptor -->
			<interceptor-ref name="defaultStack"></interceptor-ref>
			<result name="success" type="redirect">/main.jsp</result>
			<result name="fail">/login.jsp</result>
			<result name="logout">/login.jsp</result>
		</action>
		
		<!-- Random验证码 -->
		<action name="rand" class="sercurityCodeAction">
       		<result type="stream">     
            	<param name="contentType">image/jpeg</param>     
            	<param name="inputName">inputStream</param>     
       		</result>  
   		</action>

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值