如果您的服务器中有足够的内存,并且没有太多的图像,只需将所有内容预加载到内存中,但我必须承认这可能不是一个真正的选择。
但是您的问题实际上是缓存对数据库的访问的问题。对整个页面使用单个查询很容易,并且可以选择在会话期间缓存它,具体取决于可分配的内存和预期的并发会话数。
原则:在这个答案中,为简洁起见,我不会将控制器、服务和数据库层分开。当您从请求属性中获得listaNews 时,我假设您已经拥有一个计算此列表的servlet,将其放入请求属性中并转发到您的JSP。
这个 servlet 将从数据库中加载来自listaNews 的所有图像,并将它们存储在会话中。然后ShowImage 在会话中搜索图像(如果由于任何原因它不存在,它应该从数据库中加载它)并返回它。 (可选)如果需要节省内存,它会将其从会话中删除。
我会以这种方式实现它,使用发送计数从会话中驱逐缓存的图像 - 如果 0 次(正常情况下为 1):
CachedImage:保存图片字节数和可以发送的次数
public class CachedImage {
private static final int BUFFER_SIZE = 32768; // 32k buf
byte[] data;
int toSend;
public CachedImage(int toSend, InputStream is) throws IOException {
byte[] buffer = new byte[BUFFER_SIZE];
ByteArrayOutputStream os = new ByteArrayOutputStream();
while (is.read(buffer) != -1) {
os.write(buffer);
}
data = os.toByteArray();
}
}
在准备页面的 servlet 中的修改:
@Override
protected void service(HttpServletRequest hsr, HttpServletResponse hsr1) throws ServletException, IOException {
final int TO_SEND = 1; //number of time each image should be downloaded before purge (-1 = no purge)
HashMap<String, CachedImage> images = new HashMap<String, CachedImage>();
...
// calculates listaNews
// loads all the images from database and store them in session
for(...) { // loops for the images key id , InputStream is
images.put(id, new CachedImage(TO_SEND, is));
}
HttpSession session = hsr.getSession();
session.setAttribute("cachedImages", images);
}
显示图像:
@Override
protected void service(HttpServletRequest hsr, HttpServletResponse hsr1) throws ServletException, IOException {
String id = hsr.getParameter("idI");
HttpSession session = hsr.getSession();
Map<String,CachedImage> images = (Map<String,CachedImage>) session.getAttribute("cachedImages");
if (images != null) { // Ok map is in session
CachedImage cached = images.get(id);
if (cached != null) { // ok image is in cache
if (cached.toSend > 0) { // if relevant, evict image from session cache
if (--cached.toSend == 0) {
images.remove(id);
}
}
}
//send cached image : cached.data
}
// load image from database and send it
}