JAVA项目实战-生成二维码和验证码功能
本节将分享java生成二维码和验证码功能,希望能帮助你!
package com.sf.vsolution.hb.sfce.util.verifycode; import javax.imageio.ImageIO; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; /** * 验证码生成工具 */ public class VerifyCodeUtil { /** * 验证码类型为仅数字,即0~9 */ public static final int TYPE_NUM_ONLY = 0; /** * 验证码类型为仅字母,即大小写字母混合 */ public static final int TYPE_LETTER_ONLY = 1; /** * 验证码类型为数字和大小写字母混合 */ public static final int TYPE_ALL_MIXED = 2; /** * 验证码类型为数字和大写字母混合 */ public static final int TYPE_NUM_UPPER = 3; /** * 验证码类型为数字和小写字母混合 */ public static final int TYPE_NUM_LOWER = 4; /** * 验证码类型为仅大写字母 */ public static final int TYPE_UPPER_ONLY = 5; /** * 验证码类型为仅小写字母 */ public static final int TYPE_LOWER_ONLY = 6; private VerifyCodeUtil(){} /** * 生成验证码 * @param request * @param response * @throws IOException */ public void getVerifyCodeImage(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession session = request.getSession(); response.setHeader("Pragma", "no-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); String verifyCode = generateTextCode(VerifyCodeUtil.TYPE_NUM_LOWER, 4, null); response.setContentType("image/jpeg"); BufferedImage bufferedImage =generateImageCode(verifyCode, 90, 30, 3, true, Color.WHITE, Color.BLACK, null); ImageIO.write(bufferedImage, "jpeg", response.getOutputStream()); } /** * 生成验证码字符串 * @param type 验证码类型,参见本类的静态属 * @param length 验证码长度,要求大于0的整数 * @param excludeString 需排除的特殊字符(无需排除则为null) * @return 验证码字符串 */ public static String generateTextCode(int type, int length, String excludeString){ if(length <= 0){ return ""; } StringBuffer verifyCode = new StringBuffer(); int i = 0; Random random = new Random(); switch(type){ case TYPE_NUM_ONLY: while(i < length){ int t = random.nextInt(10); //排除特殊字符 if(null==excludeString || excludeString.indexOf(t+"")<0) { verifyCode.append(t); i++; } } break; case TYPE_LETTER_ONLY: while(i < length){ int t = random.nextInt(123); if((t>=97 || (t>=65&&t<=90)) && (null==excludeString||excludeString.indexOf((char)t)<0)){ verifyCode.append((char)t); i++; } } break; case TYPE_ALL_MIXED: while(i < length){ int t = random.nextInt(123); if((t>=97 || (t>=65&&t<=90) || (t>=48&&t<=57)) && (null==excludeString||excludeString.indexOf((char)t)<0)){ verifyCode.append((char)t); i++; } } break; case TYPE_NUM_UPPER: while(i < length){ int t = random.nextInt(91); if((t>=65 || (t>=48&&t<=57)) && (null==excludeString || excludeString.indexOf((char)t)<0)){ verifyCode.append((char)t); i++; } } break; case TYPE_NUM_LOWER: while(i < length){ int t = random.nextInt(123); if((t>=97 || (t>=48&&t<=57)) && (null==excludeString || excludeString.indexOf((char)t)<0)){ verifyCode.append((char)t); i++; } } break; case TYPE_UPPER_ONLY: while(i < length){ int t = random.nextInt(91); if((t >= 65) && (null==excludeString||excludeString.indexOf((char)t)<0)){ verifyCode.append((char)t); i++; } } break; case TYPE_LOWER_ONLY: while(i < length){ int t = random.nextInt(123); if((t>=97) && (null==excludeString||excludeString.indexOf((char)t)<0)){ verifyCode.append((char)t); i++; } } break; } return verifyCode.toString(); } /** * 已有验证码,生成验证码图片 * @param textCode 文本验证码 * @param width 图片宽度(注意此宽度若过小,容易造成验证码文本显示不全,如4个字符的文本可使用85到90的宽度) * @param height 图片高度 * @param interLine 图片中干扰线的条数 * @param randomLocation 每个字符的高低位置是否随机 * @param backColor 图片颜色,若为null则表示采用随机颜色 * @param foreColor 字体颜色,若为null则表示采用随机颜色 * @param lineColor 干扰线颜色,若为null则表示采用随机颜色 * @return 图片缓存对象 */ public static BufferedImage generateImageCode(String textCode, int width, int height, int interLine, boolean randomLocation, Color backColor, Color foreColor, Color lineColor){ //创建内存图像 BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); //获取图形上下文 Graphics graphics = bufferedImage.getGraphics(); //画背景图 graphics.setColor(null==backColor ? generateRandomColor() : backColor); graphics.fillRect(0, 0, width, height); //画干扰线 Random random = new Random(); if(interLine > 0){ int x = 0, y = 0, x1 = width, y1 = 0; for(int i=0; i<interLine; i++){ graphics.setColor(null==lineColor ? generateRandomColor() : lineColor); y = random.nextInt(height); y1 = random.nextInt(height); graphics.drawLine(x, y, x1, y1); } } //字体大小为图片高度的80% int fsize = (int)(height * 0.8); int fx = height - fsize; int fy = fsize; //设定字体 graphics.setFont(new Font("Default", Font.PLAIN, fsize)); //写验证码字符 for(int i=0; i<textCode.length(); i++){ fy = randomLocation ? (int)((Math.random()*0.3+0.6)*height) : fy; graphics.setColor(null==foreColor ? generateRandomColor() : foreColor); //将验证码字符显示到图象中 graphics.drawString(textCode.charAt(i)+"", fx, fy); fx += fsize * 0.9; } graphics.dispose(); return bufferedImage; } /** * 生成随机颜色 */ private static Color generateRandomColor() { Random random = new Random(); return new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)); } }
package com.sf.vsolution.hb.sfce.util.qrcode; import cn.hutool.extra.qrcode.QrConfig; import org.apache.commons.io.FilenameUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.web.multipart.MultipartFile; import javax.imageio.ImageIO; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.awt.*; import java.awt.image.BufferedImage; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; /** * @ClassName QrCodeUtil * @Description * @Author 01374735 * @Date 2019/7/29 **/ public class QrCodeUtil { private static final Logger LOG = LogManager.getLogger(QrCodeUtil.class);
/** * 二维码LOG 位置(默认放在项目中) */ private static final String SFLOG = "/static/img/sflog.png"; /** * 二维码背景图片 位置(默认放在项目中) */ private static final String QRBG = "/static/img/qrbg.png"; /** * 文件导出 * @param response 相应头 * @param filePath 二维码图片地址 */ public static void exportImg(HttpServletResponse response, String filePath) { File file = new File(filePath); response.setCharacterEncoding("utf-8"); //设置响应的内容类型 response.setContentType("text/plain"); //设置文件的名称和格式 response.setHeader("content-type", "application/octet-stream"); response.setContentType("application/octet-stream"); response.addHeader("Content-Disposition", "attachment;filename=" + file.getName()); BufferedOutputStream buff = null; ServletOutputStream outStr = null; try { outStr = response.getOutputStream(); buff = new BufferedOutputStream(outStr); buff.write(cn.hutool.core.io.FileUtil.readBytes(filePath)); buff.flush(); buff.close(); } catch (Exception e) { e.printStackTrace(); LOG.error("文件导出异常:", e); } finally { try { buff.close(); } catch (Exception e) { LOG.error("流关闭异常:", e); } try { outStr.close(); } catch (Exception e) { LOG.error("流关闭异常:", e); } } } /** * 生成二维码地址 * * @param url 二维码跳转链接 * @param pathFolder 生成地址文件夹 * @param qrName 二维码名称 * @return */ public static String generateQrCode(String url, String pathFolder, String qrName) throws IOException { String log = QrCodeUtil.class.getResource(SFLOG).getPath(); String bg = QrCodeUtil.class.getResource(QRBG).getPath(); QrConfig config = new QrConfig(860, 860); //顺丰log config.setImg(log); // 生成二维码到文件,也可以到流 File path = new File(pathFolder); if (!path.exists()) { path.mkdirs(); } String qrFile = pathFolder + System.currentTimeMillis() + ".png"; cn.hutool.extra.qrcode.QrCodeUtil.generate(url, config, new File(qrFile)); //设置背景图片 BufferedImage exImage = ImageIO.read(new File(bg)); BufferedImage innerImage = ImageIO.read(new File(qrFile)); Graphics2D g2d = exImage.createGraphics(); // 在图形和图像中实现混合和透明效果 g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1)); // 绘制 g2d.drawImage(innerImage, 512, 930, 860, 860, null); g2d.dispose(); String hotelQr = pathFolder + qrName + ".png"; ImageIO.write(exImage, "png", new FileOutputStream(hotelQr)); return hotelQr; } /** * 校验图片格式 * @param file * @return */ public static boolean checkFileLayout(MultipartFile file ) { String checkFilename = file.getOriginalFilename(); String checkSuffix = FilenameUtils.getExtension(checkFilename); Collection collection= new ArrayList(); collection.add("png"); collection.add("jpeg"); collection.add("jpg"); return collection.contains(checkSuffix); } }
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <hutool.version>4.5.10</hutool.version> </dependency>
package com.sf.vsolution.hb.sfce.util.verifycode;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
/**
* 验证码生成工具
*/
public class VerifyCodeUtil {
/**
* 验证码类型为仅数字,即0~9
*/
public static final int TYPE_NUM_ONLY = 0;
/**
* 验证码类型为仅字母,即大小写字母混合
*/
public static final int TYPE_LETTER_ONLY = 1;
/**
* 验证码类型为数字和大小写字母混合
*/
public static final int TYPE_ALL_MIXED = 2;
/**
* 验证码类型为数字和大写字母混合
*/
public static final int TYPE_NUM_UPPER = 3;
/**
* 验证码类型为数字和小写字母混合
*/
public static final int TYPE_NUM_LOWER = 4;
/**
* 验证码类型为仅大写字母
*/
public static final int TYPE_UPPER_ONLY = 5;
/**
* 验证码类型为仅小写字母
*/
public static final int TYPE_LOWER_ONLY = 6;
private VerifyCodeUtil(){}
/**
* 生成验证码
* @param request
* @param response
* @throws IOException
*/
public void getVerifyCodeImage(HttpServletRequest request, HttpServletResponse response) throws IOException {
HttpSession session = request.getSession();
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
String verifyCode = generateTextCode(VerifyCodeUtil.TYPE_NUM_LOWER, 4, null);
response.setContentType("image/jpeg");
BufferedImage bufferedImage =generateImageCode(verifyCode, 90, 30, 3, true, Color.WHITE, Color.BLACK, null);
ImageIO.write(bufferedImage, "jpeg", response.getOutputStream());
}
/**
* 生成验证码字符串
* @param type 验证码类型,参见本类的静态属
* @param length 验证码长度,要求大于0的整数
* @param excludeString 需排除的特殊字符(无需排除则为null)
* @return 验证码字符串
*/
public static String generateTextCode(int type, int length, String excludeString){
if(length <= 0){
return "";
}
StringBuffer verifyCode = new StringBuffer();
int i = 0;
Random random = new Random();
switch(type){
case TYPE_NUM_ONLY:
while(i < length){
int t = random.nextInt(10);
//排除特殊字符
if(null==excludeString || excludeString.indexOf(t+"")<0) {
verifyCode.append(t);
i++;
}
}
break;
case TYPE_LETTER_ONLY:
while(i < length){
int t = random.nextInt(123);
if((t>=97 || (t>=65&&t<=90)) && (null==excludeString||excludeString.indexOf((char)t)<0)){
verifyCode.append((char)t);
i++;
}
}
break;
case TYPE_ALL_MIXED:
while(i < length){
int t = random.nextInt(123);
if((t>=97 || (t>=65&&t<=90) || (t>=48&&t<=57)) && (null==excludeString||excludeString.indexOf((char)t)<0)){
verifyCode.append((char)t);
i++;
}
}
break;
case TYPE_NUM_UPPER:
while(i < length){
int t = random.nextInt(91);
if((t>=65 || (t>=48&&t<=57)) && (null==excludeString || excludeString.indexOf((char)t)<0)){
verifyCode.append((char)t);
i++;
}
}
break;
case TYPE_NUM_LOWER:
while(i < length){
int t = random.nextInt(123);
if((t>=97 || (t>=48&&t<=57)) && (null==excludeString || excludeString.indexOf((char)t)<0)){
verifyCode.append((char)t);
i++;
}
}
break;
case TYPE_UPPER_ONLY:
while(i < length){
int t = random.nextInt(91);
if((t >= 65) && (null==excludeString||excludeString.indexOf((char)t)<0)){
verifyCode.append((char)t);
i++;
}
}
break;
case TYPE_LOWER_ONLY:
while(i < length){
int t = random.nextInt(123);
if((t>=97) && (null==excludeString||excludeString.indexOf((char)t)<0)){
verifyCode.append((char)t);
i++;
}
}
break;
}
return verifyCode.toString();
}
/**
* 已有验证码,生成验证码图片
* @param textCode 文本验证码
* @param width 图片宽度(注意此宽度若过小,容易造成验证码文本显示不全,如4个字符的文本可使用85到90的宽度)
* @param height 图片高度
* @param interLine 图片中干扰线的条数
* @param randomLocation 每个字符的高低位置是否随机
* @param backColor 图片颜色,若为null则表示采用随机颜色
* @param foreColor 字体颜色,若为null则表示采用随机颜色
* @param lineColor 干扰线颜色,若为null则表示采用随机颜色
* @return 图片缓存对象
*/
public static BufferedImage generateImageCode(String textCode, int width, int height, int interLine, boolean randomLocation, Color backColor, Color foreColor, Color lineColor){
//创建内存图像
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//获取图形上下文
Graphics graphics = bufferedImage.getGraphics();
//画背景图
graphics.setColor(null==backColor ? generateRandomColor() : backColor);
graphics.fillRect(0, 0, width, height);
//画干扰线
Random random = new Random();
if(interLine > 0){
int x = 0, y = 0, x1 = width, y1 = 0;
for(int i=0; i<interLine; i++){
graphics.setColor(null==lineColor ? generateRandomColor() : lineColor);
y = random.nextInt(height);
y1 = random.nextInt(height);
graphics.drawLine(x, y, x1, y1);
}
}
//字体大小为图片高度的80%
int fsize = (int)(height * 0.8);
int fx = height - fsize;
int fy = fsize;
//设定字体
graphics.setFont(new Font("Default", Font.PLAIN, fsize));
//写验证码字符
for(int i=0; i<textCode.length(); i++){
fy = randomLocation ? (int)((Math.random()*0.3+0.6)*height) : fy;
graphics.setColor(null==foreColor ? generateRandomColor() : foreColor);
//将验证码字符显示到图象中
graphics.drawString(textCode.charAt(i)+"", fx, fy);
fx += fsize * 0.9;
}
graphics.dispose();
return bufferedImage;
}
/**
* 生成随机颜色
*/
private static Color generateRandomColor() {
Random random = new Random();
return new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255));
}
}