0

サーブレットのライフサイクルをよく理解していないかもしれませんが、これが私の望みです: サーブレットによって生成されたページを表示したいと思います。このページでは、Web サーバー上のフォルダーに保存されている画像の一覧を表示します。画像の URL のアドレスは次のようなものです: /img/80-80-1-1-1-1-1-1-1-1-1 ここで、/img/* は画像を表示するための私のサーブレットです。

ブラウザで一度に 1 つの画像を表示したい場合は、すべてうまくいきます。しかし、一度にすべてのリストを表示したい場合、画像が正しく表示されません。まったく表示されない場合もあれば、間違った位置に表示される場合 (時間的に位置が変わらない) がある場合や、一部の画像のみが表示される場合もあります。

どういうわけか、すべての doGet() メソッドがキャッチされているわけではないのではないかと思います。

誰かアドバイスをくれませんか?ここでは、サーブレット コードの魔女がここのチュートリアルで実装されています: 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

サーブレットに重大な並行性の問題があります。サーブレットの単一インスタンスを使用して、このサーブレットへのすべてのリクエストを処理します。したがって、サーブレットはステートレスである必要があります。しかし、あなたが最初にやっていることは、

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

これは、サーブレットに対して 2 つの同時要求が行われた場合、最初の要求でこれら 2 つのインスタンス変数を設定し、次に 2 番目の要求で同じインスタンス変数をリセットする可能性があることを意味します。したがって、最初の画像は 2 番目の要求への応答として送信され、最初の要求への応答としては何も送信されません。そして、これは起こりうる奇妙なことの 1 つにすぎません。また、例外や一貫性のないデータが発生する可能性もあります。

リクエストとレスポンス (およびその他の状態) をインスタンス変数に格納しないでください。それらをメソッドからメソッドに渡します。コード全体を分析したわけではありませんが、サーブレットに含める必要がある唯一のインスタンス フィールドは、sessionFactory フィールドです。

于 2013-01-27T17:40:59.260 に答える