服务器对客户端浏览器做出的响应被封装成一个HttpResponse对象。要对浏览器进行操作,只需要操作HttpRespones对象,通过HttpServletResponse.getWriter()获得PrintWriter,该对象为outputStream的子类。然后使用该对象输出信息即可。
本例将使用Servlet输出图片验证码。
图片验证码的原理是,服务器生成一个包含随即的字符串图片发给客户端,客户端提交数据时需要填写字符串作为验证信息。由于字符串保存在图片里,因此机器很难识别,从而达到防止有人使用计算机程序恶意发送信息的目的。
本帖由卡菲牛奶撰写,原文请访问http://fuchangle.iteye.com/blog/1325408
开始正文
Servlet输出图片时,需要调用getOutputStream输出图片,代码如下:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
public class IdentityServlet extends HttpServlet{
public static final char[] CHARS={'2','3','4','5','6','7','8','9','A','B','C',
'D','E','F','G','H','K','M','L','N','L','X','Y','Z','Q'};
public static Random random=new Random();
public static String getRandomString(){
StringBuffer buffer=new StringBuffer();
//随即产生6位数
for(int i=0;i<6;i++){
buffer.append(CHARS[random.nextInt(CHARS.length)]);
}
System.out.println(buffer.toString());
return buffer.toString();
}
//获取随即的颜色
public static Color getRandomColor(){
return new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255));
}
//返回某颜色的反色
public static Color getReverseColor(Color c){
return new Color(255-c.getRed(), 255-c.getGreen(),255-c.getBlue());
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("image/jpeg");
String randomString=getRandomString();
request.getSession(true).setAttribute("randomString", randomString);
int width=100;//图片宽度
int height=30;//图片高度
Color color=getRandomColor(); //随即颜色。用于背景颜色
Color reverse=getReverseColor(color);//反色,用于前背景
//创建一个彩色图片
BufferedImage bi=new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//获取绘图对象
Graphics2D g=bi.createGraphics();
g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 16));//设置字体
g.setColor(color); //设置颜色
g.fillRect(0, 0, width, height);//绘制背景
g.setColor(reverse);//设置颜色
g.drawString(randomString, 18, 20);
for(int i=0;i<100;i++){
g.drawRect(random.nextInt(width), random.nextInt(height),1, 1); //随即噪音点
}
ServletOutputStream out=response.getOutputStream(); //转换JPEG格式
JPEGImageEncoder encoder=JPEGCodec.createJPEGEncoder(out); //编码器
encoder.encode(bi);
out.flush(); //输出到客户端
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
super.doPost(req, resp);
}
}
代码中利用一个随机数生成Random与char[]类型的字符字典生成随即字符串,字符字典里将比较容易混淆的0和O,1和I等都去掉,然后生成一个长100宽30的图片利用随即颜色填充背景,利用反色在前面绘制随即字符,并画出100个位置随即 的噪点,增加图片的识别难度
该Servlet需要配置到web.xml中,代码如下:
web.xml
<servlet>
<servlet-name>IdentityServlet</servlet-name>
<servlet-class>com.fcl.IdentityServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>IdentityServlet</servlet-name>
<url-pattern>/servlet/IdentityServlet</url-pattern>
</servlet-mapping>
然后访问该Servlet就可以预览图片啦。为了演示方面,下面用一个HTML文件引用这个图片验证码,代码如下:
<script type="text/javascript">
function reloadImage(){
document.getElementById('btn').disabled=true;
document.getElementById('identity').src='servlet/IdentityServlet?ts='+new Date().getTime();
}
</script>
<body>
<img src="servlet/IdentityServlet" id="identity" onload="btn.disabled=false;">
<input type="button" value="更换图片" onclick="reloadImage()" id="btn">
</body>
这样就OK啦!