Servlet线程安全:实例变量与请求范围属性

时间:2017-08-05 22:07:54

标签: java performance servlets

这是示例代码,说明了实例变量和请求属性的用法:

    @WebServlet(name = "Upload", urlPatterns = {"/upload"})
    @MultipartConfig()
    public class Upload extends HttpServlet {

    private String txt;

    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       try{
        String txt2 = (String) request.getAttribute("txt2");
        //txt and txt2 variables are available for processing.
         ..........
          } finally {
        txt = null;//Prepare variable for next request.
       }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            .....
        request.setAttribute("txt2", someValue);
        //vs
        txt = someValue;

    processRequest(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            .....
     processRequest(request, response);
      }
    }

现在我知道实例变量永远不应该在servlet中声明,因为在concurent请求之间共享相同的servlet。但是请求属性呢?使用它们是否安全?

2 个答案:

答案 0 :(得分:1)

不确定初始化变量是什么意思。在servlet上你或者在哪里?

根据您的需要,可能会涉及到您无法控制合同的API(因为它们不是您的API)。

例如,当过滤器链处理请求时。也许一个过滤器对先前在链中执行的过滤器设置的数据感兴趣。您没有办法在过滤器链合同上传递数据。请求属性可能是一个选项。使用ThreadLocal可能是另一种,但它具有性能影响,并不总是适合。

另一个例子,也许您将一个请求从servlet转发到另一个请求。同样,您将无法选择使用您定义的任何成员变量。

此外,如果您考虑在servlet上添加成员变量,请记住Servlet不是线程安全的。你会怎么做?同步请求处理,每个servlet只处理一个请求?

答案 1 :(得分:1)

您的servlet将在并发请求中服务数百个,每个请求将使用相同的servlet共享实例,因此使用私有实例变量将导致不一致的行为。除非您同步对它的访问,否则会导致访问此私有字段的争用更多,从而减慢响应时间,从而产生瓶颈。

虽然将绑定到单个请求中的属性存储将允许您避免此类问题,而且它旨在克服与您类似的问题。