实现验证码功能

//生成验证码的类

publicclass SecurityCode {

     /**

     *验证码难度级别,Simple只包含数字,Medium包含数字和小写英文,Hard包含数字和大小写英文

     */

    publicenum SecurityCodeLevel {Simple,Medium,Hard};

   

    /**

     *产生默认验证码,4位高级难度

     *@return  String验证码

     */

    publicstatic StringgetSecurityCode(Map<String, Object> session){

    StringsecurityCode=getSecurityCode(4,SecurityCodeLevel.Hard,false);

    session.put("securityCode",securityCode);

        return securityCode;

    }

   

    /**

     *产生长度和难度任意的验证码

     *@paramlength  长度

     *@paramlevel   难度级别

     *@paramisCanRepeat  是否能够出现重复的字符,如果为true,则可能出现5578这样包含两个5,如果为false,则不可能出现这种情况

     *@return  String验证码

     */

    publicstatic String getSecurityCode(intlength,SecurityCodeLevel level,boolean isCanRepeat){

       

        //随机抽取len个字符

        int len=length;

       

        //字符集合(除去易混淆的数字0、数字1、字母l、字母o、字母O)

        char[] codes={'1','2','3','4','5','6','7','8','9',

                      'a','b','c','d','e','f','g','h','i',

                      'j','k','m','n','p','q','r','s','t',

                      'u','v','w','x','y','z','A','B','C',

                      'D','E','F','G','H','I','J','K','L',

                      'M','N','P','Q','R','S','T','U','V',

                      'W','X','Y','Z'};

        

        //根据不同的难度截取字符数组

        if(level==SecurityCodeLevel.Simple){

            codes=Arrays.copyOfRange(codes,0,9);

        }elseif(level==SecurityCodeLevel.Medium){

            codes=Arrays.copyOfRange(codes,0,33);

        }

       

        //字符集合长度

        int n=codes.length;

       

        //抛出运行时异常

        if(len>n&&isCanRepeat==false){

            thrownew RuntimeException(

                    String.format("调用SecurityCode.getSecurityCode(%1$s,%2$s,%3$s)出现异常," +

                                   "isCanRepeat%3$s时,传入参数%1$s不能大于%4$s",

                                  len,level,isCanRepeat,n));

        }

       

        //存放抽取出来的字符

        char[] result=newchar[len];

       

        //判断能否出现重复的字符

        if(isCanRepeat){

            for(int i=0;i<result.length;i++){

                //索引 0 and n-1

                int r=(int)(Math.random()*n);

           

                //result中的第i个元素设置为codes[r]存放的数值

                result[i]=codes[r];

            }

        }else{

            for(int i=0;i<result.length;i++){

                //索引 0 and n-1

                int r=(int)(Math.random()*n);

               

                //result中的第i个元素设置为codes[r]存放的数值

                result[i]=codes[r];

               

                //必须确保不会再次抽取到那个字符,因为所有抽取的字符必须不相同。

                //因此,这里用数组中的最后一个字符改写codes[r],并将n1

                codes[r]=codes[n-1];

                n--;

            }

        }

       

        return String.valueOf(result);

    }

}

//生成验证码图片类

publicclass SecurityImage {

    

     /**

      *生成验证码图片

      *@paramsecurityCode   验证码字符

      *@return  BufferedImage  图片

      */

     publicstatic BufferedImagecreateImage(String securityCode){

        

         //验证码长度

         int codeLength=securityCode.length();

         //字体大小

         int fSize = 15;

         int fWidth = fSize + 1;

         //图片宽度

         int width = codeLength * fWidth + 6 ;

         //图片高度

         int height = fSize * 2 + 1;

        

         //图片

         BufferedImage image=newBufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

         Graphics g=image.createGraphics();

        

         //设置背景色

         g.setColor(Color.WHITE);

         //填充背景

         g.fillRect(0, 0, width, height);

        

         //设置边框颜色

         g.setColor(Color.LIGHT_GRAY);

         //边框字体样式

         g.setFont(new Font("Arial", Font.BOLD, height - 2));

         //绘制边框

         g.drawRect(0, 0, width - 1, height-1);

        

        

         //绘制噪点

         Random rand = new Random();

         //设置噪点颜色

         g.setColor(Color.LIGHT_GRAY);

         for(int i = 0;i < codeLength * 6;i++){

             int x = rand.nextInt(width);

             int y = rand.nextInt(height);

             //绘制1*1大小的矩形

             g.drawRect(x, y, 1, 1);

         }

        

         //绘制验证码

         int codeY = height - 10; 

         //设置字体颜色和样式

         g.setColor(new Color(19,148,246));

         g.setFont(new Font("Georgia", Font.BOLD, fSize));

         for(int i = 0; i < codeLength;i++){

             g.drawString(String.valueOf(securityCode.charAt(i)),i * 16 + 5, codeY);

         }

         //关闭资源

         g.dispose();

        

         return image;

     }

    

     /**

      *返回验证码图片的流格式

      *@paramsecurityCode  验证码

      *@returnByteArrayInputStream图片流

      */

     publicstaticvoid getImageAsInputStream(HttpServletResponseresponse,String securityCode){

         try {

         //获取图片

         BufferedImage image = createImage(securityCode);

         //禁止图片缓存

         response.setHeader("Pragma", "no-cache");  

         response.setHeader("Cache-Control", "no-cache");  

         response.setDateHeader("Expires", 0);

         response.setContentType("image/jpeg");

         ServletOutputStreamstream=response.getOutputStream();

         //将图像输出到Servlet输出流中

           ImageIO.write(image, "JPG", stream);

           stream.close();

       } catch (IOException e) {

           // TODO Auto-generatedcatch block

           e.printStackTrace();

       }

     }

    

 }

 

//Action调用方法

// 获取验证码图片

public String getSecurityCodeImage() {

       // 获取默认难度和长度的验证码

       String securityCode = SecurityCode.getSecurityCode(getSession());

       // 写出图片到页面

       SecurityImage.getImageAsInputStream(getResponse(), securityCode);

    returnnull

}

//因为返回一个图片流所以return null 不用返回视图前端是img控件的src调用  此处需特别注意方法内不能使用session保存数据不然会抛出异常java.lang.IllegalStateException

该异常表示,当前对客户端的响应已经结束,不能在响应已经结束(或说消亡)后再向客户端(实际上是缓冲区)输出任何内容。

response是服务端对客户端请求的一个响应,其中封装了响应头、状态码、内容等服务端在把response提交到客户端之前,会向缓冲区内写入响应头和状态码,然后将所有内容flush。这就标志着该次响应已经committed(提交)。对于当前页面中已经committed(提交)的response,就不能再使用这个response向缓冲区写任何东西(注:同一个页面中的response.XXX()是同一个response的不同方法,只要其中一个已经导致了committed,那么其它类似方式的调用都会导致 IllegalStateException异常)。

我这里的具体原因大概是由于我用session提交了保存了数据后再用response输出图片流到页面。其他情况出现这个异常 大致按照这个思路解决就好

 

页面调用代码:

<imgid="imgObj" alt="换一张" src="test!getSecurityCodeImage.action"οnclick="changeImg()"></img>(struts2的调用方式)

Js代码:

function changeImg() {

 var imgSrc =document.getElementById("imgObj"); 

      imgSrc.src=imgSrc.src+"?temp="+Math.random()

      }

//比较懒 没花多大心思写这个js  大概意思是在src最后+?+无用参数=随机值

表示src变了能实现点击变换验证码(我这个是一直加下去?后有N个?号)问题不大

类似test!getSecurityCodeImage.action?temp=0.51564654654?temp=0.5156462352353

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值