如何在新线程中删除会话属性?



我写web-app。有captcha,保存在会话中。创建captcha后,我启动新线程,其中作为参数,我从servlet传递HttpServletRequest。接下来,转发发生在servlet中。线程休眠1分钟,并从会话中删除captcha属性。但我得到nullpointerexception。我想是因为前锋被叫了。如何删除属性从会话在这个线程?

我代码:

public class RegisterServlet extends HttpServlet {
private CaptchaHandler captchaHandler = new CaptchaHandler();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
captchaHandler.createCaptcha(req, resp);
new MyThread(req).start();
req.getRequestDispatcher("./register.jsp").forward(req, resp);
}
}

public class MyThread extends Thread{

private HttpServletRequest req;
public MyThread(HttpServletRequest req) {
this.req = req;
}
@Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
req.getSession().removeAttribute("captcha");
}
}

HttpServletRequest对象仅在servlet的service方法(它调用doGet方法)中有效。参见Servlet规范的3.13节:

开发人员必须意识到,不建议维护对未在上述作用域之外调用startAsync的请求对象的引用,因为它可能会产生不确定的结果。

大多数servlet容器回收请求对象。这就是getSession()方法给出null的原因。(几乎)所有从HttpServletRequest中获得的对象都具有相同的生命周期,因此将引用传递给HttpSession对象也不是解决方案。

我猜你的最终目的是限制未解决captcha的会话数量。为此,您可以调用:

req.getSession().setMaxInactiveInterval(60);

doGet方法中,并在captcha求解器中恢复更高的值。这样,所有在60秒内没有解决验证码的会话将被删除。

最新更新