使用纯Servlet实现验证码

(1)在web.xml配置:
view plaincopy to clipboardprint?
<servlet>     
    <servlet-name>image</servlet-name>     
    <servlet-class>org.test.web.AuthImage</servlet-class>     
</servlet>     
    
<servlet-mapping>     
    <servlet-name>image</servlet-name>     
 <url-pattern>/authImage</url-pattern>     
</servlet-mapping>   
<servlet>  
    <servlet-name>image</servlet-name>  
    <servlet-class>org.test.web.AuthImage</servlet-class>  
</servlet>  
 
<servlet-mapping>  
    <servlet-name>image</servlet-name>  
 <url-pattern>/authImage</url-pattern>  
</servlet-mapping>  

(2)servlet源码

view plaincopy to clipboardprint?
public class AuthImage extends HttpServlet     
{     
    
    private static final String CONTENT_TYPE = "text/html; charset=gb2312";     
    //设置字母的大小,大小     
    private Font mFont = new Font("Times New Roman", Font.PLAIN, 17);     
    public void init() throws ServletException     
    {     
        super.init();     
    }     
    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);     
    }     
    
    public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException     
    {     
        response.setHeader("Pragma","No-cache");     
        response.setHeader("Cache-Control","no-cache");     
        response.setDateHeader("Expires", 0);     
        //表明生成的响应是图片     
        response.setContentType("image/jpeg");     
             
        int width=100, height=18;     
        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(1, 1, width-1, height-1);     
        g.setColor(new Color(102,102,102));     
        g.drawRect(0, 0, width-1, height-1);     
        g.setFont(mFont);     
    
        g.setColor(getRandColor(160,200));     
    
        //画随机线     
        for (int i=0;i<155;i++)     
        {     
            int x = random.nextInt(width - 1);     
            int y = random.nextInt(height - 1);     
            int xl = random.nextInt(6) + 1;     
            int yl = random.nextInt(12) + 1;     
            g.drawLine(x,y,x + xl,y + yl);     
        }     
    
        //从另一方向画随机线     
        for (int i = 0;i < 70;i++)     
        {     
            int x = random.nextInt(width - 1);     
            int y = random.nextInt(height - 1);     
            int xl = random.nextInt(12) + 1;     
            int yl = random.nextInt(6) + 1;     
            g.drawLine(x,y,x - xl,y - yl);     
        }     
    
        //生成随机数,并将随机数字转换为字母     
        String sRand="";     
        for (int i=0;i<6;i++)     
        {     
            int itmp = random.nextInt(26) + 65;     
            char ctmp = (char)itmp;     
            sRand += String.valueOf(ctmp);     
            g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));     
            g.drawString(String.valueOf(ctmp),15*i+10,16);     
        }     
    
        HttpSession session = request.getSession(true);     
        session.setAttribute("rand",sRand);     
        g.dispose();     
        ImageIO.write(image, "JPEG", response.getOutputStream());     
    }     
    public void destroy()     
    {     
    }     
}   
public class AuthImage extends HttpServlet  
{  
 
