java 图片验证码_Java服务端写验证码图片到前端

这篇博客介绍了如何在Java服务端生成验证码图片,并将其显示在前端注册页面上。通过ImageCodeServlet类生成随机验证码并保存到session,然后利用VerifyCodeUtils工具类绘制包含干扰线和渐变色的图片,最后前端通过js代码实现刷新验证码功能。
摘要由CSDN通过智能技术生成

1. 先看前端页面的验证码图片与html代码:/register.jsp

46c6faf91dd12fa3879be397930b612a.png

注册校验

输入校验码: 
 

imageCode  

看不清换一张

2. 根据上面代码可以看到验证码图片的src地址指向了一个名为"imageCode"的Servlet。此Servlet代码如下:ImageCodeServlet.java

@SuppressWarnings("serial")

@WebServlet("/imageCode")

public class ImageCodeServlet extends HttpServlet {

public void doGet(HttpServletRequest req, HttpServletResponse res)

throws ServletException, IOException {

//req.setCharacterEncoding("utf-8");

//res.setContentType("text/html;charset=utf-8");

// 设置http响应的文件MIME类型为图片

res.setContentType("image/jpeg");

// 不让浏览器记录此图片的缓存

res.setDateHeader("expries", -1);

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

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

// 这里调用了一个工具类VerifyCodeUtils来生成指定位数(也可指定内容)的验证码字符串

String verifyCode = VerifyCodeUtils.generateVerifyCode(5);

// 将生成验证码字符串保存到session域中,方面进行表单验证

req.getSession().setAttribute("verifyCode", verifyCode);

// 生成图片并写到响应输出流里. 因为register.jsp页面里的验证码图片宽高分别为180,30.这里使保持一致

VerifyCodeUtils.outputImage(180, 30, res.getOutputStream(), verifyCode);

}

public void doPost(HttpServletRequest req, HttpServletResponse res)

throws ServletException, IOException {

doGet(req, res);

}

}

3. 生成验证码图片的工具类--VerifyUtils.java

import java.awt.Color;

import java.awt.Font;

import java.awt.Graphics2D;

import java.awt.LinearGradientPaint;

import java.awt.Paint;

import java.awt.geom.AffineTransform;

import java.awt.image.BufferedImage;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.OutputStream;

import java.util.Arrays;

import java.util.Random;

import javax.imageio.ImageIO;

public class VerifyCodeUtils{

// 可自定义验证码字符源

public static final String VERIFY_CODES = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

/**

* 使用系统默认字符源生成验证码

* @param verifySize 验证码长度

* @return

*/

public static String generateVerifyCode(int verifySize){

return generateVerifyCode(verifySize, VERIFY_CODES);

}

/**

* 使用指定源生成验证码

* @param verifySize 验证码长度

* @param sources 验证码字符源

* @return

*/

public static String generateVerifyCode(int verifySize, String sources){

if(sources == null || sources.length() == 0){

sources = VERIFY_CODES;

}

int codesLen = sources.length();

Random rand = new Random(System.currentTimeMillis());

StringBuilder verifyCode = new StringBuilder(verifySize);

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

verifyCode.append(sources.charAt(rand.nextInt(codesLen-1)));

}

return verifyCode.toString();

}

/**

* 生成随机验证码文件,并返回验证码值

* @param w 图片宽(像素)

* @param h 图片高(像素)

* @param outputFile

* @param verifySize

* @return

* @throws IOException

*/

public static String outputVerifyImage(int w, int h, File outputFile, int verifySize) throws IOException{

String verifyCode = generateVerifyCode(verifySize);

outputImage(w, h, outputFile, verifyCode);

return verifyCode;

}

/**

* 输出随机验证码图片流,并返回验证码值

* @param w

* @param h

* @param os

* @param verifySize

* @return

* @throws IOException

*/

public static String outputVerifyImage(int w, int h, OutputStream os, int verifySize) throws IOException{

String verifyCode = generateVerifyCode(verifySize);

outputImage(w, h, os, verifyCode);

return verifyCode;

}

/**

* 生成指定验证码图像文件

* @param w

* @param h

* @param outputFile

* @param code

* @throws IOException

*/

public static void outputImage(int w, int h, File outputFile, String code) throws IOException{

if(outputFile == null){

return;

}

File dir = outputFile.getParentFile();

if(!dir.exists()){

dir.mkdirs();

}

try{

outputFile.createNewFile();

FileOutputStream fos = new FileOutputStream(outputFile);

outputImage(w, h, fos, code);

fos.close();

} catch(IOException e){

throw e;

}

}

/**

* 输出指定验证码图片流

* @param w

* @param h

* @param os

* @param code

* @throws IOException

*/

public static void outputImage(int w,

int h,

OutputStream os,

String code) throws IOException{

int verifySize = code.length();

BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);

Random rand = new Random();

Graphics2D g2 = image.createGraphics();

Color[] colors = new Color[5];

Color[] colorSpaces = new Color[] { Color.WHITE, Color.CYAN,

Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,

Color.PINK, Color.YELLOW };

float[] fractions = new float[colors.length];

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

colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];

fractions[i] = rand.nextFloat();

}

Arrays.sort(fractions);

Paint linearPaint = new LinearGradientPaint(0, 0, w, h, fractions, colors);

Paint linearPaint2 = new LinearGradientPaint(0, 0, w, h, new float[]{0.3f, .6f, .8f, .9f}, new Color[]{Color.BLUE, Color.BLACK, Color.GREEN, Color.BLUE});

//设置图片背景为白色

g2.setPaint(Color.WHITE);

g2.fillRect(0, 0, w, h);

//设置图片渐变背景

g2.setPaint(linearPaint);

g2.fillRoundRect(0, 0, w, h, 5, 5);

g2.setPaint(linearPaint2);

int fontSize = (int) (Math.min(w/verifySize, h));

Font font = new Font("微软雅黑", Font.BOLD, fontSize);

g2.setFont(font);

char[] chars = code.toCharArray();

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

AffineTransform affine = new AffineTransform();

affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize/2, h/2);

g2.setTransform(affine);

g2.drawChars(chars, i, 1, (w / verifySize) * i, h/2 + fontSize /2);

}

g2.dispose();

ImageIO.write(image, "jpg", os);

}

public static void main(String[] args) throws IOException{

File dir = new File("F:/verifies");

int w = 200, h = 80;

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

String verifyCode = generateVerifyCode(4);

File file = new File(dir, verifyCode + ".jpg");

outputImage(w, h, file, verifyCode);

}

}

}

4. 实现点击"看不清楚,换一图片"功能的js代码:/register.jsp:

function changeImage() {

document.getElementById("img").src = "${pageContext.request.contextPath}/imageCode?time=" + new Date().getTime();

}

0d0b154da91a667f3d2e8008d08db1c8.gif

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值