上几篇文章,主要学习了 Extjs4 Grid 的使用方法,从本篇开始,我们开始其他组件的
学习,使用。在登录、注册甚至是发表文章或帖子的时候,都会用到验证码这个东西,那
么在 EXTJS 中,可以使用验证码功能么?答案是肯定的,在 EXTJS4 之前,也有很多验证
码的实现,在 Extjs4 中,验证码到底如何实现呢?
        暂时,我们将验证码组件,命名为 CheckCode。此组件继承自 Ext.form.field.Text,在
实现之前,我们需要写两个样式,分别用来控制验证码的输入框和验证码图片的大小。
CSS 样式为:
Css代码  收藏代码
    #CheckCode{ float:left;}  
    .x-form-code{width:73px;height:20px;vertical-align:middle;cursor:pointer; float:left; margin-left:7px;}  
         记住这两个样式的定义,后面,我们会用到它。
验证码的 JS 代码(CheckCode.js):
   
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({ 
                 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):
   
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):
   
Js代码  收藏代码
    Ext.application({ 
        name: 'SMS', 
            
        appFolder: 'app', 
            
        launch: function() { 
            requires: ['SMS.view.Login'] 
            var win; 
            win = Ext.create('SMS.view.Login').show(); 
        }    
            
    }); 
   
   
login.jsp:
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):
   
Java代码  收藏代码
    package org.changkong.sms.utils; 
        
    import java.awt.Color; 
    import java.awt.Font; 
    import java.awt.Graphics; 
    import java.awt.p_w_picpath.BufferedImage; 
    import java.io.ByteArrayInputStream; 
    import java.io.ByteArrayOutputStream; 
    import java.util.Random; 
        
    import javax.p_w_picpathio.ImageIO; 
    import javax.p_w_picpathio.stream.ImageOutputStream; 
        
    /**
     * 生成验证码的类文件
     * 
     */ 
    public class RandomNumUtil { 
        private ByteArrayInputStream p_w_picpath;     //图像 
        private String str;     //验证码 
        
        private RandomNumUtil() { 
            init();     //初始化属性 
        } 
        
        /*
         * 取得RandomNumUtil实例
         */ 
        public static RandomNumUtil Instance() { 
            return new RandomNumUtil(); 
        } 
        
        /*
         * 取得验证码图片
         */ 
        public ByteArrayInputStream getImage() { 
            return this.p_w_picpath; 
        } 
        
        /*
         * 取得图片的验证码
         */ 
        public String getString() { 
            return this.str; 
        } 
        
        private void init() { 
            //在内存中创建图象 
            //图像的高度和宽度 
            int width = 55, height = 20; 
            BufferedImage p_w_picpath = new BufferedImage(width, height, 
                    BufferedImage.TYPE_INT_RGB); 
            //获取图形上下文 
            Graphics g = p_w_picpath.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 p_w_picpathOut = ImageIO 
                        .createImageOutputStream(output); 
                ImageIO.write(p_w_picpath, "JPEG", p_w_picpathOut); 
                p_w_picpathOut.close(); 
                input = new ByteArrayInputStream(output.toByteArray()); 
            } catch (Exception e) { 
                System.out.println("验证码图片产生出现错误:" + e.toString()); 
            } 
            this.p_w_picpath = 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):
   
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):
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:
   
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">p_w_picpath/jpeg</param>      
                    <param name="inputName">inputStream</param>      
                </result>   
            </action>