我正在以最佳性能将图像写入servlet响应。任何建议,做法,经验?
答案 0 :(得分:22)
为了获得最佳性能和效率,请不要将整个内容放在byte[]
中。每个byte
吃掉,是的,来自Java内存的一个字节。想象一下,100个并发用户请求每100KB的10张图像,这已经消耗掉了100MB的Java内存。
使用InputStream
从数据库中获取ResultSet#getBinaryStream()
的图像,将其包装在BufferedInputStream
中并将其写入包含在{{{{}}中的响应的OutputStream
1}}通过一个小的BufferedOutputStream
缓冲区。
假设您按数据库键选择图像作为标识符,请在HTML中使用:
byte[]
创建一个<img src="images/123">
类,该Servlet
类在web.xml
url-pattern
/images/*
上映射,并按如下方式实施其doGet()
方法。
Long imageId = Long.valueOf(request.getPathInfo().substring(1)); // 123
Image image = imageDAO.find(imageId); // Get Image from DB.
// Image class is just a Javabean with the following properties:
// private String filename;
// private Long length;
// private InputStream content;
response.setHeader("Content-Type", getServletContext().getMimeType(image.getFilename()));
response.setHeader("Content-Length", String.valueOf(image.getLength()));
response.setHeader("Content-Disposition", "inline; filename=\"" + image.getFilename() + "\"");
BufferedInputStream input = null;
BufferedOutputStream output = null;
try {
input = new BufferedInputStream(image.getContent());
output = new BufferedOutputStream(response.getOutputStream());
byte[] buffer = new byte[8192];
for (int length = 0; (length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
} finally {
if (output != null) try { output.close(); } catch (IOException logOrIgnore) {}
if (input != null) try { input.close(); } catch (IOException logOrIgnore) {}
}
在ImageDAO#find()
中,您可以使用ResultSet#getBinaryStream()
将图片作为InputStream
从数据库中获取。
答案 1 :(得分:0)
如果在Blob类型的数据库中存在,则可以使用来自servlet的图像的数组类型的字节。
byte[] image;
或者还有一种方法,但它有点复杂。当你打电话给你的servlet时,所以在此之前你需要确定该呼叫是用于图像还是正常呼叫。如果它是一个正常的调用,那么你可以继续调用servlet,但是如果它调用了image,那么就不要调用servlet,但你可以将图像引用存储在计算机的某个物理位置并检索它。
但是如果你在DB中有图像,这个方法将不起作用,而你可以在DB中有相对路径然后你可以从该路径中获取图像。
答案 2 :(得分:0)
如果图像是静态的,请记住,最快的响应是在它到达之前处理的响应。
您可以在Tomcat服务器前面站起Apache的httpd。您可以使用缓存边缘服务器的其他变体。这些方面有很多技巧。
当然,这假设您的应用程序是在URL以一种易于缓存的方式有效映射到一个图像的地方编写的。如果您的应用程序缺乏此功能,那么这些优势足以考虑重组。