(一)验证码如何生成?
(1)实现验证码所需要的类:
(1)、java.awt.image.BufferedImage:
BufferedImage 子类描述具有可访问图像数据缓冲区的 Image。
(2)、java.awt.Graphics:
Graphics 类是所有图形上下文的抽象基类,允许应用程序在组件(已经在各种设备上实现)以及闭屏图像上进行绘制。
(3)、java.awt.Graphics2D:
Graphics2D 类扩展 Graphics 类,以提供对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制。
(4)、javax.imageio.ImageWriter:
用来编码和写入图像的抽象超类。此类必须由在 Java Image I/O 框架的上下文中写出图像的类为其创建子类。
(2)实现一个验证码的方式:
(1)演示: 把字符串”Hello”变成图片写到一个jpg文件中
@Test
public void demo1() throws IOException{
//定义图片的宽和高
int w=60;
int h=30;
//声明一个RGB格式的内存中的图片
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics();
//最左侧字符的基线位于此图形上下文坐标系的 (x, y) 位置处。 (此时位于左下角的位置)
g.drawString("Hello", 0, 30);
g.dispose();//类似于IO中的flush(),把图形数据刷到img中
//把内存图片img对象保存到一个jpg文件
ImageIO.write(img, "JPEG", new FileOutputStream("a.jpg"));
System.out.println("Over....");
}
验证码效果:
(2)演示: 把验证码(4个随机数字)变成图片写到一个jpg文件中
@Test
public void demo2() throws IOException{
//定义图片的宽和高
int w=60;
int h=30;
//声明一个RGB格式的内存中的图片
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics();
//把背景变白色
g.setColor(Color.white);
g.fillRect(0, 0, w, h);
//设置字体
g.setFont(new Font("aa",Font.BOLD,18));
//产生并draw出4个随机数字
Random r = new Random();
for(int i=0;i<4;i++){
int a = r.nextInt(10);//生成0~9之间的随机整数
int y = 15+r.nextInt(20);//产生随机的垂直位置
//产生随机颜色
Color c = new Color(r.nextInt(256),r.nextInt(256),r.nextInt(256));
g.setColor(c);
g.drawString(""+a, i*15, y);
}
//画几条干扰线
for(int i=0;i<10;i++){
//产生随机颜色
Color c = new Color(r.nextInt(256),r.nextInt(256),r.nextInt(256));
g.setColor(c);
g.drawLine(r.nextInt(60), r.nextInt(30), r.nextInt(60), r.nextInt(30));
}
g.dispose();//类似于IO中的flush(),把图形数据刷到img中
//把内存图片img对象保存到一个jpg文件
ImageIO.write(img, "JPEG", new FileOutputStream("a.jpg"));
System.out.println("Over....");
}
验证码效果:
(3)演示: 生成可以缩放和旋转的验证码 —用Graphics2D类代替Graphics:
@Test
public void demo3() throws IOException{
int w = 90;
int h = 30;
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = (Graphics2D) img.getGraphics();
g2d.setFont(new Font("黑体",Font.BOLD,18));
Random r = new Random();
for(int i=0;i<4;i++){
String s = "" +r.nextInt(10);
//旋转矩阵
AffineTransform aff = new AffineTransform();
aff.rotate(Math.random(),i*18,h-5);//旋转
aff.scale(0.6+Math.random(), 0.6+Math.random());//放缩
g2d.setTransform(aff);
g2d.drawString(s, i*15, h-5);
}
g2d.dispose();
ImageIO.write(img, "JPEG", new FileOutputStream("a2.jpg"));
System.out.println("Over....");
}
验证码效果:
(二)如何写一个WebProject项目?
(1)进入MyEclipse->New->WebProject进行创建:
(2)进入New Web Project配置项目名及路径:
(3)项目初步创建完成如图:
(4)首先进入index.jsp修改成所需的jsp页面:
(1):显示注册表单:
<body>
<form action="" >
姓名:<input type="text" name="name"><br/>
密码:<input type="password" name="pwd"><br/>
验证码:<input type="text" name="code">
<img id="codeImage" src=""><a href="">看不清</a><br/>
<input type="submit" value="注册"><br/>
</form>
</body>
1)我们知道表单注册,都是从前端(网页)收集数据然后提交给后台(数据库)进行校验。
2)前端数据如何收集?比如此处的姓名密码可以通过输入获得,而验证码也是通过后台发送的填入,同时如果验证码看不清,则需要页面与用户交互。
3)这里涉及如何显示“验证码”,如何“更换”验证码?
【解决上面提到的两个问题】:
4)前边我们已经生成了验证码,这里直接读取图片img的src即可;5)通过点击超链接更换图片。
6)src路径是变得,用变量code作为其路径;超链接由javaScript函数实现。
(2)显示、更改、验证码:
1)设置<img>标签的id="codeImage",src变量名src="code";
<img id="codeImage" src="code">
2)设置<a>标签的href为js函数:changeImage();
<a href="javascript:changeImage();">看不清</a>
3)<head>标签中写js代码,实现function函数 changeImage()。
i:code后边的"?"代表的是此code变量带有参数:new Date().getTime();
【注意:浏览器服务器相互通信,每次浏览器请求服务器会有一个session,有一段时间session是不变的。
由于上次服务器对浏览器做了响应,下次访问服务器可能不会成功,这时只要我们改变了session,
就可以第二次请求服务器了。所以我们让code带时间参数每次都变,这样就可以一直请求 变化的验证码了!】
ii:code如何访问?通过配置web.xml中的servlet,来调用java后台,接下来我们要写CodeImgServlet。
<script type="text/javascript">
function changeImage(){
var img = document.getElementById("codeImage");
img.src="code?"+new Date().getTime();
}
</script>
index.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>注册界面</title>
<script type="text/javascript">
function changeImage(){
var img = document.getElementById("codeImage");
img.src="code?"+new Date().getTime();
}
</script>
</head>
<body>
<form action="LoginServlet" method="get">
姓名:<input type="text" name="name"><br/>
密码:<input type="password" name="pwd"><br/>
验证码:<input type="text" name="code">
<img id="codeImage" src="code"><a href="javascript:changeImage();">看不清</a><br/>
<input type="submit" value="注册"><br/>
</form>
</body>
</html>
(5)在后台(src)编写CodeImgServlet.java程序:
(1)建立一个servlets包,再建立一个Servlet类:
当我们创建CodeImgServlet类即将成功的时候,还会弹出最后一个页面,这个页面中的内容信息都是为配置web.xml做准备的,上边已经提到过web.xml配置,配置信息如图:
这时Web.xml配置文件自动修改了:
(2)CodeImgServlet类创建好以后,开始编写此类:
(1)直接覆盖父类的方法:service(req,resp):
CodeImgServlet.java类:
package servlets;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CodeImgServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// ☆1☆--相比纯java方式有变化的地方
// 设置http响应头---告诉浏览器我现在发的是这个图片格式的数据,你用相应的方式来解析
resp.setContentType("image/jpeg");
// 定义图片的宽和高
int w = 60;
int h = 30;
// 声明一个RGB格式的内存中的图片
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics();
// 把背景变白色
g.setColor(Color.white);
g.fillRect(0, 0, w, h);
// 设置字体
g.setFont(new Font("aa", Font.BOLD, 18));
// 产生并draw出4个随机数字
Random r = new Random();
for (int i = 0; i < 4; i++) {
int a = r.nextInt(10);// 生成0~9之间的随机整数
int y = 15 + r.nextInt(20);// 产生随机的垂直位置
// 产生随机颜色
Color c = new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256));
g.setColor(c);
g.drawString("" + a, i * 15, y);
}
// 画几条干扰线
for (int i = 0; i < 10; i++) {
// 产生随机颜色
Color c = new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256));
g.setColor(c);
g.drawLine(r.nextInt(60), r.nextInt(30), r.nextInt(60),
r.nextInt(30));
}
g.dispose();// 类似于IO中的flush(),把图形数据刷到img中
// 把内存图片img对象保存到一个jpg文件
ImageIO.write(img, "JPEG", resp.getOutputStream());// ☆2☆
}
}
但是注意以下两处是编写此类的关键语句:
//(1)设置http响应头---告诉浏览器我现在发的是这个图片格式的数据,你用相应的方式来解析
resp.setContentType("image/jpeg");
//(2)servlet将响应信息发送到浏览器上。
ImageIO.write(img, "JPEG", resp.getOutputStream());// ☆2☆
此时我们一个最基本的前端和后台的所需的基本内容都已完成,记下来,我们可以在网页上实现用户交互,点击“看不清”验证码就会变化!
验证码的创建交互都已近实现,接下来就是如何实现表单的提交?如何把我们注册的信息全部提交到后台去?
(6)在后台(src)编写LoginServlet.java程序实现表单提交:
(1)首先要设置index.jsp中表单的action和提交方式:
//此处的LoginServlet和code类似,设置提交方式为get也可以,但是一般表单提交都用post,get_post详细说明见后边演示:
<form action="LoginServlet" method="get">
LoginServlet.java类:
package servlets;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String name=req.getParameter("name");
String pwd=req.getParameter("pwd");
String code=req.getParameter("code");
resp.getWriter().print(name+","+pwd+","+code);
}
}
此时servlet类创建完毕,可以看到web.xml所有配置信息:
Web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name></display-name>
<servlet>
<description>This is the description of my J2EE component</description>
<display-name>This is the display name of my J2EE component</display-name>
<servlet-name>CodeImgServlet</servlet-name>
<servlet-class>servlets.CodeImgServlet</servlet-class>
</servlet>
<servlet>
<description>This is the description of my J2EE component</description>
<display-name>This is the display name of my J2EE component</display-name>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>servlets.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CodeImgServlet</servlet-name>
<url-pattern>/code</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/LoginServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
(7)此时验证表单提交:
【注意】:此时我们将表单信息只是显示到页面即可,具体的向后台提交后边再学。
注册信息:
表单提交成功!