我正在尝试使用Jstl在Jsp页面中显示图像,并且图像路径由servlet传递。 Jsp页面实际上只显示一个检索到的图像并抛出NullPointerException。
Jsp看起来像这样:
<c:forEach items="${images}" var="img">
<div class="col-md-3">
<img src="displayImg?imageId=${img.imageId}">
</div>
</c:forEach>
servlet doGet方法如下所示:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int imageId = Integer.parseInt(request.getParameter("imageId"));
Image img = imageDao.getImageById(imageId);
response.setContentType("image/" + img.getImageType());
File f = new File(img.getImagePath());
BufferedImage bi = ImageIO.read(f);
OutputStream out = response.getOutputStream();
ImageIO.write(bi, img.getImageType(), out);
out.close();
}
我无法理解为什么当请求参数正确时,这个servlet会设法为一个映像提供服务而在其他映像上失败并且使用NullPointerException失败。我有一种印象,因为它是并发问题,因为Jsp显示任意图像。
请帮忙吗?
这是DAO:
public Image getImageById(int imageId) {
String query = "SELECT * FROM images WHERE imageId=?";
Image img = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
connection = ConnectionManager.getConnection();
ps = connection.prepareStatement(query);
ps.setInt(1, imageId);
rs = ps.executeQuery();
if (rs.next()) {
img = new Image();
img.setImageId(rs.getInt("imageId")); //NPE thrown here
img.setImagePath(rs.getString("imagePath"));
img.setImageType(rs.getString("imageType"));
...
img.setDescription(rs.getString("description"));
img.setCreatedOn(rs.getTimestamp("createdOn"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
close(rs);
close(ps);
close(connection); //Removed this and problem disappears
}
return img;
}
解决!! 这很奇怪,但我只是避免关闭与数据库的连接,我的所有图像都正确显示,没有错误。我想在每次单独的数据库访问之后关闭连接是有问题的,因为它无法在你想要它的确切时间关闭,但可能在另一次调用DB的过程中。现在我想知道,根本没有关闭连接也是有问题的。在那种情况下该怎么办?
答案 0 :(得分:0)
只需阅读堆栈跟踪:
at com.mysql.jdbc.ResultSetImpl.buildIndexMapping(ResultSetImpl.java:674)
at com.mysql.jdbc.ResultSetImpl.findColumn(ResultSetImpl.java:1029)
at com.mysql.jdbc.ResultSetImpl.getInt(ResultSetImpl.java:2566)
at be.kayiranga.daoImpl.ImageDaoImpl.getImageById(ImageDaoImpl.java:114)
因此,
抛出了异常rs.getInt("imageId")
表示结果集中没有名为"imageId"
的列。
你永远不应该使用select *
。使用显式列名,并在从结果集中获取数据时使用这些显式列名:
select imageId, imagePath, imageType, description, createdOn from ...
答案 1 :(得分:0)
很奇怪,因为imageId
在查询中用作列名,并且有一条记录rs.next()
。
也许它不是int而是long或SQL VARCHAR。
也许MySQL非常聪明,因为在WHERE中指定了imageId?
或者在某种程度上,您需要使用rs.getInt("images.imageId")
。
img.setImageId(rs.getInt("imageId")); //NPE thrown here
然而,可以写成(规避)
img.setImageId(mageId);
我会检查没有狡猾的错字:í
(重音),西里尔e
(如果你是东欧)或tab char。老实说你的代码看起来整洁,但类似的错误发生在更简洁的代码上:ps,ps2,rs,rs2 as fields,对并发使用造成严重破坏,并且易于打字错误。
使用更少的内存资源可以更快地完成BTW写作:
Path path = Paths.get(img.getImagePath());
OutputStream out = response.getOutputStream();
Files.copy(path, out);
在搜索错误时:
调查错误似乎是唯一的选择:
ResultSetMetaData meta = rs.getMetaData();
int numberOfColumns = meta.getColumnCount();
for (int i = 1; i <= numberOfColumns; ++i) {
log(... i, meta.getColumnName(i), meta.getColumnLabel(i) ...);
}
答案 2 :(得分:0)
这个答案可能对你没有任何帮助,因为没有人相信你完全理解你在做什么。我假设你有一个JSP页面和一个表单,我可以告诉你如何将图像显示为字符串。
public showImage(){
BASE64Encoder base64Encoder = new BASE64Encoder();
// your method to retreive the image
if(image == null){
File imagePath = new File("/home/akshay/images.jpeg"); // display alternate image
try {
BufferedImage bufferedImage = ImageIO.read(imagePath);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "png", byteArrayOutputStream);
//Below person is the main object model, and String is the image in string
person.setProfilePhotoString("data:image/png;base64," + base64Encoder.encode(byteArrayOutputStream.toByteArray()));
} catch (IOException e) {
e.printStackTrace();
}
} else{
person1.setProfilePhotoString("data:image/png;base64," + base64Encoder.encode(person1.getProfilephoto()));
}
}
JSP页面:
<form:form action="${showAction}" commandName="person">
<table>
<tr>
<td><img src= "${person.profilePhotoString}" height=100 width=100/>
</tr>
</table>
</form>