    private static final String CONTENT_TYPE = "text/html; charset=gb2312";  
    //设置字母的大小,大小  
    private Font mFont = new Font("Times New Roman", Font.PLAIN, 17);  
    public void init() throws ServletException  
    {  
        super.init();  
    }  
    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);  
    }  
 
    public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException  
    {  
        response.setHeader("Pragma","No-cache");  
        response.setHeader("Cache-Control","no-cache");  
        response.setDateHeader("Expires", 0);  
        //表明生成的响应是图片  
        response.setContentType("image/jpeg");  
          
        int width=100, height=18;  
        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(1, 1, width-1, height-1);  
        g.setColor(new Color(102,102,102));  
        g.drawRect(0, 0, width-1, height-1);  
        g.setFont(mFont);  
 
        g.setColor(getRandColor(160,200));  
 
        //画随机线  
        for (int i=0;i<155;i++)  
        {  
            int x = random.nextInt(width - 1);  
            int y = random.nextInt(height - 1);  
            int xl = random.nextInt(6) + 1;  
            int yl = random.nextInt(12) + 1;  
            g.drawLine(x,y,x + xl,y + yl);  
        }  
 
        //从另一方向画随机线  
        for (int i = 0;i < 70;i++)  
        {  
            int x = random.nextInt(width - 1);  
            int y = random.nextInt(height - 1);  
            int xl = random.nextInt(12) + 1;  
            int yl = random.nextInt(6) + 1;  
            g.drawLine(x,y,x - xl,y - yl);  
        }  
 
        //生成随机数,并将随机数字转换为字母  
        String sRand="";  
        for (int i=0;i<6;i++)  
        {  
            int itmp = random.nextInt(26) + 65;  
            char ctmp = (char)itmp;  
            sRand += String.valueOf(ctmp);  
            g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));  
            g.drawString(String.valueOf(ctmp),15*i+10,16);  
        }  
 
        HttpSession session = request.getSession(true);  
        session.setAttribute("rand",sRand);  
        g.dispose();  
        ImageIO.write(image, "JPEG", response.getOutputStream());  
    }  
    public void destroy()  
    {  
    }  
}  

(3)页面显示

view plaincopy to clipboardprint?
<img src="authImage"/>  
<img src="authImage"/> 

二、使用纯jsp实现验证码

view plaincopy to clipboardprint?
<%@ page language="java" import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*"   
     contentType="image/jpeg" pageEncoding="UTF-8"%>  
 
 
<%  //设置页面不缓存  
   response.setHeader("Pragma","No-cache");  
   response.setHeader("Cahce-Control","no-cache");  
   response.setDateHeader("Expires",0);  
   //在内存中创建图片  
   int width=60,height=20;  
   BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);  
   //获取图形上下文  
   Graphics g= image.getGraphics();  
   //生成随机类  
   Random random= new Random();  
   //设置背景颜色  
   g.setColor(new Color(160,200,100));  
   g.fillRect(0,0,width,height);  
   //设置字体  
   g.setFont(new Font("Times New Roman",Font.PLAIN,18));  
   //随机产生50条干扰线,使图形中的验证码不易被其他的程序探测到  
    g.setColor(new Color(160,200,200));  
   for(int i=0;i<50;i++)  
   {  
     int x=random.nextInt(width);  
     int y=random.nextInt(height);  
     int x1=random.nextInt(width);  
     int y1=random.nextInt(height);  
     g.drawLine(x,y,x+x1,y+y1);  
   }  
   //随机产生验证码(6位数字)  
   String sRand="";  
   for(int i=0;i<6;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);  
   }  
   session.setAttribute("rand",sRand);  //////将产生的验证码存储到sesson中  
   g.dispose();  
   ImageIO.write(image,"JPEG",response.getOutputStream());  
   out.clear(); //***********  
   out=pageContext.pushBody();//**********  
 %> 
<%@ page language="java" import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*"
     contentType="image/jpeg" pageEncoding="UTF-8"%>


<%  //设置页面不缓存
   response.setHeader("Pragma","No-cache");
   response.setHeader("Cahce-Control","no-cache");
   response.setDateHeader("Expires",0);
   //在内存中创建图片
   int width=60,height=20;
   BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
   //获取图形上下文
   Graphics g= image.getGraphics();
   //生成随机类
   Random random= new Random();
   //设置背景颜色
   g.setColor(new Color(160,200,100));
   g.fillRect(0,0,width,height);
   //设置字体
   g.setFont(new Font("Times New Roman",Font.PLAIN,18));
   //随机产生50条干扰线,使图形中的验证码不易被其他的程序探测到
    g.setColor(new Color(160,200,200));
   for(int i=0;i<50;i++)
   {
     int x=random.nextInt(width);
     int y=random.nextInt(height);
     int x1=random.nextInt(width);
     int y1=random.nextInt(height);
     g.drawLine(x,y,x+x1,y+y1);
   }
   //随机产生验证码(6位数字)
   String sRand="";
   for(int i=0;i<6;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);
   }
   session.setAttribute("rand",sRand);  //////将产生的验证码存储到sesson中
   g.dispose();
   ImageIO.write(image,"JPEG",response.getOutputStream());
   out.clear(); //***********
   out=pageContext.pushBody();//**********
 %>
 

