`
PrisonBreak
  • 浏览: 96068 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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>

 

 

 

  • 大小: 16.7 KB
  • 大小: 18.7 KB
分享到:
评论

相关推荐

    Extjs4.0学习笔记

    Extjs4.0学习笔记,以下是部分介绍: xtjs4,创建Ext组件有了新的方式,就是Ext.create(....),而且可以使用动态加载JS的方式来加快组件的渲染,我们再也不必一次加载已经...ExtJS4学习笔记(十)---ExtJS4图片验证码的实现

    extjs4.0帮助文档 extjs-docs-4.0.2.zip

    extjs4.0开发人员以及学习可以下载参考

    Extjs4.0权威指南-中文

    ### Extjs4.0 权威指南 - 中文版知识点详解 #### 一、Extjs4.0 简介 Extjs 是一款基于 JavaScript 的前端框架,它提供了丰富的 UI 组件库,使得开发者能够快速地构建出高性能的 Web 应用程序。Extjs4.0 是该系列中...

    ExtJS4中文教程2 开发笔记 chm

    ExtJS4学习笔记(十)---ExtJS4图片验证码的实现 ExtJS4学习笔记(十一)---TabPanel ExtJS4学习笔记(十三)---上传文件(upload) ExtJS4学习笔记(十二)---选项卡(tabs) ExtJS4学习笔记(十五)---Ext.data.Model ExtJS4学习...

    ExtJS4.0-API.rar

    ExtJS4.0-API Ext4.0-API Ext4 ExtJS4 API 学EXTJS4的好东西...

    Extjs4.0学习指南(中文)

    ### Extjs4.0 学习指南核心知识点详解 #### 一、获取与安装Extjs4.0 **1.1 获取Extjs4.0** - **官方资源**: 访问官方网站 [http://extjs.org.cn/](http://extjs.org.cn/) 下载最新版本的Extjs4.0及相关文档和支持...

    ExtJS4.0开发笔记

    ExtJS4.0开发笔记

    Extjs4.0学习笔记大全.pdf

    Extjs4.0学习笔记大全.pdf,供大家学习

    Extjs4.0学习笔记大全

    Extjs4.0学习笔记大全

    Extjs4.0学习指南中文PDF版

    Extjs4学习指南(仅供学习使用、转载需注明出处)Extjs4可用的学习资料少之又少,本文内容大部分为网络整理、方便学习者使用,如有出入以extjs4 api文档为准。资源截图: 资源太大,传百度网盘了,链接在附件中,有...

    Extjs 4.0中文版API

    Extjs 4.0中文版API

    EXTJS4.0视频教程配套代码

    [02]EXTJS4.0的新特性.003.zip (14.41M)[02]EXTJS4.0的新特性.002.zip (50.00M)[02]EXTJS4.0的新特性.001.zip 第三讲:extjs4.0数据模型--Model(附件较大做了分包压缩大家只要下载2个包运行001就ok了) [03]EXTJS...

    ExtJS笔记---Grid实现后台分页

    这篇“ExtJS笔记——Grid实现后台分页”探讨了如何在ExtJS的Grid组件中实现高效的后台分页功能。 后台分页是一种常见的数据处理策略,特别是在大数据量的情况下,它将数据分批加载,避免一次性加载所有记录导致的...

    语言程序设计资料:ExtJs学习笔记-2积分.doc

    语言程序设计资料:ExtJs学习笔记-2积分.doc

    Extjs4.0基础学习指南

    一款很好的适合Extjs4.0初学者学习的word文档,示例加上简单的标注说明,使你很快对Extjs4.0进入入门阶段,不可多得的文档,值得下载

Global site tag (gtag.js) - Google Analytics