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

时间:2014-07-25 10:36:28

标签: java jsp servlets

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

现在我在jsp页面中有了这段代码:

    <c:forEach var="news" items="${requestScope.listaNews}">    
            <img src="ShowImage?idI=${news.idImmagine}" >
    </c:forEach>

servlet ShowImage我使用idI进行查询,然后打印图像。

这对我不好,因为我的循环中可能有100个项目,并且不得不调用servlet ShowImage的100倍;因为我在servlet ShowImage中调用了db,这意味着只需一页即可与数据库建立100个连接。

通过查询打印从db(来自bliob字段)获取的图像循环的正确方法是什么?

2 个答案:

答案 0 :(得分:0)

您可以使用JSTL

之外的内容

这是一个简单的例子:

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>

BackingBean,我在Bean的第一个实例化中使用图像初始化List,如果您的图像数量不会改变,请执行此操作,否则您可以查询数据库中新鲜的图像列表,当您调用getImages()方法或将其封装在另一个方法中,并在Bean上的return images;之前调用它。

所以这是Demo Bean

import de.professional_webworkx.imagegallery.domain.DisplayImage;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;


@Named(value = "imageBean")
@SessionScoped
public class ImageBean implements Serializable {

    private List<DisplayImage> images = new ArrayList<>();

    @PostConstruct
    public void init() {
        images.add(new DisplayImage("Image1", "http://i.stack.imgur.com/7bI1Y.jpg"));
        images.add(new DisplayImage("Image2", "http://i.stack.imgur.com/XZ4V5.jpg"));
        images.add(new DisplayImage("Image3", "http://i.stack.imgur.com/7bI1Y.jpg"));
        images.add(new DisplayImage("Image4", "http://i.stack.imgur.com/iQFxo.gif"));
    }
    public List<DisplayImage> getImages() {
        return images;
    }

    public void setImages(List<DisplayImage> images) {
        this.images = images;
    }
}

Domain类

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页面上显示所有图像。

帕特里克

答案 1 :(得分:0)

如果你的服务器有足够的内存,而不是太多的图像,只需将所有内容预加载到内存中,但我必须承认它可能不是一个真正的选择。

但是你的问题实际上是缓存对数据库的访问的问题。对整个页面使用单个查询很容易,可以选择在会话期间缓存它,具体取决于可记忆内存和预期的并发会话数。

Princips:在这个答案中,为简洁起见,我不会将控制器,服务和数据库层分开。当你从listaNews形成请求属性时,我假设你已经有一个servlet来计算这个列表,将它放在一个请求属性中并转发到你的JSP。 此servlet将从数据库加载listaNews的所有图像,并将它们存储在会话中。然后ShowImage在会话中搜索图像(如果由于任何原因它不应该从数据库加载它)并返回它。如果保存内存是一个问题,它会将它从会话中删除。

我会以这种方式实现它,使用计数发送以从会话中逐出缓存的图像 - 如果&lt; 0,永远不会驱逐,如果&gt; 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);
}

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
}