Java 如何在jsp中打印图像(大量)

Java 如何在jsp中打印图像(大量),java,jsp,servlets,Java,Jsp,Servlets,在jsp页面中,我想显示从blob字段的db中获取的许多图像 现在,我的jsp页面中有以下代码: 在servlet ShowImage中,我使用idI进行查询并打印图像 这对我不好,因为我的循环中可能有100个项目,我必须调用100次servlet ShowImage;由于我在servlet ShowImage中调用db,这意味着我将在一个页面中建立100个到数据库的连接 使用just on query打印从bliob字段的db中获取的图像循环的正确方法是什么 您可以使用 下面是一个简单的例子

在jsp页面中,我想显示从blob字段的db中获取的许多图像

现在,我的jsp页面中有以下代码:

在servlet ShowImage中,我使用idI进行查询并打印图像

这对我不好,因为我的循环中可能有100个项目,我必须调用100次servlet ShowImage;由于我在servlet ShowImage中调用db,这意味着我将在一个页面中建立100个到数据库的连接


使用just on query打印从bliob字段的db中获取的图像循环的正确方法是什么

您可以使用

下面是一个简单的例子:

JSP

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page contentType="text/html" pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Image Overview</title>
    </head>
    <body>
        <c:forEach items="${imageBean.images}" step="1" var="img">
            <c:out value="${img.name}"/><br/>
            <img src="${img.sourceUri}"><br/>
        </c:forEach>
    </body>
</html>
和域类

import java.io.Serializable;


public class DisplayImage implements Serializable {

    private String name;
    private String sourceUri;

    public DisplayImage() {
    }

    public DisplayImage(String name, String sourceUri) {
        this.name = name;
        this.sourceUri = sourceUri;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSourceUri() {
        return sourceUri;
    }

    public void setSourceUri(String sourceUri) {
        this.sourceUri = sourceUri;
    }
}
现在,您可以在一个JSP页面上显示所有图像


Patrick

如果您的服务器内存充足,并且没有太多图像,只需将所有内容预加载到内存中,但我必须承认这可能不是一个真正的选择

但是您的问题实际上是缓存对数据库的访问的问题。可以很容易地对整个页面使用一个查询,根据可分配内存和预期的并发会话数,可以选择在会话期间对其进行缓存

普林西比:在这个回答中,为了简洁起见,我不会分离控制器、服务和数据库层。当您从请求属性中获取listaNews时,我假设您已经准备好了一个servlet来计算该列表,并将其放入请求属性中并转发给JSP。 这个servlet将从数据库加载listaNews中的所有图像,并将它们存储在会话中。然后ShowImage在会话中搜索图像,如果它出于任何原因不在会话中,它应该从数据库中加载并返回它。或者,如果需要节省内存,它会将其从会话中删除

我将以这种方式实现它,使用计数发送以从会话中逐出缓存图像-正常情况下,如果在缓存逐出1之前发送的次数为0:

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);
}
ShowImage:

@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
}

我没有我的图像的URI,我从数据库中获取它们,然后用数据库中的图像填充列表。。我认为您使用的是一个结果集,例如:DisplayImages di=newdisplayImage;di.setNamers.getStringnameCol;di.setSourceUrirs.getStringsource;然后将while循环中的图像添加到列表中并返回此对象。在db中,我只是在每个图像的blob字段中有一个InputStream,我没有图像UriOk,我明白了,然后和Post应该对您有帮助。但是没有办法不创建包装类就可以这样做吗?一种让servlet返回图像列表,然后使用${servletName}访问该列表的方法?是的,没错。为了解决这个问题,我找到了这个非逻辑的解决方案。我无法理解如何仅通过一次选择就可以从一个数据库打印多个图像。@MatteoDepasquali:您的图像是静态的吗?它们的数字是否更改?如果他们可能会改变,典型的改变是什么?想象一下facebook。我有足够的图片给每个用户。因此,对于每个用户页面,我必须在blob字段中打印它保存在数据库中的所有图片。用户可以有1张或100张图片,可以每天上传一张新图片,也可以从不上传。你的图片的典型尺寸是多少?但是无论如何,对于100个图像,我不认为内联是一个选项。大小大约为500K。实际上,在这个应用程序中,每页大概不会有超过20-30个图像。
@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
}