简体   繁体   English

通过Servlet在JSP页面上显示图像

[英]Display images on a JSP page through a servlet

I am trying to display images in a Jsp page using Jstl, and image paths are passed on by a servlet. 我正在尝试使用Jstl在Jsp页面中显示图像,并且图像路径由servlet传递。 The Jsp page actually displays only one of the retrieved images and throws a NullPointerException. Jsp页面实际上仅显示检索到的图像之一,并引发NullPointerException。

The Jsp looks like this: Jsp看起来像这样:

<c:forEach items="${images}" var="img">
    <div class="col-md-3">
        <img src="displayImg?imageId=${img.imageId}">
    </div>
</c:forEach>

And servlet doGet method looks like this: 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();
}

I can't understand why this servlet manages to serve one image and fails on others with a NullPointerException when the request parameter is correct. 我不明白为什么当请求参数正确时,此servlet为何能够提供一个图像,而在另一个图像上却出现NullPointerException失败。 I have an impression like it is a concurrency issue because the Jsp displays arbitrary image. 我的印象是这是一个并发问题,因为Jsp显示任意图像。

Any help please? 有什么帮助吗?

Here is the DAO: 这是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;
    }

Solved!! 解决了!! It is weird but I just avoided closing the connection to the database and all my images are displaying correctly with no errors. 这很奇怪,但是我只是避免关闭与数据库的连接,并且所有图像都正确显示,没有错误。 I guess closing the connection after every single DB access is problematic as it could not close at the exact time you want it to but maybe in the middle of another call to the DB. 我想在每次单个数据库访问后关闭连接都是有问题的,因为它无法在您希望的确切时间关闭,但是可能在另一个对数据库的调用中关闭了。 Now I wonder, not closing the connection at all is problematic too. 现在我想知道,根本不关闭连接也是有问题的。 What to do in that case? 在那种情况下该怎么办?

Just read the stack trace: 只需阅读堆栈跟踪:

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)

So, the exception is thrown by 所以,异常是由

rs.getInt("imageId")

which means that there is no column named "imageId" in the result set. 这意味着结果集中没有名为"imageId"列。

You should never use select * . 您永远不要使用select * Use explicit column names, and use these explicit column names when getting data from the result set: 使用显式列名,并在从结果集中获取数据时使用这些显式列名:

select imageId, imagePath, imageType, description, createdOn from ...

Weird as imageId is used as column name in the query, and there is a record, rs.next() . 奇怪的imageId用作查询中的列名,并且有一条记录rs.next() Maybe it is not an int but long, or SQL VARCHAR. 可能不是整数,而是long或SQL VARCHAR。 Maybe MySQL was so overly clever to leave out imageId as this was specified in the WHERE? 也许MySQL太聪明了,无法在WHERE中指定它而忽略imageId? Or somehow in this case you need to use rs.getInt("images.imageId") . 或者在这种情况下,您需要使用rs.getInt("images.imageId")

            img.setImageId(rs.getInt("imageId")); //NPE thrown here

could however be written (circumvented) as 但是可以写成(规避)为

            img.setImageId(mageId);

I would check that there is no devious typo: í (accent), Cyrillic e (if you are East European) or tab char. 我会检查是否没有不正确的错字: í (重音),西里尔字母e (如果您是东欧人)或tab char。 Honestly said your code looks neat, but similar errors happen with much less neat code: ps, ps2, rs, rs2 as fields, playing havoc with concurrent uses and apt to typos. 老实说,您的代码看起来很简洁,但是类似的错误却发生了,而更少的简洁代码:ps,ps2,rs,rs2作为字段,对并发使用造成了破坏,并且容易出现错字。

BTW writing could be done faster with less memory resources: BTW写入可以用更少的内存资源来更快地完成:

Path path = Paths.get(img.getImagePath());
OutputStream out = response.getOutputStream();
Files.copy(path, out);

On the search for errors: 在搜索错误时:

Investigating the error seems the only option: 调查错误似乎是唯一的选择:

ResultSetMetaData meta = rs.getMetaData();
int numberOfColumns = meta.getColumnCount();
for (int i = 1; i <= numberOfColumns; ++i) {
    log(... i, meta.getColumnName(i), meta.getColumnLabel(i) ...);
}

THis answer might not help you completely, as no one I believe understands what you are doing exactly. 这个答案可能无法完全帮助您,因为我相信没人会确切地了解您在做什么。 I am presuming you have a JSP page and a form inside, I can show you how to display the image as a string. 我假设您内部有一个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 page : JSP页面:

<form:form action="${showAction}" commandName="person">
    <table>
 <tr>
            <td><img src= "${person.profilePhotoString}"  height=100 width=100/>
        </tr>
</table>
</form>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM