做注册模块,需要图片验证码机制。google了一圈,自己再整理修改了一下,总算是弄出来了。思路就是在一个action里应用java的awt包里面的类绘制一个内存中的图片,然后产生随机数并将随机数写到图片上,然后把action的返回类型设为stream,把图片数据写入到输入流返回给浏览器。html可以通过img页面直接用src属性引用该action
action的代码如下
- import java.io.*;
- import javax.imageio.ImageIO;
- import javax.imageio.stream.ImageOutputStream;
- import java.awt.*;
- import java.awt.Color;
- import java.awt.image.BufferedImage;
-
- public class CreateValidateAction extends DefaultAction {
-
- private ByteArrayInputStream inputStream;
-
- public String createRandomString() {
- String str = "";
- for (int i = 0; i < 4; i++) {
- str += Integer.toString((new Double(Math.random() * 10)).intValue());
- }
- return str;
- }
-
- public Color createsRandomColor() {
- int r = (new Double(Math.random() * 256)).intValue();
- int g = (new Double(Math.random() * 256)).intValue();
- int b = (new Double(Math.random() * 256)).intValue();
- return new Color(r, g, b);
- }
-
- public BufferedImage createImage(String str) {
- int width = 60;
- int height = 22;
- BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
-
- Graphics g = image.getGraphics();
-
- g.setColor(Color.WHITE);
- g.fillRect(0, 0, width, height);
-
- g.setColor(Color.black);
- g.drawRect(0, 0, width - 1, height - 1);
-
- g.setFont(new Font("Atlantic Inline", Font.PLAIN, 18));
-
- g.setColor(this.createsRandomColor());
-
- g.drawString(Character.toString(str.charAt(0)), 8, 17);
- g.drawString(Character.toString(str.charAt(1)), 20, 17);
- g.drawString(Character.toString(str.charAt(2)), 33, 17);
- g.drawString(Character.toString(str.charAt(3)), 45, 17);
-
- g.dispose();
- return image;
- }
-
- public ByteArrayInputStream createInputStream() throws Exception {
-
- String str=this.createRandomString();
- BufferedImage image = this.createImage(str);
-
- this.getSession().put("validateCode", str);
- ByteArrayOutputStream output = new ByteArrayOutputStream();
- ImageOutputStream imageOut = ImageIO.createImageOutputStream(output);
- ImageIO.write(image, "JPEG", imageOut);
- imageOut.close();
- ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
- output.close();
- return input;
- }
-
- @Override
- public String execute() throws Exception {
- setInputStream(createInputStream());
- return SUCCESS;
- }
-
- public ByteArrayInputStream getInputStream() {
- return inputStream;
- }
- public void setInputStream(ByteArrayInputStream inputStream) {
- this.inputStream = inputStream;
- }
- }
然后是对应的struts的配置
-
- <action name="createValidateAction" class="createValidateAction">
- <result type="stream">
- <param name="contentType">image/jpeg</param>
- <param name="inputName">inputStream</param>
- </result>
- </action>
最后就是html的写法,点击图片的时候可以更新验证码
- <script type="text/javascript">
- function changeValidateCode(obj) {
- //获取当前的时间作为参数,无具体意义
- var timenow = new Date().getTime();
- //每次请求需要一个不同的参数,否则可能会返回同样的验证码
- //据说和浏览器的缓存机制有关系,不太明白,照做吧
- obj.src="createValidateAction.action?d="+timenow;
- }
- </script>
-
- <img src="createValidateAction.action" onclick="changeValidateCode(this)"/>