Servlet 是否适合复合操作



Servlet是非线程安全的,不同请求的方法调用之间可能会丢失状态。

但是,在单个请求期间,我是否可以安全地保持自己的 Servlet 方法之间的状态以实现复合操作?

喜欢这个:

public class MyServlet extends HttpServletRequest {
    private String var;
    void addH() {
        var += "h";
    }
    void addI() {
        var += "i";
    }
    void doGet(...) {
        addH();
        addI();
        // var = "hi"?
    }
}

在这种情况下,即使有并发请求,var也会包含正确的值吗?换句话说,它是否像 EJB 中的无状态 Bean 一样工作?

不,你不能。 就像你说的,servlet 不是线程安全的。 请求所在的"空间"不受保护。 因此,多个线程(以及请求)可以同时命中var。 如果你想要这样一个受保护的"空间",你需要同步doGet()(这当然会破坏并发性)或做一些类似使用ThreadLocal的事情,以便每个线程(以及请求)都有自己单独的实例范围状态副本。

如果你不需要状态在请求之外持久化,你可以在doGet()中创建状态并将其传递给其他方法:

void doGet(...) {
    StringBuilder var = new StringBuilder();
    addH(var);
    addI(var);
    resp.write(var.toString());
}
void addH(StringBuilder var) {
    var.append('h');
}
void addI(StringBuilder var) {
    ver.append('i');
}
public class MyServlet extends HttpServletRequest {
    private String var = "";
    void addH() {
        var += "h";
    }
    void addI(long dontAnswerBefore) {
        while(System.currentTimeMillis() < dontAnswerBefore) {
          // Do nothing 
        }
        var += "i";
    }
    void doGet(...) {
        long now = System.currentTimeMillis();
        addH();
        addI(now + 10_000);
        resp.write(var);
    }
}

这应该让您有 10 秒的时间在两个选项卡或两个不同的浏览器中发出两个请求。

最新更新