import java.awt.Color;  
    import java.awt.Font;  
    import java.awt.Graphics2D;  
    import java.awt.RenderingHints;  
    import java.awt.image.BufferedImage;  
    import java.util.Random;  
      
    import org.apache.commons.lang3.StringUtils;  
      
    /** 
     * 图片验证码类 
     */  
    public 
class Captcha {  
        private int width = 100;  
        private int height = 30;  
        private Random random = new Random();  
        private BufferedImage image;  
        /** 验证码图片上显示的字符 */  
        private String code;  
        /** 波形的幅度倍数,越大扭曲的程序越高,一般为3 */  
        private int twistLevel = 2;  
        /** 干扰线数量 */  
        private int noiseLineNumber = 3;  
        /** 背景色 */  
        private Color backgroundColor = Color.WHITE;  
        /** 字体颜色 */  
        // private Color foregroundColor = Color.BLACK;  
        private Color[] colors = { Color.BLUE, Color.RED, Color.GREEN, Color.BLACK, Color.CYAN, Color.MAGENTA };  
      
        private Color getRandomColor() {  
            return colors[random.nextInt(colors.length)];  
        }  
      
        /** 
         * @param width 
         *            - 验证码图片宽度 
         * @param height 
         *            - 验证码图片高度 
         * @param randomStr 
         *            - 随机字符串 
         * @return 
         */  
        public Captcha generate(int width, int height, String randomStr) {  
            this.width = width;  
            this.height = height;  
            this.code = randomStr;  
            if (StringUtils.isBlank(code)) {  
                throw new RuntimeException("randomStr 
can not be empty.");  
            }  
            int xWidth = width / (code.length() + 2);  
            int yIndex = height - 4;  
            Graphics2D graphics = graphicsInit();  
            for (int i = 0; i < code.length(); i++) {  
                // graphics.setColor(foregroundColor);  
                graphics.setColor(getRandomColor());  
                graphics.setRenderingHint(RenderingHints.
KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);  
                graphics.drawString(code.charAt(i) + "", (i + 1) * xWidth, yIndex);  
            }  
            setBuffImg(disturb());  
            return this;  
        }  
      
        private Graphics2D graphicsInit() {  
            Graphics2D graphics = buffImgInit().createGraphics();  
            graphics.setColor(backgroundColor);  
            graphics.fillRect(0, 0, width, height);  
            graphics.setFont(new Font("Fixedsys", Font.ITALIC, height - 2));  
            graphics.drawRect(0, 0, width - 1, height - 1);  
            return graphics;  
        }  
      
        private BufferedImage buffImgInit() {  
            image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);  
            return image;  
        }  
      
        private BufferedImage disturb() {  
            drawNoiseLine(image.createGraphics());  
            return twistImage();  
        }  
      
        private void drawNoiseLine(Graphics2D graphics) {  
            int x = 0;  
            int y = 0;  
            int xl = 0;  
            int yl = 0;  
            for (int i = 0; i < noiseLineNumber; i++) {  
                x = random.nextInt(width * 2 / 3);  
                y = random.nextInt(height * 2 / 3);  
                xl = random.nextInt(width / 2);  
                yl = random.nextInt(height / 2);  
                // graphics.setColor(foregroundColor);  
                graphics.setColor(getRandomColor());  
                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);  
                graphics.drawLine(x, y, x + xl, y + yl);  
            }  
        }  
      
        private BufferedImage twistImage() {  
            double dMultValue = random.nextInt(9) + twistLevel;  
            double dP
hase = random.nextInt(6);// 波形的起始相位,取值区间(0-2*PI)  
            BufferedImage destBi = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);  
            Graphics2D graphics = destBi.createGraphics();  
            graphics.setColor(backgroundColor);  
            graphics.fillRect(0, 0, width, height);  
            for (int i = 0; i < destBi.getWidth(); i++) {  
                for (int j = 0; j < destBi.getHeight(); j++) {  
                    int nOldX = getXPosition4Twist(dPhase, dMultValue, destBi.getHeight(), i, j);  
                    int nOldY = j;  
                    if (nOldX >= 0 && nOldX < destBi.getWidth() && nOldY >= 0 && nOldY < destBi.getHeight()) {  
                        destBi.setRGB(nOldX, nOldY, image.getRGB(i, j));  
                    }  
                }  
            }  
            return destBi;  
        }  
      
        private int getXPosition4Twist(double dPhase, double dMultValue, int height, int xPosition, int yPosition) {  
            double PI = Math.PI; // 此值越大,扭曲程度越大  
            double dx = (double) (PI * yPosition) / height + dPhase;  
            double dy = Math.sin(dx);  
            return xPosition + (int) (dy * dMultValue);  
        }  
      
        public BufferedImage getImage() {  
            return image;  
        }  
      
        public void setBuffImg(BufferedImage buffImg) {  
            this.image = buffImg;  
        }  
      
        public int getWidth() {  
            return width;  
        }  
      
        public void setWidth(int width) {  
            this.width = width;  
        }  
      
        public int getHeight() {  
            return height;  
        }  
      
        public void setHeight(int height) {  
            this.height = height;  
        }  
      
    }  
使用示例:
Java代码  收藏代码
    String randomStr = RandomStringUtils.randomAlphabetic(4).toLowerCase();  
    request.getSession().setAttribute(KEY_CAPTCHA, randomStr);  
    BufferedImage bi = new Captcha().generate(200, 50, randomStr).getImage();  
    ByteArrayOutputStream bos = new ByteArrayOutputStream();  
    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bos);  
    encoder.encode(bi);  
    ImageIO.write(bi, "JPEG", response.getOutputStream());