三、使用Struts2来实现验证码

(1)定义一个生成验证码的工具类

view plaincopy to clipboardprint?
package com.cn.hospital.util;  
 
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=85, 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<6;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);      
    }     

package com.cn.hospital.util;

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=85, 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<6;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);   
 }  
}
 

(2)定义一个验证码输出的action

view plaincopy to clipboardprint?
package com.cn.hospital.action;  
 
import java.io.ByteArrayInputStream;  
import java.io.ByteArrayOutputStream;  
 
import org.springframework.context.annotation.Scope;  
import org.springframework.stereotype.Controller;  
 
import com.cn.hospital.util.RandomCharUtil;  
import com.cn.hospital.util.RandomNumUtil;  
import com.opensymphony.xwork2.ActionContext;  
import com.opensymphony.xwork2.ActionSupport;  
 
@Controller("utilAction")  
@Scope("prototype")  
public class UtilAction extends ActionSupport{  
      
    private static final long serialVersionUID = -7193209177116825032L;  
    private ByteArrayInputStream inputStream;   
      
    private int width;     
    private int height;     
    private int fontSize;     
    private int codeLength;   
    private int disturbType;  
      
    public String validNumGenerate() throws Exception{  
        RandomNumUtil rdnu=RandomNumUtil.Instance();      
        this.setInputStream(rdnu.getImage());//取得带有随机字符串的图片      
        ActionContext.getContext().getSession().put("random", rdnu.getString());//取得随机字符串放入HttpSession      
        return SUCCESS;      
    }   
      
      
    public void setInputStream(ByteArrayInputStream inputStream) {      
        this.inputStream = inputStream;      
    }     
      
    public ByteArrayInputStream getInputStream() {      
        return inputStream;      
    }  
      
 

package com.cn.hospital.action;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.cn.hospital.util.RandomCharUtil;
import com.cn.hospital.util.RandomNumUtil;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

@Controller("utilAction")
@Scope("prototype")
public class UtilAction extends ActionSupport{
 
 private static final long serialVersionUID = -7193209177116825032L;
 private ByteArrayInputStream inputStream;
 
 private int width;  
    private int height;  
    private int fontSize;  
    private int codeLength;
    private int disturbType;
 
 public String validNumGenerate() throws Exception{
  RandomNumUtil rdnu=RandomNumUtil.Instance();   
  this.setInputStream(rdnu.getImage());//取得带有随机字符串的图片   
  ActionContext.getContext().getSession().put("random", rdnu.getString());//取得随机字符串放入HttpSession   
  return SUCCESS;   
 }
 
 
 public void setInputStream(ByteArrayInputStream inputStream) {   
  this.inputStream = inputStream;   
 }  
 
 public ByteArrayInputStream getInputStream() {   
  return inputStream;   
 }
 

}
 

(3)struts.xml配置

view plaincopy to clipboardprint?
<!-- 产生随机验证码 -->  
        <action name="randNum" class="utilAction" method="validNumGenerate">        
           <result name="success" type="stream">        
                <param name="contentType">image/jpeg</param>        
                <param name="inputName">inputStream</param>        
           </result>     
        </action>  
<!-- 产生随机验证码 -->
  <action name="randNum" class="utilAction" method="validNumGenerate">     
        <result name="success" type="stream">     
             <param name="contentType">image/jpeg</param>     
             <param name="inputName">inputStream</param>     
        </result>  
     </action> 

四、小结

    对于java的web技术,归根究底还是在服务器端执行的servlet.从上面的三种不同实现中,我们很容易察觉到他们存在一个共同点,那就是返回浏览器端的contentType。

    servlet:使用response.setContentType(" ");方法来实现

    jsp:在<@ page contentType=" ">中来实现

    struts2:通过配置<param name="contentType"> </param>来实现

原文地址:https://www.cnblogs.com/rongxiang/p/2351294.html