博客部分内容转载自 LonlySnow的博客:后台java 实现验证码生成

1、controller方法

@RequestMapping(value = "/verifycode/img", method = RequestMethod.GET)
@ApiOperation("generate image verification code")
public void generateImgVerificationCode(HttpServletRequest request, HttpServletResponse response) { try {
// int width = 200;
// int height = 69;
int width = 129;
int height = 40;
BufferedImage verifyImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 生成对应宽高的初始图片
// 生成验证码字符并加上噪点,干扰线,返回值为验证码字符
String randomText = UtilFunctions.drawRandomText(width, height, verifyImg); request.getSession().setAttribute("img_verify_code", randomText.toUpperCase());
request.getSession().setAttribute("img_verify_time", System.currentTimeMillis()); response.setContentType("image/png"); // 必须设置响应内容类型为图片,否则前台不识别
OutputStream os = response.getOutputStream(); // 获取文件输出流
ImageIO.write(verifyImg, "png", os); // 输出图片流 os.flush();
os.close();
} catch (Exception e) {
UtilFunctions.log.error("msg: {}, exception: {}", e.toString(), e);
UtilFunctions.reportError(e.toString(), e);
}
}

2、生成图片的方法

public static String drawRandomText(int width, int height, BufferedImage verifyImg) {

    Graphics2D graphics = (Graphics2D) verifyImg.getGraphics();
graphics.setColor(Color.WHITE);// 设置画笔颜色-验证码背景色
graphics.fillRect(0, 0, width, height);// 填充背景
// graphics.setFont(new Font("微软雅黑", Font.BOLD, 40));
graphics.setFont(new Font("微软雅黑", Font.BOLD, 30)); // 数字和字母的组合
//String baseNumLetter = "123456789abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
//String baseNumLetter = "2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY";
String baseNumLetter = "123456789";
StringBuffer sBuffer = new StringBuffer();
int x = 10; // 旋转原点的 x 坐标
String ch = ""; Random random = new Random();
Color textColor = getRandomColor();
for (int i = 0; i < 4; i++) {
// graphics.setColor(getRandomColor());
graphics.setColor(textColor);
// 设置字体旋转角度
int degree = random.nextInt() % 30; // 角度小于30度
int dot = random.nextInt(baseNumLetter.length());
ch = baseNumLetter.charAt(dot) + "";
sBuffer.append(ch);
// 正向旋转
graphics.rotate(degree * Math.PI / 180, x, 45);
//graphics.drawString(ch, x, 45);
graphics.drawString(ch, x, 30);
// 反向旋转
graphics.rotate(-degree * Math.PI / 180, x, 45);
//x += 48;
x += 30;
} // 画干扰线
for (int i = 0; i < 6; i++) {
// 设置随机颜色
graphics.setColor(getRandomColor());
// 随机画线
graphics.drawLine(random.nextInt(width), random.nextInt(height), random.nextInt(width),
random.nextInt(height));
} // 添加噪点
// for (int i = 0; i < 30; i++) {
// int x1 = random.nextInt(width);
// int y1 = random.nextInt(height);
// graphics.setColor(getRandomColor());
// graphics.fillRect(x1, y1, 2, 2);
// }
return sBuffer.toString();
} private static Color getRandomColor() {
Random ran = new Random();
Color color = new Color(ran.nextInt(256), ran.nextInt(256), ran.nextInt(256));
return color;
}

 

3、效果

==========================================================

4、 使用java来画图的api

