Struts2中使用Stream Result Type
Stream result type是Struts2中比较有用的一个feature。特别是在动态生成图片和文档的情况下;例如动态验证码,各种报表图片生成等。鉴于网上使用struts2生成动态验证码,struts2+jfreechart的例子中很少使用到该feature,这里以生成动态验证码为例解释stream result的使用:
- Action类,action主要要提供一个获取InputStrem的方法
public class CheckCodeAction extends ActionSupport implements SessionAware { private Logger log = LoggerFactory.getLogger(this.getClass()); private InputStream imageStream; private Map session; public String getCheckCodeImage(String str, int show, ByteArrayOutputStream output) { Random random = new Random(); BufferedImage image = new BufferedImage(80, 30, BufferedImage.TYPE_3BYTE_BGR); Font font = new Font("Arial", Font.PLAIN, 24); int distance = 18; Graphics d = image.getGraphics(); d.setColor(Color.WHITE); d.fillRect(0, 0, image.getWidth(), image.getHeight()); d.setColor(new Color(random.nextInt(100) + 100, random.nextInt(100) + 100, random.nextInt(100) + 100)); for (int i = 0; i < 10; i++) { d.drawLine(random.nextInt(image.getWidth()), random.nextInt(image.getHeight()), random.nextInt(image.getWidth()), random.nextInt(image.getHeight())); } d.setColor(Color.BLACK); d.setFont(font); String checkCode = ""; char tmp; int x = -distance; for (int i = 0; i < show; i++) { tmp = str.charAt(random.nextInt(str.length() - 1)); checkCode = checkCode + tmp; x = x + distance; d.setColor(new Color(random.nextInt(100) + 50, random.nextInt(100) + 50, random.nextInt(100) + 50)); d.drawString(tmp + "", x, random.nextInt(image.getHeight() - (font.getSize())) + (font.getSize())); } d.dispose(); try { ImageIO.write(image, "jpg", output); } catch (IOException e) { log.warn("生成验证码错误.", e); } return checkCode; } public String execute() throws Exception { ByteArrayOutputStream output = new ByteArrayOutputStream(); String checkCode = getCheckCodeImage("ABCDEFGHJKLMNPQRSTUVWXYZ123456789", 4, output); this.session.put(Constants.CHECK_CODE_KEY, checkCode); //这里将output stream转化为 inputstream this.imageStream = new ByteArrayInputStream(output.toByteArray()); output.close(); return SUCCESS; } public InputStream getImageStream() { return imageStream; } public void setSession(Map session) { this.session = session; }?struts配置文件<action name="checkCode" type="stream"> <param name="contentType">image/jpeg</param> <!-- 指定提供InputStream的filed name --> <param name="inputName">imageStream</param> <param name="bufferSize">1024</param> </result> <interceptor-ref name="defaultStack"/></action>?可以看出使用Stream result type非常简单。在该例子中使用了一个小技巧将OutputStream转化为InputStrem
ByteArrayOutputStream output = new ByteArrayOutputStream();//省略填充output的代码... InputStremin = new ByteArrayInputStream(output.toByteArray());?
public SafeImageAction() {
}
public String execute() throws IOException {
response.setContentType("image/jpeg");
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0L);
output = new ByteArrayOutputStream();
// HttpSession session = request.getSession();
int width = 60;
int height = 20;
// image = new BufferedImage(width, height, 1);
image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
Graphics g = image.getGraphics();
Random random = new Random();
g.setColor(getRandColor(200, 250));
g.fillRect(0, 0, width, height);
g.setFont(new Font("Arial", 0, 19));
g.setColor(getRandColor(160, 200));
for (int i = 0; i < 155; i++) {
int x = random.nextInt(width + 100);
int y = random.nextInt(height + 100);
int xl = random.nextInt(10);
int yl = random.nextInt(12);
g.drawOval(x, y, x + xl, y + yl);
}
String sRand = "";
for (int i = 0; i < 4; i++) {
String rand = getRandChar(random.nextInt(36));
sRand = (new StringBuilder()).append(sRand).append(rand).toString();
g.setColor(new Color(20 + random.nextInt(110), 20 + random
.nextInt(110), 20 + random.nextInt(110)));
g.drawString(rand, 13 * i + 6, 16);
}
// session().setAttribute("rand", sRand);
// session.put("rand", sRand);
g.dispose();
try {
ImageIO.write(image, "jpg", output);
} catch (IOException e) {
System.out.println("生成验证码有误: " + e);
}
imageOut = response.getOutputStream();
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(imageOut);
encoder.encode(image);
this.imageStream = new ByteArrayInputStream(output.toByteArray());
output.close();
return SUCCESS;
}
public void setServletResponse(HttpServletResponse response) {
this.response = response;
}
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
private Color getRandColor(int fc, int bc) {
Random random = new Random();
if (fc > 255) {
fc = 255;
}
if (bc > 255) {
bc = 255;
}
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);
}
private String getRandChar(int randNumber) {
return CHARARRAY[randNumber];
}
public void setSession(Map session) {
this.session = session;
}
public BufferedImage getImage() {
return image;
}
public void setImage(BufferedImage image) {
this.image = image;
}
public javax.servlet.ServletOutputStream getImageOut() {
return imageOut;
}
public void setImageOut(javax.servlet.ServletOutputStream imageOut) {
this.imageOut = imageOut;
}
}
----------------------------------------- 9 楼 ray_linn 2008-07-03 Stream result type? 可有可无,把Respose的header设置成image/xxx就可以了。 10 楼 kjj 2008-12-31 ray_linn 写道Stream result type? 可有可无,把Respose的header设置成image/xxx就可以了。
用struts2 为什么,她的目的就是让你们忘掉servlet ,造一个脱离servlet 的瓶子,你又给拉回去了,还不如直接用servlet 算了,不伦不类滴 11 楼 epanthere 2009-01-09 kjj 写道ray_linn 写道Stream result type? 可有可无,把Respose的header设置成image/xxx就可以了。
用struts2 为什么,她的目的就是让你们忘掉servlet ,造一个脱离servlet 的瓶子,你又给拉回去了,还不如直接用servlet 算了,不伦不类滴
ls的正解 和servlet的交互struts2都给你封装好了 干嘛没事找事 12 楼 wenquan4004 2009-04-02 哎呀!我找了好几天的有关struts2读取数据库显示图片的例子都是些老版本(servlet)
谁知今天我才看到一片关于使用result处理的图片的文章,还是英文,费老劲才看懂,原来是用了StreamResult,想看看网上有没有和这个相关的文章学习下,还就找到了,看了哥哥的文章我是如梦初醒啊!学了java也很长时间了虽说会抄写代码,但是达到哥哥这种地步还是望尘莫及啊!谢谢! 13 楼 wzlcm 2011-07-26 kjj 写道ray_linn 写道Stream result type? 可有可无,把Respose的header设置成image/xxx就可以了。
用struts2 为什么,她的目的就是让你们忘掉servlet ,造一个脱离servlet 的瓶子,你又给拉回去了,还不如直接用servlet 算了,不伦不类滴
不大同意楼上,用header也并非没有好处,例如:我想在线看(一般浏览器都支持)doc,excel,jpg等,我就没必要用几个不同的result,我可以直接在后台判断文件类型,然后直接让返回相应的ContentType,这样岂不更方便?
使用框架,当然怎么是简单方便怎么样,而不要被所谓“思想”给局限了!