使用Servlet生成验证码
如何使用Servlet生成验证码
在Java中我们可以在Web项目中使用Servlet来生成验证码,流程是:前端请求验证码servlet对应的地址,后端servlet收到请求,生成一串字符作为验证码,存入到Session中,最后将验证码作为一张图片返回给前端。前端填写了验证码提交到服务器来验证。
我们看一个示例,你也可以根据这个示例在右侧编辑器中一步一步实现验证码的功能。
项目和servlet已经创建好了,我们首先在web.xml文件中注册servlet。
步骤
在servlet的doGet()方法中编写代码实现生成图片验证码:
分为如下步骤:
- 定义图像数据缓冲区(BufferedImage);
- 创建图片对象;
- 创建绘制工具(Graphics);
- 生成随机数,存入到session中;
- 使用Graphics绘制图形;
- 将验证码通过图像输出流(ImageIO)输出到客户端;
- 最后输入验证码地址即可访问单验证码。
代码如下:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 使用验证码的步骤 // 定义图片的宽高 int height = 20; int width = 60; BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 绘图工具 Graphics graphics = image.getGraphics(); // 绘制矩形 graphics.setColor(getRandColor()); // 绘制矩形背景 前两个参数 是 x y的坐标 graphics.fillRect(0, 0, width, height); // 设置文字的颜色 为白色 graphics.setColor(Color.WHITE); String yzm = ""; // 生成四个随机数字并且画在图片上 for (int i = 1; i <= 4; i++) { // 生成随机数字并且显示到页面上 int number = new Random().nextInt(10); yzm += number; graphics.drawString(number + "", 10 * i, 10); } // 将验证码放入Httpsession中 HttpSession session = req.getSession(); session.setAttribute("sessionYzm", yzm); // 将验证码图片输出到客户端 ImageIO.write(image, "jpg", resp.getOutputStream()); } // 获取随机颜色 private Color getRandColor() { int red = new Random().nextInt(255); int green = new Random().nextInt(255); int blue = new Random().nextInt(255); return new Color(red, green, blue); }
效果如下:
验证码案例:
案例1:
效果
html
html中,没点击一次img 标签(即验证码图片)就会请求一次servlet得到一个响应,重新绘制验证码图案。
<div class="verify"> <input name="check" type="text" placeholder="请输入验证码" autocomplete="off"> <span><img src="checkCode" alt="" onclick="changeCheckCode(this)"></span> <script type="text/javascript"> //图片点击事件 function changeCheckCode(img) { img.src="checkCode?"+new Date().getTime(); // console.log (new Date().getTime()); // 时间戳 } </script> </div>
servlet
package cn.itcast.travel.web.servlet; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; /** * 验证码 */ @WebServlet("/checkCode") public class CheckCodeServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { //服务器通知浏览器不要缓存 response.setHeader("pragma","no-cache"); response.setHeader("cache-control","no-cache"); response.setHeader("expires","0"); //在内存中创建一个长80,宽30的图片,默认黑色背景 //参数一:长 //参数二:宽 //参数三:颜色 int width = 80; int height = 30; BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); //获取画笔 Graphics g = image.getGraphics(); //设置画笔颜色为灰色 g.setColor(Color.GRAY); //填充图片 g.fillRect(0,0, width,height); //产生4个随机验证码,12Ey String checkCode = getCheckCode(); //将验证码放入HttpSession中 request.getSession().setAttribute("CHECKCODE_SERVER",checkCode); //设置画笔颜色为黄色 g.setColor(Color.YELLOW); //设置字体的小大 g.setFont(new Font("黑体",Font.BOLD,24)); //向图片上写入验证码 g.drawString(checkCode,15,25); //将内存中的图片输出到浏览器 //参数一:图片对象 //参数二:图片的格式,如PNG,JPG,GIF //参数三:图片输出到哪里去 ImageIO.write(image,"PNG",response.getOutputStream()); } /** * 产生4位随机字符串 */ private String getCheckCode() { String base = "0123456789ABCDEFGabcdefg"; int size = base.length(); Random r = new Random(); StringBuffer sb = new StringBuffer(); for(int i=1;i<=4;i++){ //产生0到size-1的随机值 int index = r.nextInt(size); //在base字符串中获取下标为index的字符 char c = base.charAt(index); //将c放入到StringBuffer中去 sb.append(c); } return sb.toString(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request,response); } }
案例2:
效果
servlet
public class ResponseDemo3 extends HttpServlet { /** * 输出图片 * @param request * @param response * @throws ServletException * @throws IOException */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int width = 200; int height = 35; /** * 实现步骤: * 1.创建图像内存对象 * 2.拿到画笔 * 3.设置颜色,画矩形边框 * 4.设置颜色,填充矩形 * 5.设置颜色,画干扰线 * 6.设置颜色,画验证码 * 7.把内存图像输出到浏览器上 */ //创建内存图像 BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);//参数:宽度,高度 (指的都是像素),使用的格式(RGB) Graphics g = image.getGraphics();//画笔就一根 //设置颜色 g.setColor(Color.BLUE); //画边框 g.drawRect(0, 0, width, height); //设置颜色 g.setColor(Color.GRAY); //填充矩形 g.fillRect(1, 1, width-2, height-2); //设置颜色 g.setColor(Color.WHITE); //拿随机数对象 Random r = new Random(); //画干扰线 10条 for(int i=0;i<10;i++){ g.drawLine(r.nextInt(width), r.nextInt(height),r.nextInt(width), r.nextInt(height)); } //设置颜色 g.setColor(Color.RED); //改变字体大小 Font font = new Font("宋体", Font.BOLD,30);//参数:1字体名称。2.字体样式 3.字体大小 g.setFont(font);//设置字体 //画验证码 4个 int x = 35;//第一个数的横坐标是35像素 for(int i=0;i<4;i++){ //r.nextInt(10)+""这种写法效率是十分低的 g.drawString(String.valueOf(r.nextInt(10)), x, 25); x+=35; } //输出到浏览器上 //参数: 1.内存对象。2.输出的图片格式。3.使用的输出流 ImageIO.write(image, "jpg", response.getOutputStream()); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }