0

也许我不太了解 servlet 生命周期,但这就是我想要的:我想显示一个由 servlet 生成的页面,比如说 servlet:paginaAmd。在此页面上,我想显示存储在 Web 服务器文件夹中的图像列表。图像的 url 地址类似于:/img/80-80-1-1-1-1-1-1-1-1-1 其中 /img/* 是我用于显示图像的 servlet。

如果我想在浏览器中一次显示一张图像,一切都很好。但是当我想一次放置所有列表时,图像无法正确显示。有时根本不显示,有时显示在错误的位置(位置没有及时改变),有时只显示一些图像。

我怀疑不是所有的 doGet() 方法都被捕获了。

有人可以给我一些建议吗?以下是本教程实现的 servlet 代码:http: //balusc.blogspot.fr/2007/04/imageservlet.html

@WebServlet(name = "ImgDisplay", urlPatterns = {"/img/*"})
public class ImgDisplay extends HttpServlet
{
    private SessionFactory sessionfactory = new AnnotationConfiguration().configure().buildSessionFactory();
    private Query query;
    private String mesajEroare = "";
    private HttpServletRequest _request;
    private HttpServletResponse _response;

    private int width = 0;
    private int height = 0;
    private int idImagine = 0;
    private int format = 0;
    private String titluArticol = "";
    private String numeImagine = "";
    private boolean imgValida = false;

    private int DEFAULT_BUFFER_SIZE = 1024 * 100;

    String fileUploadPath = "";


    @Override
    public void init() throws ServletException {
    }



    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {
        this._request = request;
        this._response = response;


        this.SetVariabile();

        if(imgValida)
        {
            String nImagine = this.GetImageFromDisk();
            this.DisplayImage(nImagine);
        }

    }








    private void SetVariabile()
    {
        String reqUrl = _request.getRequestURL().toString();

        String aUrl[] = reqUrl.split("/");
        String urlImg = aUrl[aUrl.length - 1];

        aUrl = urlImg.split("-");
        try
        {
            this.width = Integer.parseInt(aUrl[0]);
            this.height = Integer.parseInt(aUrl[1]);
            this.idImagine = Integer.parseInt(aUrl[2]);
            this.format = Integer.parseInt(aUrl[3]);
            this.numeImagine = aUrl[aUrl.length - 1];
            this.imgValida = true;
        }
        catch(Exception e)
        {
            this.imgValida = false;
        }

    }




    private String GetImageFromDisk()
    {
        String nImagine;
        //preiau imaginea
        PaginiImagini pa = new PaginiImagini();
        Session session;
        try
        {
            session = sessionfactory.openSession();
            session.beginTransaction();

            query = session.getNamedQuery("PaginiImagini.findByImagineID");
            query.setInteger("imagineID", this.idImagine);
            pa = (PaginiImagini) query.uniqueResult();
            session.getTransaction().commit();
            session.close();
        }
        catch( Exception e )
        {
            this.mesajEroare = "Nu pot citi din baza de date!";
        }

        // citesc imagine de pe disk
        ServletContext sctx = getServletContext();
        this.fileUploadPath = sctx.getInitParameter("file-upload-path");
        String pathImagine = this.fileUploadPath + "/" + Setari.pathImaginiMici;
        if(this.width > Setari.wImagineMica || this.height > Setari.hImagineMica)
        {
            pathImagine = this.fileUploadPath + "/" + Setari.pathImaginiMari;
        }

        nImagine =  pathImagine + "/" + pa.getNumeImaginePeDisc();
        return nImagine;
    }






    private void DisplayImage(String imageToRead) throws FileNotFoundException, IOException
    {
        File image = new File(imageToRead);

        String contentType = getServletContext().getMimeType(image.getName());
        _response.setContentType(contentType);
        _response.setHeader("Content-Length", String.valueOf(image.length()));
        _response.setHeader("Content-Disposition", "inline; filename=\"" + image.getName() + "\"");
        _response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
        _response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
        _response.setDateHeader("Expires", 0); // Proxies.

        // Prepare streams.
        BufferedInputStream input = null;
        BufferedOutputStream output = null;

        try
        {
            // Open streams.
            input = new BufferedInputStream(new FileInputStream(image), DEFAULT_BUFFER_SIZE);
            output = new BufferedOutputStream(_response.getOutputStream(), DEFAULT_BUFFER_SIZE);

            // Write file contents to response.
            byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
            int length;
            while ((length = input.read(buffer)) > 0)
            {
                output.write(buffer, 0, length);
            }
        }
        finally
        {
            // Gently close streams.
            close(output);
            close(input);
        }

    }





    /**
     *
     * @param resource
     */
    private static void close(Closeable resource)
    {
        if (resource != null)
        {
            try
            {
                resource.close();
            }
            catch (IOException e)
            {
                // Do your thing with the exception. Print it, log it or mail
                // it.
                //e.printStackTrace();
            }
        }
    }



}
4

1 回答 1

2

您的 servlet 中存在严重的并发问题。servlet 的单个实例用于为该 servlet 的所有请求提供服务。所以一个servlet应该是无状态的。但你要做的第一件事是

this._request = request;
this._response = response;

这意味着如果对 servlet 发出两个并发请求,您可能让第一个请求设置这两个实例变量,然后第二个请求重置相同的实例变量。因此,第一个图像将作为对第二个请求的响应发送,并且不会发送任何内容作为对第一个请求的响应。这只是可能发生的奇怪事情之一。您还可能有异常和不一致的数据。

不要将请求和响应(以及任何其他状态)存储在实例变量中。将它们从一个方法传递到另一个方法。我没有分析整个代码,但你应该在 servlet 中拥有的唯一实例字段是 sessionFactory 字段。

于 2013-01-27T17:40:59.260 回答