【问题标题】:Threadsafe java servlet线程安全的 java servlet
【发布时间】:2010-11-14 18:08:02
【问题描述】:

就线程而言,我需要知道以下代码是否存在任何问题。我一直认为只要不使用类级别变量,线程就不是问题。

public class UploadReferralImage extends HttpServlet
{
    String CLASS_NAME = "UploadReferralImage";

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
   // Not handling Get, service must be invoked via Post.
}

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
    String METHOD_NAME = "doPost";
    LogHelper.debug(PACKAGE_NAME, CLASS_NAME, METHOD_NAME, "Made it to the servlet");
    String reply = upload(request);
    response.setHeader("Content-Type", "text/xml");
    response.getWriter().write(reply);
    response.getWriter().flush();
    response.getWriter().close();
}

public String upload(HttpServletRequest request)
{

    String METHOD_NAME = "upload";
    LogHelper.debug(PACKAGE_NAME, CLASS_NAME, METHOD_NAME, "Inside upload");
    String replyMsg = "Unable to call ImageUpload";

    try
    {
        ObjectInputStream inputFromApplet = new ObjectInputStream(request.getInputStream());
        FileBean fBean = (FileBean) inputFromApplet.readObject();

        inputFromApplet.close();
        LogHelper.debug(PACKAGE_NAME, CLASS_NAME, METHOD_NAME, fBean.getFileName());

        replyMsg = doImageUpload(fBean);

        } 
        catch (IOException e)
    {   
        e.printStackTrace();
            replyMsg = "Exception :" + e.toString();

    } 
        catch (ClassNotFoundException e)
    {
        e.printStackTrace();
            replyMsg = "Exception :" + e.toString();
    }

    return replyMsg;
}

private String doImageUpload(FileBean fBean)
{
       //Save the file and return the response
       SaveCaseClientAgent saveCaseClientAgent = new SaveCaseClientAgent();
       saveCaseClientAgent.save(fBean);
}

【问题讨论】:

  • 看起来不错。你有理由相信它不是吗?
  • 我只是担心上传方法是公开的,不知道为什么我这样做了,必须纠正它。但到目前为止,这没有问题。

标签: java servlets multithreading


【解决方案1】:

你是对的。

只要您不使用类级变量,您的Servlet 就会是线程安全的。

为了安全起见,不妨让你的班级级别Stringfinal:

final String CLASS_NAME = "UploadReferralImage";

【讨论】:

    【解决方案2】:

    通常在 servlet 容器中只有一个 servlet 实例,它一次可重入地服务多个请求。因此,由于竞争条件,使用实例变量将事物从一种方法传递到另一种方法是一个坏主意。

    解决它的最佳(也是最简单)的方法是编写自己的“处理程序”类,您将在每个请求中实例化一次并将所有内容传递给它。在代码中它看起来像这样:

    public void doGet(HttpServletRequest req, HttpServletResponse resp) {
       new MyHandler().doGet(req, resp);
    }
    

    现在在MyHandler 中重用实例变量是最安全的。

    【讨论】:

    • 所以我通过传递 public void doGet(HttpServletRequest req, HttpServletResponse resp) { upload(request); } 可能会导致问题?
    • 没有。在您的情况下,两个不同的请求之间没有共享状态(调用堆栈在线程之间不共享,传递给方法的引用通过堆栈共享)。也就是说,我的“技巧”仍然是一种更清洁、更广泛使用的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-24
    • 2012-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多