// 得到图片缓冲区
BufferedImage bi = new BufferedImage(150, 70, BufferedImage.TYPE_INT_RGB);
// 得到它的绘制环境(画图的笔)
Graphics2D g2 = (Graphics2D) bi.getGraphics(); g2.setColor(Color.WHITE);// 设置画笔颜色,即后面背景色为白色
g2.fillRect(0, 0, 150, 70);// 填充整张图片(其实就是设置背景色) g2.setColor(Color.BLUE);// 设置画笔颜色,即后面边框颜色为蓝色
g2.drawRect(0, 0, 150 - 1, 70 - 1);// 设置边框 g2.setFont(new Font("宋体", Font.BOLD, 18));// 设置字体名称、样式、字号
g2.setColor(Color.BLACK);// 设置画笔颜色,即后面字符串颜色为黑色
g2.drawString("HelloWorld", 20, 40);// 设置字符"H"左下角坐标,向图片上写字符串 ImageIO.write(bi, "JPEG", new FileOutputStream("D:/a.jpg"));// 保存图片

5、生成验证码图片的工具类VerifyCode

package com.oy.demo;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random; import javax.imageio.ImageIO; public class VerifyCode {
private int w = 70;
private int h = 35;
private Random r = new Random();
// {"宋体", "华文楷体", "黑体", "华文新魏", "华文隶书", "微软雅黑", "楷体_GB2312"}
private String[] fontNames = {"宋体", "华文楷体", "黑体", "微软雅黑", "楷体_GB2312"};
//可选字符
private String codes = "23456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ";
//背景色
private Color bgColor = new Color(255, 255, 255);
private String text ; //生成随机的颜色
private Color randomColor () {
int red = r.nextInt(150);
int green = r.nextInt(150);
int blue = r.nextInt(150);
return new Color(red, green, blue);
} //生成随机字体
private Font randomFont () {
int index = r.nextInt(fontNames.length);
String fontName = fontNames[index];
int style = r.nextInt(4); //生成随机样式,0:无样式,1:粗体,2:斜体,3:粗体+斜体
int size = r.nextInt(5) + 24; //生成随机字号
return new Font(fontName, style, size);
} //画干扰线
private void drawLine (BufferedImage image) {
int num = 3; //总共画三条干扰线
Graphics2D g2 = (Graphics2D)image.getGraphics();
for(int i = 0; i < num; i++) { //生成两个点的左边,即4个值
int x1 = r.nextInt(w);
int y1 = r.nextInt(h);
int x2 = r.nextInt(w);
int y2 = r.nextInt(h);
g2.setStroke(new BasicStroke(1.5F));
g2.setColor(Color.BLUE); //设置干扰线颜色为蓝色
g2.drawLine(x1, y1, x2, y2);
}
} //随机生成一个字符
private char randomChar () {
int index = r.nextInt(codes.length());
return codes.charAt(index);
} //创建BufferedImage
private BufferedImage createImage () {
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = (Graphics2D)image.getGraphics();
g2.setColor(this.bgColor);
g2.fillRect(0, 0, w, h);
return image;
} public BufferedImage getImage () {
BufferedImage image = createImage(); //创建图片缓冲区
Graphics2D g2 = (Graphics2D)image.getGraphics();//得到绘制环境,画笔
StringBuilder sb = new StringBuilder();//用来装载生成的验证码文本
// 向图片中画4个字符
for(int i = 0; i < 4; i++) {
String s = randomChar() + ""; //随机生成一个字符
sb.append(s);
float x = i * 1.0F * w / 4; //设置当前字符的x轴坐标
g2.setFont(randomFont()); //设置随机字体
g2.setColor(randomColor()); //设置随机颜色
g2.drawString(s, x, h-5); //画图
}
this.text = sb.toString(); //把生成的字符串赋给this.text
drawLine(image); //添加干扰线
return image;
} //返回验证码图片上的文本
public String getText () {
return text;
} //保存图片到指定的输出流
public static void output (BufferedImage image, OutputStream out)
throws IOException {
ImageIO.write(image, "JPEG", out);
}
}

  VerifyCode的使用

@Test
public void fun() throws FileNotFoundException, IOException {
VerifyCode verifyCode = new VerifyCode();
BufferedImage bi = verifyCode.getImage();// 随机的
System.out.println(verifyCode.getText());// 打印图片上的文本内容
VerifyCode.output(bi, new FileOutputStream("d:/b.jpg"));
}

  创建一个Servlet:使用VerifyCode返回图片验证码

