在前台页面有如下语句
<img onclick="this.src='/ran/random?random='+Math.random()" alt="验证码,点击图片更换" src="/ran/random?random=0.2868249340216069" width="86" height="40">
其中src 指向的地址不是一个img文件,而是一个转到SpringMVC的类中方法
src="/ran/random?random=0.2868249340216069"
方法如下:
@Controller
public class RandomCodeController {
@RequestMapping(value={"/ran/random"})
public void genericRandomCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setHeader("Cache-Control", "private,no-cache,no-store");
response.setContentType("image/png");
HttpSession session = request.getSession();
int width = 85;
int height = 28;
BufferedImage image = new BufferedImage(width, height, 2);
Graphics2D g = image.createGraphics();
g.setComposite(AlphaComposite.getInstance(3, 1.0f));
Random random = new Random();
g.setColor(new Color(231, 231, 231));
g.fillRect(0, 0, width, height);
g.setFont(new Font("Microsoft YaHei", 2, 24));
String sRand = "";
for (int responseOutputStream = 0; responseOutputStream < 4; ++responseOutputStream) {
String rand = String.valueOf(random.nextInt(10));
sRand = sRand + rand;
g.setColor(new Color(121, 143, 96));
g.drawString(rand, 13 * responseOutputStream + 16, 23);
}
session.setAttribute("COMMON_RAND_CODE", (Object)sRand);
g.dispose();
ServletOutputStream var12 = response.getOutputStream();
ImageIO.write((RenderedImage)image, "png", (OutputStream)var12);
var12.close();
}
}
所以其实这个src相联系的是一个ServletOutputStream
这个地方我不太理解
ServletOutputStream如何和一个图片联系起来?
不仅仅是图片,其他文件也是以流的形式传输的。浏览器把后台给的流解析成了图片了。
说白了,图片是怎么展示到你的电脑上的呢,就是一个通过网络数据流。
所谓指向具体图片,或者是其他服务器上的资源也一样,就是你的web服务器将对应的文件以流的形式读取,然后通过网络发出去。浏览器端接到的都是流,他只能根据
mime type
去判断这个流内的文件是什么以伪代码简单来说就是这样的
而你上面那段代码 其实主要是生成了一个图片,只不过他没有将文件写道硬盘,而是直接发送给了浏览器端。
ImageIO.write(image, "png", output)
这句实际上就是将image
对象的数据写入到对应的位置,如果这个流是一个fileoutput,那他就会写入到硬盘,所以你也可以改成这样。这是文件流在Servlet中传输方式问题,ServletOutputStream通过HttpServletResponse.getOutputStream()与浏览器客户端实现连通,ImageIO.write()将文件转换成为输出流,而至于中间的连通过程及具体实现方式,那就需要你去看源代码了。
估计你也不想研究这么深,知道文件流在B/S结构中传输大致流程,了解具体代码实现方式和参数设置规则即可。另外,建议你把验证码生成代码提取出来单独写一个方法,然后再让RandomCodeController()方法调用,这样结构简单明了