在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字段)获取的图像循环的正确方法是什么?
答案 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
}