public class VerifyCodeServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*
* a、生成图片; b、保存图片上的文本到session域中; c、把图片响应给客户端。
*/
VerifyCode vc = new VerifyCode();
BufferedImage bi = vc.getImage(); // 生成图片
request.getSession().setAttribute("session_verifyCode", vc.getText()); // 保存图片上的文本到session域中
VerifyCode.output(bi, response.getOutputStream());// 把图片响应给客户端
}
}

  login.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>"> <title>My JSP 'login.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
--> </head> <body>
<h2>登录页面</h2> <%
/*
* 查找名为"uname"的Cookie,如果存在,将该Cookie的值赋给变量uname
*/
String uname="";
Cookie[] cs=request.getCookies(); //获取所有Cookie
if(null!=cs){ //如果存在Cookie
for(Cookie c:cs){ //遍历所有Cookie
if("uname".equals(c.getName())){ //查找名为"uname"的Cookie
uname=c.getValue(); //把名为"uname"的Cookie的值赋给变量uname
}
}
}
%> <!-- 显示登录错误信息 -->
<div style="color:red;">
<%
String msg=(String)request.getAttribute("msg");
if(null!=msg){
out.print(msg);
}
%>
</div> <%
String message_verifyCode="";
String msg_verifyCode=(String)request.getAttribute("msg_verifyCode");
if(null!=msg_verifyCode){
message_verifyCode=msg_verifyCode;
}
%> <!-- 如果存在名为"uname"的Cookie,将其该Cookie的值输出到用户名文本框 -->
<form action="/day11_2/LoginServlet" method="post">
用户名:<input type="text" name="username" value="<%=uname %>"/><br/>
密 码:<input type="password" name="password"/><br/>
验证码:<input type="text" size="4" name="verifyCode"/>
<img id="id_img" src="/day11_2/VerifyCodeServlet"/>
<a href="javascript:_change()">看不清,换一张</a>
<span style="color:red"><%= message_verifyCode %></span>
<br/>
<input type="submit" value="登录"/>
</form> </body> <script type="text/javascript">
function _change(){
//获取<img>元素对象
var imgEle=document.getElementById("id_img");
//给<img>元素的src属性赋值为"/day11_2/VerifyCodeServlet"
//"?a="+new Date().getTime()是为了防止浏览器缓存的影响
imgEle.src="/day11_2/VerifyCodeServlet?a="+new Date().getTime();
//alert(1);//用来测试代码 }
</script>
</html>

  效果:

java生成图片验证码(转)--封装生成图片验证码的工具类的更多相关文章

  1. jdbc 11: 封装自己的jdbc工具类

    jdbc连接mysql,封装自己的jdbc工具类 package com.examples.jdbc.utils; import java.sql.*; import java.util.Resour ...

  2. iOS开发拓展篇—封装音频文件播放工具类

    iOS开发拓展篇—封装音频文件播放工具类 一.简单说明 1.关于音乐播放的简单说明 (1)音乐播放用到一个叫做AVAudioPlayer的类 (2)AVAudioPlayer常用方法 加载音乐文件 - ...

  3. JBPM4入门——4.封装流程管理的工具类(JbpmUtil)

    本博文只是简要对JBPM4进行介绍,如需更详细内容请自行google 链接: JBPM入门系列文章: JBPM4入门——1.jbpm简要介绍 JBPM4入门——2.在eclipse中安装绘制jbpm流 ...

  4. Redis进阶实践之九 独立封装的RedisClient客户端工具类(转载9)

    Redis进阶实践之九 独立封装的RedisClient客户端工具类 一.引言 今天开始有关Redis学习的第九篇文章了,以后肯定会大量系统使用Redis作为缓存介质,为了更好的更好的Redis,自己 ...

  5. Java并发(十六):并发工具类——Exchanger

    Exchanger(交换者)是一个用于线程间协作的工具类.Exchanger用于进行线程间的数据交换.它提供一个同步点,在这个同步点两个线程可以交换彼此的数据.这两个线程通过exchange方法交换数 ...

  6. Java并发(十五):并发工具类——信号量Semaphore

    先做总结: 1.Semaphore是什么? Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源. 把它比作是控制流量的红绿灯,比如XX马路要 ...

  7. Java并发(十四):并发工具类——CountDownLatch

    先做总结: 1.CountDownLatch 是什么? CountDownLatch 允许一个或多个线程等待其他线程(不一定是线程,某个操作)完成之后再执行. CountDownLatch的构造函数接 ...

  8. Java并发编程系列-(2) 线程的并发工具类

    2.线程的并发工具类 2.1 Fork-Join JDK 7中引入了fork-join框架,专门来解决计算密集型的任务.可以将一个大任务,拆分成若干个小任务,如下图所示: Fork-Join框架利用了 ...

  9. Java匹马行天下之JavaSE核心技术——工具类

    Java匹马行天之JavaSE核心技术——工具类 一.Object类 java.lang.ObjectObject类是所有类直接或间接的父类 常用的方法: toString():以字符串形式返回对象的 ...

  10. Java容器类Collection,List,Set,Map.,Iterator,Collections工具类,Arrays工具类,Comparable

    Java容器类Collection,List,Set,Map.,Iterator,Collections工具类,Arrays工具类,Comparable接口,泛型 Collection,List,Se ...

随机推荐

  1. 【ABAP系列】SAP 面试 ABAPer的一些感想

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP 面试 ABAPer的一些 ...

  2. HDU4372(第一类斯特林数)

    题意:N座高楼,高度均不同且为1~N中的数,从前向后看能看到F个,从后向前看能看到B个,问有多少种可能的排列数. 0 < N, F, B <= 2000 首先我们知道一个结论:n的环排列的 ...

  3. jeecg项目将workbook 的Excel流添加到zip压缩包里导出

    1.直接献出代码 Map<String,List<ConfidentialInformation>> typeMap = new HashMap<>(); try ...

  4. Java基础/时间日期格式

    Java时间日期格式转换 一.Date转String和String转Date 参考博客:https://www.cnblogs.com/sharpest/p/7879377.html public s ...

  5. django中的一对一的关系

    在django中一对一的关系其实就是在后面加上了unique=True 唯一的操作 源码就是这样的 其余的操作跟多对一的操作一样

  6. 扫描 + 注解完成bean的自动配置

    链接:https://pan.baidu.com/s/1W3TINXNnqpxmkIADOcJZCQ 提取码:fmt5 我们知道,我们一般是通过id或name调用getBean方法来从IOC容器中获取 ...

  7. 配置NAT

    NAT是将IP数据报文报头中的IP地址转换为另-一个IP地址的过程,主要用于实现内部网络(私有IP地址)访问外部网络(公有IP地址)的功能.NAT有3种类型:静态NAT.动态地址NAT以及网络地址端口 ...

  8. java版微信支付/查询/撤销

    最近公司接入微信刷卡支付,网上根本没见到很直接的教程(可能眼拙),一直摸滚打爬,加班加点才走通,忍不了必须写一写 微信 刷卡支付/查询/撤销... 必须要有公众号然后去申请,申请自己去看文档,这里主要 ...

  9. RBAC----基于角色的访问权限控制

    RBAC是什么? 基于角色的权限访问控制(Role-Based Access Control) 作为传统访问控制(自主访问.强制访问)的有前景的代替 受到了广泛的关注. 在RBAC中,权限与角色相关联 ...

  10. Android的Monkey和MonkeyRunner

    本文部分解释性语段摘自网络百科或其它BLOG,语句内容网络随处可见,也不知道谁是初始原创,便不再署名出处,如有雷同,还请见谅. Monkey 什么是Monkey Monkey是Android中的一个命 ...